2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: GDI Palette Functions
5 * FILE: win32ss/gdi/ntgdi/palette.c
6 * PROGRAMERS: Jason Filby
15 static UINT SystemPaletteUse
= SYSPAL_NOSTATIC
; /* The program need save the pallete and restore it */
17 PALETTE gpalRGB
, gpalBGR
, gpalRGB555
, gpalRGB565
, *gppalMono
, *gppalDefault
;
18 PPALETTE appalSurfaceDefault
[11];
20 const PALETTEENTRY g_sysPalTemplate
[NB_RESERVED_COLORS
] =
22 // First 10 entries in the system palette
23 // Red Green Blue Flags
24 { 0x00, 0x00, 0x00, PC_SYS_USED
},
25 { 0x80, 0x00, 0x00, PC_SYS_USED
},
26 { 0x00, 0x80, 0x00, PC_SYS_USED
},
27 { 0x80, 0x80, 0x00, PC_SYS_USED
},
28 { 0x00, 0x00, 0x80, PC_SYS_USED
},
29 { 0x80, 0x00, 0x80, PC_SYS_USED
},
30 { 0x00, 0x80, 0x80, PC_SYS_USED
},
31 { 0xc0, 0xc0, 0xc0, PC_SYS_USED
},
32 { 0xc0, 0xdc, 0xc0, PC_SYS_USED
},
33 { 0xa6, 0xca, 0xf0, PC_SYS_USED
},
35 // ... c_min/2 dynamic colorcells
36 // ... gap (for sparse palettes)
37 // ... c_min/2 dynamic colorcells
39 { 0xff, 0xfb, 0xf0, PC_SYS_USED
},
40 { 0xa0, 0xa0, 0xa4, PC_SYS_USED
},
41 { 0x80, 0x80, 0x80, PC_SYS_USED
},
42 { 0xff, 0x00, 0x00, PC_SYS_USED
},
43 { 0x00, 0xff, 0x00, PC_SYS_USED
},
44 { 0xff, 0xff, 0x00, PC_SYS_USED
},
45 { 0x00, 0x00, 0xff, PC_SYS_USED
},
46 { 0xff, 0x00, 0xff, PC_SYS_USED
},
47 { 0x00, 0xff, 0xff, PC_SYS_USED
},
48 { 0xff, 0xff, 0xff, PC_SYS_USED
} // Last 10
51 unsigned short GetNumberOfBits(unsigned int dwMask
)
54 for (wBits
= 0; dwMask
; dwMask
= dwMask
& (dwMask
- 1))
59 // Create the system palette
65 // Create default palette (20 system colors)
66 gppalDefault
= PALETTE_AllocPalWithHandle(PAL_INDEXED
,
70 GDIOBJ_vReferenceObjectByPointer(&gppalDefault
->BaseObject
);
71 PALETTE_UnlockPalette(gppalDefault
);
73 /* palette_size = visual->map_entries; */
75 gpalRGB
.flFlags
= PAL_RGB
;
76 gpalRGB
.RedMask
= RGB(0xFF, 0x00, 0x00);
77 gpalRGB
.GreenMask
= RGB(0x00, 0xFF, 0x00);
78 gpalRGB
.BlueMask
= RGB(0x00, 0x00, 0xFF);
79 gpalRGB
.BaseObject
.ulShareCount
= 1;
80 gpalRGB
.BaseObject
.BaseFlags
= 0 ;
82 gpalBGR
.flFlags
= PAL_BGR
;
83 gpalBGR
.RedMask
= RGB(0x00, 0x00, 0xFF);
84 gpalBGR
.GreenMask
= RGB(0x00, 0xFF, 0x00);
85 gpalBGR
.BlueMask
= RGB(0xFF, 0x00, 0x00);
86 gpalBGR
.BaseObject
.ulShareCount
= 1;
87 gpalBGR
.BaseObject
.BaseFlags
= 0 ;
89 gpalRGB555
.flFlags
= PAL_RGB16_555
| PAL_BITFIELDS
;
90 gpalRGB555
.RedMask
= 0x7C00;
91 gpalRGB555
.GreenMask
= 0x3E0;
92 gpalRGB555
.BlueMask
= 0x1F;
93 gpalRGB555
.BaseObject
.ulShareCount
= 1;
94 gpalRGB555
.BaseObject
.BaseFlags
= 0 ;
96 gpalRGB565
.flFlags
= PAL_RGB16_565
| PAL_BITFIELDS
;
97 gpalRGB565
.RedMask
= 0xF800;
98 gpalRGB565
.GreenMask
= 0x7E0;
99 gpalRGB565
.BlueMask
= 0x1F;
100 gpalRGB565
.BaseObject
.ulShareCount
= 1;
101 gpalRGB565
.BaseObject
.BaseFlags
= 0 ;
103 gppalMono
= PALETTE_AllocPalette(PAL_MONOCHROME
|PAL_INDEXED
, 2, NULL
, 0, 0, 0);
104 PALETTE_vSetRGBColorForIndex(gppalMono
, 0, 0x000000);
105 PALETTE_vSetRGBColorForIndex(gppalMono
, 1, 0xffffff);
107 /* Initialize default surface palettes */
108 appalSurfaceDefault
[BMF_1BPP
] = gppalMono
;
109 appalSurfaceDefault
[BMF_4BPP
] = gppalDefault
;
110 appalSurfaceDefault
[BMF_8BPP
] = gppalDefault
;
111 appalSurfaceDefault
[BMF_16BPP
] = &gpalRGB565
;
112 appalSurfaceDefault
[BMF_24BPP
] = &gpalBGR
;
113 appalSurfaceDefault
[BMF_32BPP
] = &gpalBGR
;
114 appalSurfaceDefault
[BMF_4RLE
] = gppalDefault
;
115 appalSurfaceDefault
[BMF_8RLE
] = gppalDefault
;
116 appalSurfaceDefault
[BMF_JPEG
] = &gpalRGB
;
117 appalSurfaceDefault
[BMF_PNG
] = &gpalRGB
;
119 return STATUS_SUCCESS
;
122 VOID FASTCALL
PALETTE_ValidateFlags(PALETTEENTRY
* lpPalE
, INT size
)
126 lpPalE
[i
].peFlags
= PC_SYS_USED
| (lpPalE
[i
].peFlags
& 0x07);
132 PALETTE_AllocPalette(
135 _In_opt_
const PALETTEENTRY
* pEntries
,
141 ULONG fl
= 0, cjSize
= sizeof(PALETTE
);
143 /* Check if the palette has entries */
144 if (iMode
& PAL_INDEXED
)
146 /* Check color count */
147 if ((cColors
== 0) || (cColors
> 1024)) return NULL
;
149 /* Allocate enough space for the palete entries */
150 cjSize
+= cColors
* sizeof(PALETTEENTRY
);
154 /* There are no palette entries */
157 /* We can use the lookaside list */
158 fl
|= BASEFLAG_LOOKASIDE
;
161 /* Allocate the object (without a handle!) */
162 ppal
= (PPALETTE
)GDIOBJ_AllocateObject(GDIObjType_PAL_TYPE
, cjSize
, fl
);
168 /* Set mode, color count and entry pointer */
169 ppal
->flFlags
= iMode
;
170 ppal
->NumColors
= cColors
;
171 ppal
->IndexedColors
= ppal
->apalColors
;
173 /* Check what kind of palette this is */
174 if (iMode
& PAL_INDEXED
)
176 /* Check if we got a color array */
179 /* Copy the entries */
180 RtlCopyMemory(ppal
->IndexedColors
, pEntries
, cColors
* sizeof(pEntries
[0]));
183 else if (iMode
& PAL_BITFIELDS
)
185 /* Copy the color masks */
186 ppal
->RedMask
= flRed
;
187 ppal
->GreenMask
= flGreen
;
188 ppal
->BlueMask
= flBlue
;
190 /* Check what masks we have and set optimization flags */
191 if ((flRed
== 0x7c00) && (flGreen
== 0x3E0) && (flBlue
== 0x1F))
192 ppal
->flFlags
|= PAL_RGB16_555
;
193 else if ((flRed
== 0xF800) && (flGreen
== 0x7E0) && (flBlue
== 0x1F))
194 ppal
->flFlags
|= PAL_RGB16_565
;
195 else if ((flRed
== 0xFF0000) && (flGreen
== 0xFF00) && (flBlue
== 0xFF))
196 ppal
->flFlags
|= PAL_BGR
;
197 else if ((flRed
== 0xFF) && (flGreen
== 0xFF00) && (flBlue
== 0xFF0000))
198 ppal
->flFlags
|= PAL_RGB
;
206 PALETTE_AllocPalWithHandle(
209 _In_opt_
const PALETTEENTRY
* pEntries
,
216 /* Allocate the palette without a handle */
217 ppal
= PALETTE_AllocPalette(iMode
, cColors
, pEntries
, flRed
, flGreen
, flBlue
);
218 if (!ppal
) return NULL
;
220 /* Insert the palette into the handle table */
221 if (!GDIOBJ_hInsertObject(&ppal
->BaseObject
, GDI_OBJ_HMGR_POWNED
))
223 DPRINT1("Could not insert palette into handle table.\n");
224 GDIOBJ_vFreeObject(&ppal
->BaseObject
);
233 PALETTE_vCleanup(PVOID ObjectBody
)
235 PPALETTE pPal
= (PPALETTE
)ObjectBody
;
236 if (pPal
->IndexedColors
&& pPal
->IndexedColors
!= pPal
->apalColors
)
238 ExFreePoolWithTag(pPal
->IndexedColors
, TAG_PALETTE
);
244 PALETTE_GetObject(PPALETTE ppal
, INT cbCount
, LPLOGBRUSH lpBuffer
)
251 if ((UINT
)cbCount
< sizeof(WORD
)) return 0;
252 *((WORD
*)lpBuffer
) = (WORD
)ppal
->NumColors
;
258 PALETTE_ulGetNearestPaletteIndex(PALETTE
* ppal
, ULONG iColor
)
260 ULONG ulDiff
, ulColorDiff
, ulMinimalDiff
= 0xFFFFFF;
261 ULONG i
, ulBestIndex
= 0;
262 PALETTEENTRY peColor
= *(PPALETTEENTRY
)&iColor
;
264 /* Loop all palette entries */
265 for (i
= 0; i
< ppal
->NumColors
; i
++)
267 /* Calculate distance in the color cube */
268 ulDiff
= peColor
.peRed
- ppal
->IndexedColors
[i
].peRed
;
269 ulColorDiff
= ulDiff
* ulDiff
;
270 ulDiff
= peColor
.peGreen
- ppal
->IndexedColors
[i
].peGreen
;
271 ulColorDiff
+= ulDiff
* ulDiff
;
272 ulDiff
= peColor
.peBlue
- ppal
->IndexedColors
[i
].peBlue
;
273 ulColorDiff
+= ulDiff
* ulDiff
;
275 /* Check for a better match */
276 if (ulColorDiff
< ulMinimalDiff
)
279 ulMinimalDiff
= ulColorDiff
;
281 /* Break on exact match */
282 if (ulMinimalDiff
== 0) break;
291 PALETTE_ulGetNearestBitFieldsIndex(PALETTE
* ppal
, ULONG ulColor
)
295 // FIXME: HACK, should be stored already
296 ppal
->ulRedShift
= CalculateShift(RGB(0xff,0,0), ppal
->RedMask
);
297 ppal
->ulGreenShift
= CalculateShift(RGB(0,0xff,0), ppal
->GreenMask
);
298 ppal
->ulBlueShift
= CalculateShift(RGB(0,0,0xff), ppal
->BlueMask
);
300 ulNewColor
= _rotl(ulColor
, ppal
->ulRedShift
) & ppal
->RedMask
;
301 ulNewColor
|= _rotl(ulColor
, ppal
->ulGreenShift
) & ppal
->GreenMask
;
302 ulNewColor
|= _rotl(ulColor
, ppal
->ulBlueShift
) & ppal
->BlueMask
;
309 PALETTE_ulGetNearestIndex(PALETTE
* ppal
, ULONG ulColor
)
311 if (ppal
->flFlags
& PAL_INDEXED
) // Use fl & PALINDEXED
312 return PALETTE_ulGetNearestPaletteIndex(ppal
, ulColor
);
314 return PALETTE_ulGetNearestBitFieldsIndex(ppal
, ulColor
);
319 PALETTE_vGetBitMasks(PPALETTE ppal
, PULONG pulColors
)
323 if (ppal
->flFlags
& PAL_INDEXED
|| ppal
->flFlags
& PAL_RGB
)
325 pulColors
[0] = RGB(0xFF, 0x00, 0x00);
326 pulColors
[1] = RGB(0x00, 0xFF, 0x00);
327 pulColors
[2] = RGB(0x00, 0x00, 0xFF);
329 else if (ppal
->flFlags
& PAL_BGR
)
331 pulColors
[0] = RGB(0x00, 0x00, 0xFF);
332 pulColors
[1] = RGB(0x00, 0xFF, 0x00);
333 pulColors
[2] = RGB(0xFF, 0x00, 0x00);
335 else if (ppal
->flFlags
& PAL_BITFIELDS
)
337 pulColors
[0] = ppal
->RedMask
;
338 pulColors
[1] = ppal
->GreenMask
;
339 pulColors
[2] = ppal
->BlueMask
;
345 ColorCorrection(PPALETTE PalGDI
, PPALETTEENTRY PaletteEntry
, ULONG Colors
)
347 PPDEVOBJ ppdev
= (PPDEVOBJ
)PalGDI
->hPDev
;
351 if (ppdev
->flFlags
& PDEV_GAMMARAMP_TABLE
)
354 PGAMMARAMP GammaRamp
= (PGAMMARAMP
)ppdev
->pvGammaRamp
;
355 for ( i
= 0; i
< Colors
; i
++)
357 PaletteEntry
[i
].peRed
+= GammaRamp
->Red
[i
];
358 PaletteEntry
[i
].peGreen
+= GammaRamp
->Green
[i
];
359 PaletteEntry
[i
].peBlue
+= GammaRamp
->Blue
[i
];
365 /** Display Driver Interface **************************************************/
383 ppal
= PALETTE_AllocPalette(iMode
, cColors
, (PPALETTEENTRY
)pulColors
, flRed
, flGreen
, flBlue
);
384 if (!ppal
) return NULL
;
386 hpal
= GDIOBJ_hInsertObject(&ppal
->BaseObject
, GDI_OBJ_HMGR_PUBLIC
);
389 DPRINT1("Could not insert palette into handle table.\n");
390 GDIOBJ_vFreeObject(&ppal
->BaseObject
);
394 PALETTE_UnlockPalette(ppal
);
403 EngDeletePalette(IN HPALETTE hpal
)
407 ppal
= PALETTE_ShareLockPalette(hpal
);
408 if (!ppal
) return FALSE
;
410 GDIOBJ_vDeleteObject(&ppal
->BaseObject
);
420 PALOBJ_cGetColors(PALOBJ
*PalObj
, ULONG Start
, ULONG Colors
, ULONG
*PaletteEntry
)
424 PalGDI
= (PALETTE
*)PalObj
;
426 if (Start
>= PalGDI
->NumColors
)
429 Colors
= min(Colors
, PalGDI
->NumColors
- Start
);
431 /* NOTE: PaletteEntry ULONGs are in the same order as PALETTEENTRY. */
432 RtlCopyMemory(PaletteEntry
, PalGDI
->IndexedColors
+ Start
, sizeof(ULONG
) * Colors
);
434 if (PalGDI
->flFlags
& PAL_GAMMACORRECTION
)
435 ColorCorrection(PalGDI
, (PPALETTEENTRY
)PaletteEntry
, Colors
);
441 /** Systemcall Interface ******************************************************/
445 GreCreatePaletteInternal(
446 IN LPLOGPALETTE pLogPal
,
449 HPALETTE hpal
= NULL
;
452 pLogPal
->palNumEntries
= cEntries
;
453 ppal
= PALETTE_AllocPalWithHandle(PAL_INDEXED
,
455 pLogPal
->palPalEntry
,
460 PALETTE_ValidateFlags(ppal
->IndexedColors
, ppal
->NumColors
);
462 hpal
= ppal
->BaseObject
.hHmgr
;
463 PALETTE_UnlockPalette(ppal
);
474 NtGdiCreatePaletteInternal(
475 IN LPLOGPALETTE plogpalUser
,
478 HPALETTE hpal
= NULL
;
482 ppal
= PALETTE_AllocPalWithHandle(PAL_INDEXED
, cEntries
, NULL
, 0, 0, 0);
488 cjSize
= FIELD_OFFSET(LOGPALETTE
, palPalEntry
[cEntries
]);
492 ProbeForRead(plogpalUser
, cjSize
, 1);
494 for (i
= 0; i
< cEntries
; i
++)
496 ppal
->IndexedColors
[i
] = plogpalUser
->palPalEntry
[i
];
499 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
501 GDIOBJ_vDeleteObject(&ppal
->BaseObject
);
502 _SEH2_YIELD(return NULL
);
506 PALETTE_ValidateFlags(ppal
->IndexedColors
, cEntries
);
507 hpal
= ppal
->BaseObject
.hHmgr
;
508 PALETTE_UnlockPalette(ppal
);
515 NtGdiCreateHalftonePalette(HDC hDC
)
518 PALETTEENTRY PalEntries
[256];
521 HPALETTE hpal
= NULL
;
523 pdc
= DC_LockDc(hDC
);
526 EngSetLastError(ERROR_INVALID_HANDLE
);
530 RtlZeroMemory(PalEntries
, sizeof(PalEntries
));
532 /* First and last ten entries are default ones */
533 for (i
= 0; i
< 10; i
++)
535 PalEntries
[i
].peRed
= g_sysPalTemplate
[i
].peRed
;
536 PalEntries
[i
].peGreen
= g_sysPalTemplate
[i
].peGreen
;
537 PalEntries
[i
].peBlue
= g_sysPalTemplate
[i
].peBlue
;
539 PalEntries
[246 + i
].peRed
= g_sysPalTemplate
[10 + i
].peRed
;
540 PalEntries
[246 + i
].peGreen
= g_sysPalTemplate
[10 + i
].peGreen
;
541 PalEntries
[246 + i
].peBlue
= g_sysPalTemplate
[10 + i
].peBlue
;
544 ppal
= PALETTE_ShareLockPalette(pdc
->dclevel
.hpal
);
545 if (ppal
&& (ppal
->flFlags
& PAL_INDEXED
))
547 /* FIXME: optimize the palette for the current palette */
552 for (r
= 0; r
< 6; r
++)
554 for (g
= 0; g
< 6; g
++)
556 for (b
= 0; b
< 6; b
++)
558 i
= r
+ g
*6 + b
*36 + 10;
559 PalEntries
[i
].peRed
= r
* 51;
560 PalEntries
[i
].peGreen
= g
* 51;
561 PalEntries
[i
].peBlue
= b
* 51;
566 for (i
= 216; i
< 246; i
++)
568 int v
= (i
- 216) << 3;
569 PalEntries
[i
].peRed
= v
;
570 PalEntries
[i
].peGreen
= v
;
571 PalEntries
[i
].peBlue
= v
;
576 PALETTE_ShareUnlockPalette(ppal
);
580 ppal
= PALETTE_AllocPalWithHandle(PAL_INDEXED
, 256, PalEntries
, 0, 0, 0);
583 hpal
= ppal
->BaseObject
.hHmgr
;
584 PALETTE_UnlockPalette(ppal
);
596 /* PALOBJ *palPtr = (PALOBJ*)AccessUserObject(hPal);
597 UINT cPrevEnt, prevVer;
598 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
599 XLATEOBJ *XlateObj = NULL;
601 if(!palPtr) return FALSE;
602 cPrevEnt = palPtr->logpalette->palNumEntries;
603 prevVer = palPtr->logpalette->palVersion;
604 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
605 size += sizeof(int*) + sizeof(GDIOBJHDR);
606 XlateObj = palPtr->logicalToSystem;
608 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
612 XLATEOBJ *NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
613 if(NewXlateObj == NULL)
615 ERR("Can not resize logicalToSystem -- out of memory!");
616 GDI_ReleaseObj( hPal );
619 palPtr->logicalToSystem = NewXlateObj;
622 if(cEntries > cPrevEnt)
624 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
625 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
626 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
628 palPtr->logpalette->palNumEntries = cEntries;
629 palPtr->logpalette->palVersion = prevVer;
630 // GDI_ReleaseObj( hPal );
639 NtGdiGetColorAdjustment(
641 LPCOLORADJUSTMENT pca
)
649 NtGdiSetColorAdjustment(
651 LPCOLORADJUSTMENT pca
)
659 NtGdiGetNearestColor(
663 COLORREF nearest
= CLR_INVALID
;
672 EngSetLastError(ERROR_INVALID_HANDLE
);
676 /// FIXME: shouldn't dereference pSurface while the PDEV is not locked
677 if(dc
->dclevel
.pSurface
== NULL
)
680 ppal
= dc
->dclevel
.pSurface
->ppal
;
682 /* Translate the color to the DC format */
683 Color
= TranslateCOLORREF(dc
, Color
);
685 /* XLATE it back to RGB color space */
686 EXLATEOBJ_vInitialize(&exlo
,
690 RGB(0xff, 0xff, 0xff),
693 nearest
= XLATEOBJ_iXlate(&exlo
.xlo
, Color
);
695 EXLATEOBJ_vCleanup(&exlo
);
705 NtGdiGetNearestPaletteIndex(
709 PPALETTE ppal
= PALETTE_ShareLockPalette(hpal
);
714 if (ppal
->flFlags
& PAL_INDEXED
)
716 /* Return closest match for the given RGB color */
717 index
= PALETTE_ulGetNearestPaletteIndex(ppal
, crColor
);
719 // else SetLastError ?
720 PALETTE_ShareUnlockPalette(ppal
);
728 IntGdiRealizePalette(HDC hDC
)
732 PALETTE
*ppalSurf
, *ppalDC
;
734 pdc
= DC_LockDc(hDC
);
737 EngSetLastError(ERROR_INVALID_HANDLE
);
741 if (!pdc
->dclevel
.pSurface
)
746 if (pdc
->dctype
== DCTYPE_DIRECT
)
748 static BOOL g_WarnedOnce
= FALSE
;
757 /// FIXME: shouldn't dereference pSurface while the PDEV is not locked
758 ppalSurf
= pdc
->dclevel
.pSurface
->ppal
;
759 ppalDC
= pdc
->dclevel
.ppal
;
761 if (!(ppalSurf
->flFlags
& PAL_INDEXED
))
767 ASSERT(ppalDC
->flFlags
& PAL_INDEXED
);
769 // FIXME: Should we resize ppalSurf if it's too small?
770 realize
= (ppalDC
->NumColors
< ppalSurf
->NumColors
) ? ppalDC
->NumColors
: ppalSurf
->NumColors
;
772 for (i
=0; i
<realize
; i
++)
774 InterlockedExchange((LONG
*)&ppalSurf
->IndexedColors
[i
], *(LONG
*)&ppalDC
->IndexedColors
[i
]);
783 IntAnimatePalette(HPALETTE hPal
,
786 CONST PPALETTEENTRY PaletteColors
)
790 if( hPal
!= NtGdiGetStockObject(DEFAULT_PALETTE
) )
794 const PALETTEENTRY
*pptr
= PaletteColors
;
796 palPtr
= PALETTE_ShareLockPalette(hPal
);
797 if (!palPtr
) return FALSE
;
799 pal_entries
= palPtr
->NumColors
;
800 if (StartIndex
>= pal_entries
)
802 PALETTE_ShareUnlockPalette(palPtr
);
805 if (StartIndex
+NumEntries
> pal_entries
) NumEntries
= pal_entries
- StartIndex
;
807 for (NumEntries
+= StartIndex
; StartIndex
< NumEntries
; StartIndex
++, pptr
++)
809 /* According to MSDN, only animate PC_RESERVED colours */
810 if (palPtr
->IndexedColors
[StartIndex
].peFlags
& PC_RESERVED
)
812 memcpy( &palPtr
->IndexedColors
[StartIndex
], pptr
,
813 sizeof(PALETTEENTRY
) );
815 PALETTE_ValidateFlags(&palPtr
->IndexedColors
[StartIndex
], 1);
819 PALETTE_ShareUnlockPalette(palPtr
);
822 /* FIXME: This is completely broken! We cannot call UserGetDesktopWindow
823 without first acquiring the USER lock. But the whole process here is
824 screwed anyway. Instead of messing with the desktop DC, we need to
825 check, whether the palette is associated with a PDEV and whether that
826 PDEV supports palette operations. Then we need to call pfnDrvSetPalette.
827 But since IntGdiRealizePalette() is not even implemented for direct DCs,
828 we can as well just do nothing, that will at least not ASSERT!
829 I leave the whole thing here, to scare people away, who want to "fix" it. */
831 /* Immediately apply the new palette if current window uses it */
832 Wnd
= UserGetDesktopWindow();
833 hDC
= UserGetWindowDC(Wnd
);
837 if (dc
->dclevel
.hpal
== hPal
)
840 IntGdiRealizePalette(hDC
);
845 UserReleaseDC(Wnd
,hDC
, FALSE
);
852 IntGetPaletteEntries(
861 palGDI
= (PPALETTE
) PALETTE_ShareLockPalette(hpal
);
867 numEntries
= palGDI
->NumColors
;
870 if (numEntries
< StartIndex
+ Entries
)
872 Entries
= numEntries
- StartIndex
;
874 if (numEntries
<= StartIndex
)
876 PALETTE_ShareUnlockPalette(palGDI
);
879 memcpy(pe
, palGDI
->IndexedColors
+ StartIndex
, Entries
* sizeof(PALETTEENTRY
));
883 Entries
= numEntries
;
886 PALETTE_ShareUnlockPalette(palGDI
);
891 IntGetSystemPaletteEntries(HDC hDC
,
896 PPALETTE palGDI
= NULL
;
898 UINT EntriesSize
= 0;
903 EngSetLastError(ERROR_INVALID_PARAMETER
);
909 EntriesSize
= Entries
* sizeof(pe
[0]);
910 if (Entries
!= EntriesSize
/ sizeof(pe
[0]))
912 /* Integer overflow! */
913 EngSetLastError(ERROR_INVALID_PARAMETER
);
918 if (!(dc
= DC_LockDc(hDC
)))
920 EngSetLastError(ERROR_INVALID_HANDLE
);
924 palGDI
= PALETTE_ShareLockPalette(dc
->dclevel
.hpal
);
929 if (StartIndex
>= palGDI
->NumColors
)
931 else if (Entries
> palGDI
->NumColors
- StartIndex
)
932 Entries
= palGDI
->NumColors
- StartIndex
;
935 palGDI
->IndexedColors
+ StartIndex
,
936 Entries
* sizeof(pe
[0]));
942 Ret
= dc
->ppdev
->gdiinfo
.ulNumPalReg
;
947 PALETTE_ShareUnlockPalette(palGDI
);
957 IntSetPaletteEntries(
961 CONST LPPALETTEENTRY pe
)
966 if ((UINT_PTR
)hpal
& GDI_HANDLE_STOCK_MASK
)
971 palGDI
= PALETTE_ShareLockPalette(hpal
);
972 if (!palGDI
) return 0;
974 numEntries
= palGDI
->NumColors
;
975 if (Start
>= numEntries
)
977 PALETTE_ShareUnlockPalette(palGDI
);
980 if (numEntries
< Start
+ Entries
)
982 Entries
= numEntries
- Start
;
984 memcpy(palGDI
->IndexedColors
+ Start
, pe
, Entries
* sizeof(PALETTEENTRY
));
985 PALETTE_ShareUnlockPalette(palGDI
);
1001 PPALETTE ppal
= NULL
;
1002 ULONG i
, iEndIndex
, iResult
= 0;
1005 pdc
= DC_LockDc(hdc
);
1011 /* Get the surface from the DC */
1012 psurf
= pdc
->dclevel
.pSurface
;
1014 /* Check if we have the default surface */
1017 /* Use a mono palette */
1021 else if (psurf
->SurfObj
.iType
== STYPE_BITMAP
)
1023 /* Get the palette of the surface */
1027 /* Check if this is an indexed palette and the range is ok */
1028 if (ppal
&& (ppal
->flFlags
& PAL_INDEXED
) &&
1029 (iStartIndex
< ppal
->NumColors
))
1031 /* Calculate the end of the operation */
1032 iEndIndex
= min(iStartIndex
+ cEntries
, ppal
->NumColors
);
1034 /* Check what operation to perform */
1037 /* Loop all colors and set the palette entries */
1038 for (i
= iStartIndex
; i
< iEndIndex
; i
++, prgbColors
++)
1040 ppal
->IndexedColors
[i
].peRed
= prgbColors
->rgbRed
;
1041 ppal
->IndexedColors
[i
].peGreen
= prgbColors
->rgbGreen
;
1042 ppal
->IndexedColors
[i
].peBlue
= prgbColors
->rgbBlue
;
1045 /* Mark the dc brushes invalid */
1046 pdc
->pdcattr
->ulDirty_
|= DIRTY_FILL
|DIRTY_LINE
|
1047 DIRTY_BACKGROUND
|DIRTY_TEXT
;
1051 /* Loop all colors and get the palette entries */
1052 for (i
= iStartIndex
; i
< iEndIndex
; i
++, prgbColors
++)
1054 prgbColors
->rgbRed
= ppal
->IndexedColors
[i
].peRed
;
1055 prgbColors
->rgbGreen
= ppal
->IndexedColors
[i
].peGreen
;
1056 prgbColors
->rgbBlue
= ppal
->IndexedColors
[i
].peBlue
;
1057 prgbColors
->rgbReserved
= 0;
1061 /* Calculate how many entries were modified */
1062 iResult
= iEndIndex
- iStartIndex
;
1078 _When_(bInbound
!=0, _In_reads_bytes_(cEntries
*sizeof(PALETTEENTRY
)))
1079 _When_(bInbound
==0, _Out_writes_bytes_(cEntries
*sizeof(PALETTEENTRY
))) LPVOID pUnsafeEntries
,
1084 LPVOID pEntries
= NULL
;
1092 cjSize
= cEntries
* sizeof(PALETTEENTRY
);
1093 pEntries
= ExAllocatePoolWithTag(PagedPool
, cjSize
, TAG_PALETTE
);
1101 ProbeForRead(pUnsafeEntries
, cjSize
, 1);
1102 memcpy(pEntries
, pUnsafeEntries
, cjSize
);
1104 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1106 ExFreePoolWithTag(pEntries
, TAG_PALETTE
);
1107 _SEH2_YIELD(return 0);
1113 /* Zero it out, so we don't accidentally leak kernel data */
1114 RtlZeroMemory(pEntries
, cjSize
);
1123 ret
= IntAnimatePalette((HPALETTE
)hObj
, iStart
, cEntries
, (CONST PPALETTEENTRY
)pEntries
);
1126 case GdiPalSetEntries
:
1128 ret
= IntSetPaletteEntries((HPALETTE
)hObj
, iStart
, cEntries
, (CONST LPPALETTEENTRY
)pEntries
);
1131 case GdiPalGetEntries
:
1132 ret
= IntGetPaletteEntries((HPALETTE
)hObj
, iStart
, cEntries
, (LPPALETTEENTRY
)pEntries
);
1135 case GdiPalGetSystemEntries
:
1136 ret
= IntGetSystemPaletteEntries((HDC
)hObj
, iStart
, cEntries
, (LPPALETTEENTRY
)pEntries
);
1139 case GdiPalSetColorTable
:
1141 ret
= GreGetSetColorTable((HDC
)hObj
, iStart
, cEntries
, (RGBQUAD
*)pEntries
, TRUE
);
1144 case GdiPalGetColorTable
:
1146 ret
= GreGetSetColorTable((HDC
)hObj
, iStart
, cEntries
, (RGBQUAD
*)pEntries
, FALSE
);
1152 if (!bInbound
&& (ret
> 0))
1154 cjSize
= min(cEntries
, ret
) * sizeof(PALETTEENTRY
);
1157 ProbeForWrite(pUnsafeEntries
, cjSize
, 1);
1158 memcpy(pUnsafeEntries
, pEntries
, cjSize
);
1160 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1166 ExFreePoolWithTag(pEntries
, TAG_PALETTE
);
1173 NtGdiSetSystemPaletteUse(HDC hDC
, UINT Usage
)
1175 UINT old
= SystemPaletteUse
;
1177 /* Device doesn't support colour palettes */
1178 if (!(NtGdiGetDeviceCaps(hDC
, RASTERCAPS
) & RC_PALETTE
)) {
1179 return SYSPAL_ERROR
;
1184 case SYSPAL_NOSTATIC
:
1185 case SYSPAL_NOSTATIC256
:
1187 SystemPaletteUse
= Usage
;
1200 NtGdiGetSystemPaletteUse(HDC hDC
)
1202 return SystemPaletteUse
;
1207 NtGdiUpdateColors(HDC hDC
)
1210 BOOL calledFromUser
, ret
;
1211 USER_REFERENCE_ENTRY Ref
;
1213 calledFromUser
= UserIsEntered();
1215 if (!calledFromUser
){
1216 UserEnterExclusive();
1219 Wnd
= UserGetWindowObject(IntWindowFromDC(hDC
));
1222 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1224 if (!calledFromUser
){
1231 UserRefObjectCo(Wnd
, &Ref
);
1232 ret
= co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_INVALIDATE
);
1233 UserDerefObjectCo(Wnd
);
1235 if (!calledFromUser
){
1244 NtGdiUnrealizeObject(HGDIOBJ hgdiobj
)
1250 ((UINT_PTR
)hgdiobj
& GDI_HANDLE_STOCK_MASK
) ||
1251 !GDI_HANDLE_IS_TYPE(hgdiobj
, GDI_OBJECT_TYPE_PALETTE
) )
1254 palGDI
= PALETTE_ShareLockPalette(hgdiobj
);
1255 if (!palGDI
) return FALSE
;
1258 // Need to do something!!!
1259 // Zero out Current and Old Translated pointers?
1262 PALETTE_ShareUnlockPalette(palGDI
);