2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: GDI Palette Functions
5 * FILE: subsystems/win32/win32k/objects/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
,
68 (PULONG
)g_sysPalTemplate
,
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_ PULONG pulColors
,
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
,
182 cColors
* sizeof(ULONG
));
185 else if (iMode
& PAL_BITFIELDS
)
187 /* Copy the color masks */
188 ppal
->RedMask
= flRed
;
189 ppal
->GreenMask
= flGreen
;
190 ppal
->BlueMask
= flBlue
;
192 /* Check what masks we have and set optimization flags */
193 if ((flRed
== 0x7c00) && (flGreen
== 0x3E0) && (flBlue
== 0x1F))
194 ppal
->flFlags
|= PAL_RGB16_555
;
195 else if ((flRed
== 0xF800) && (flGreen
== 0x7E0) && (flBlue
== 0x1F))
196 ppal
->flFlags
|= PAL_RGB16_565
;
197 else if ((flRed
== 0xFF0000) && (flGreen
== 0xFF00) && (flBlue
== 0xFF))
198 ppal
->flFlags
|= PAL_BGR
;
199 else if ((flRed
== 0xFF) && (flGreen
== 0xFF00) && (flBlue
== 0xFF0000))
200 ppal
->flFlags
|= PAL_RGB
;
208 PALETTE_AllocPalWithHandle(
211 _In_opt_ PULONG pulColors
,
218 /* Allocate the palette without a handle */
219 ppal
= PALETTE_AllocPalette(iMode
, cColors
, pulColors
, flRed
, flGreen
, flBlue
);
220 if (!ppal
) return NULL
;
222 /* Insert the palette into the handle table */
223 if (!GDIOBJ_hInsertObject(&ppal
->BaseObject
, GDI_OBJ_HMGR_POWNED
))
225 DPRINT1("Could not insert palette into handle table.\n");
226 GDIOBJ_vFreeObject(&ppal
->BaseObject
);
235 PALETTE_Cleanup(PVOID ObjectBody
)
237 PPALETTE pPal
= (PPALETTE
)ObjectBody
;
238 if (pPal
->IndexedColors
&& pPal
->IndexedColors
!= pPal
->apalColors
)
240 ExFreePoolWithTag(pPal
->IndexedColors
, TAG_PALETTE
);
248 PALETTE_GetObject(PPALETTE ppal
, INT cbCount
, LPLOGBRUSH lpBuffer
)
255 if ((UINT
)cbCount
< sizeof(WORD
)) return 0;
256 *((WORD
*)lpBuffer
) = (WORD
)ppal
->NumColors
;
262 PALETTE_ulGetNearestPaletteIndex(PALETTE
* ppal
, ULONG iColor
)
264 ULONG ulDiff
, ulColorDiff
, ulMinimalDiff
= 0xFFFFFF;
265 ULONG i
, ulBestIndex
= 0;
266 PALETTEENTRY peColor
= *(PPALETTEENTRY
)&iColor
;
268 /* Loop all palette entries */
269 for (i
= 0; i
< ppal
->NumColors
; i
++)
271 /* Calculate distance in the color cube */
272 ulDiff
= peColor
.peRed
- ppal
->IndexedColors
[i
].peRed
;
273 ulColorDiff
= ulDiff
* ulDiff
;
274 ulDiff
= peColor
.peGreen
- ppal
->IndexedColors
[i
].peGreen
;
275 ulColorDiff
+= ulDiff
* ulDiff
;
276 ulDiff
= peColor
.peBlue
- ppal
->IndexedColors
[i
].peBlue
;
277 ulColorDiff
+= ulDiff
* ulDiff
;
279 /* Check for a better match */
280 if (ulColorDiff
< ulMinimalDiff
)
283 ulMinimalDiff
= ulColorDiff
;
285 /* Break on exact match */
286 if (ulMinimalDiff
== 0) break;
295 PALETTE_ulGetNearestBitFieldsIndex(PALETTE
* ppal
, ULONG ulColor
)
299 // FIXME: HACK, should be stored already
300 ppal
->ulRedShift
= CalculateShift(RGB(0xff,0,0), ppal
->RedMask
);
301 ppal
->ulGreenShift
= CalculateShift(RGB(0,0xff,0), ppal
->GreenMask
);
302 ppal
->ulBlueShift
= CalculateShift(RGB(0,0,0xff), ppal
->BlueMask
);
304 ulNewColor
= _rotl(ulColor
, ppal
->ulRedShift
) & ppal
->RedMask
;
305 ulNewColor
|= _rotl(ulColor
, ppal
->ulGreenShift
) & ppal
->GreenMask
;
306 ulNewColor
|= _rotl(ulColor
, ppal
->ulBlueShift
) & ppal
->BlueMask
;
313 PALETTE_ulGetNearestIndex(PALETTE
* ppal
, ULONG ulColor
)
315 if (ppal
->flFlags
& PAL_INDEXED
) // Use fl & PALINDEXED
316 return PALETTE_ulGetNearestPaletteIndex(ppal
, ulColor
);
318 return PALETTE_ulGetNearestBitFieldsIndex(ppal
, ulColor
);
323 PALETTE_vGetBitMasks(PPALETTE ppal
, PULONG pulColors
)
327 if (ppal
->flFlags
& PAL_INDEXED
|| ppal
->flFlags
& PAL_RGB
)
329 pulColors
[0] = RGB(0xFF, 0x00, 0x00);
330 pulColors
[1] = RGB(0x00, 0xFF, 0x00);
331 pulColors
[2] = RGB(0x00, 0x00, 0xFF);
333 else if (ppal
->flFlags
& PAL_BGR
)
335 pulColors
[0] = RGB(0x00, 0x00, 0xFF);
336 pulColors
[1] = RGB(0x00, 0xFF, 0x00);
337 pulColors
[2] = RGB(0xFF, 0x00, 0x00);
339 else if (ppal
->flFlags
& PAL_BITFIELDS
)
341 pulColors
[0] = ppal
->RedMask
;
342 pulColors
[1] = ppal
->GreenMask
;
343 pulColors
[2] = ppal
->BlueMask
;
349 ColorCorrection(PPALETTE PalGDI
, PPALETTEENTRY PaletteEntry
, ULONG Colors
)
351 PPDEVOBJ ppdev
= (PPDEVOBJ
)PalGDI
->hPDev
;
355 if (ppdev
->flFlags
& PDEV_GAMMARAMP_TABLE
)
358 PGAMMARAMP GammaRamp
= (PGAMMARAMP
)ppdev
->pvGammaRamp
;
359 for ( i
= 0; i
< Colors
; i
++)
361 PaletteEntry
[i
].peRed
+= GammaRamp
->Red
[i
];
362 PaletteEntry
[i
].peGreen
+= GammaRamp
->Green
[i
];
363 PaletteEntry
[i
].peBlue
+= GammaRamp
->Blue
[i
];
369 /** Display Driver Interface **************************************************/
387 ppal
= PALETTE_AllocPalette(iMode
, cColors
, pulColors
, flRed
, flGreen
, flBlue
);
388 if (!ppal
) return NULL
;
390 hpal
= GDIOBJ_hInsertObject(&ppal
->BaseObject
, GDI_OBJ_HMGR_PUBLIC
);
393 DPRINT1("Could not insert palette into handle table.\n");
394 GDIOBJ_vFreeObject(&ppal
->BaseObject
);
398 PALETTE_UnlockPalette(ppal
);
407 EngDeletePalette(IN HPALETTE hpal
)
411 ppal
= PALETTE_ShareLockPalette(hpal
);
412 if (!ppal
) return FALSE
;
414 GDIOBJ_vDeleteObject(&ppal
->BaseObject
);
424 PALOBJ_cGetColors(PALOBJ
*PalObj
, ULONG Start
, ULONG Colors
, ULONG
*PaletteEntry
)
428 PalGDI
= (PALETTE
*)PalObj
;
430 if (Start
>= PalGDI
->NumColors
)
433 Colors
= min(Colors
, PalGDI
->NumColors
- Start
);
435 /* NOTE: PaletteEntry ULONGs are in the same order as PALETTEENTRY. */
436 RtlCopyMemory(PaletteEntry
, PalGDI
->IndexedColors
+ Start
, sizeof(ULONG
) * Colors
);
438 if (PalGDI
->flFlags
& PAL_GAMMACORRECTION
)
439 ColorCorrection(PalGDI
, (PPALETTEENTRY
)PaletteEntry
, Colors
);
445 /** Systemcall Interface ******************************************************/
449 GreCreatePaletteInternal(
450 IN LPLOGPALETTE pLogPal
,
453 HPALETTE hpal
= NULL
;
456 pLogPal
->palNumEntries
= cEntries
;
457 ppal
= PALETTE_AllocPalWithHandle(PAL_INDEXED
,
459 (PULONG
)pLogPal
->palPalEntry
,
464 PALETTE_ValidateFlags(ppal
->IndexedColors
, ppal
->NumColors
);
466 hpal
= ppal
->BaseObject
.hHmgr
;
467 PALETTE_UnlockPalette(ppal
);
478 NtGdiCreatePaletteInternal(
479 IN LPLOGPALETTE plogpalUser
,
482 HPALETTE hpal
= NULL
;
486 ppal
= PALETTE_AllocPalWithHandle(PAL_INDEXED
, cEntries
, NULL
, 0, 0, 0);
492 cjSize
= FIELD_OFFSET(LOGPALETTE
, palPalEntry
[cEntries
]);
496 ProbeForRead(plogpalUser
, cjSize
, 1);
498 for (i
= 0; i
< cEntries
; i
++)
500 ppal
->IndexedColors
[i
] = plogpalUser
->palPalEntry
[i
];
503 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
505 GDIOBJ_vDeleteObject(&ppal
->BaseObject
);
506 _SEH2_YIELD(return NULL
);
510 PALETTE_ValidateFlags(ppal
->IndexedColors
, cEntries
);
511 hpal
= ppal
->BaseObject
.hHmgr
;
512 PALETTE_UnlockPalette(ppal
);
517 HPALETTE APIENTRY
NtGdiCreateHalftonePalette(HDC hDC
)
522 WORD NumberOfEntries
;
523 PALETTEENTRY aEntries
[256];
526 Palette
.Version
= 0x300;
527 Palette
.NumberOfEntries
= 256;
528 if (IntGetSystemPaletteEntries(hDC
, 0, 256, Palette
.aEntries
) == 0)
530 /* From WINE, more that 256 color math */
531 Palette
.NumberOfEntries
= 20;
532 for (i
= 0; i
< Palette
.NumberOfEntries
; i
++)
534 Palette
.aEntries
[i
].peRed
=0xff;
535 Palette
.aEntries
[i
].peGreen
=0xff;
536 Palette
.aEntries
[i
].peBlue
=0xff;
537 Palette
.aEntries
[i
].peFlags
=0x00;
540 Palette
.aEntries
[0].peRed
=0x00;
541 Palette
.aEntries
[0].peBlue
=0x00;
542 Palette
.aEntries
[0].peGreen
=0x00;
545 for (i
=1; i
<= 6; i
++)
547 Palette
.aEntries
[i
].peRed
=(i
%2)?0x80:0;
548 Palette
.aEntries
[i
].peGreen
=(i
==2)?0x80:(i
==3)?0x80:(i
==6)?0x80:0;
549 Palette
.aEntries
[i
].peBlue
=(i
>3)?0x80:0;
552 for (i
=7; i
<= 12; i
++)
557 Palette
.aEntries
[i
].peRed
=0xc0;
558 Palette
.aEntries
[i
].peBlue
=0xc0;
559 Palette
.aEntries
[i
].peGreen
=0xc0;
562 Palette
.aEntries
[i
].peRed
=0xc0;
563 Palette
.aEntries
[i
].peGreen
=0xdc;
564 Palette
.aEntries
[i
].peBlue
=0xc0;
567 Palette
.aEntries
[i
].peRed
=0xa6;
568 Palette
.aEntries
[i
].peGreen
=0xca;
569 Palette
.aEntries
[i
].peBlue
=0xf0;
572 Palette
.aEntries
[i
].peRed
=0xff;
573 Palette
.aEntries
[i
].peGreen
=0xfb;
574 Palette
.aEntries
[i
].peBlue
=0xf0;
577 Palette
.aEntries
[i
].peRed
=0xa0;
578 Palette
.aEntries
[i
].peGreen
=0xa0;
579 Palette
.aEntries
[i
].peBlue
=0xa4;
582 Palette
.aEntries
[i
].peRed
=0x80;
583 Palette
.aEntries
[i
].peGreen
=0x80;
584 Palette
.aEntries
[i
].peBlue
=0x80;
588 for (i
=13; i
<= 18; i
++)
590 Palette
.aEntries
[i
].peRed
=(i
%2)?0xff:0;
591 Palette
.aEntries
[i
].peGreen
=(i
==14)?0xff:(i
==15)?0xff:(i
==18)?0xff:0;
592 Palette
.aEntries
[i
].peBlue
=(i
>15)?0xff:0x00;
597 /* 256 color table */
598 for (r
= 0; r
< 6; r
++)
599 for (g
= 0; g
< 6; g
++)
600 for (b
= 0; b
< 6; b
++)
602 i
= r
+ g
*6 + b
*36 + 10;
603 Palette
.aEntries
[i
].peRed
= r
* 51;
604 Palette
.aEntries
[i
].peGreen
= g
* 51;
605 Palette
.aEntries
[i
].peBlue
= b
* 51;
608 for (i
= 216; i
< 246; i
++)
610 int v
= (i
- 216) << 3;
611 Palette
.aEntries
[i
].peRed
= v
;
612 Palette
.aEntries
[i
].peGreen
= v
;
613 Palette
.aEntries
[i
].peBlue
= v
;
617 return GreCreatePaletteInternal((LOGPALETTE
*)&Palette
, Palette
.NumberOfEntries
);
626 /* PALOBJ *palPtr = (PALOBJ*)AccessUserObject(hPal);
627 UINT cPrevEnt, prevVer;
628 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
629 XLATEOBJ *XlateObj = NULL;
631 if(!palPtr) return FALSE;
632 cPrevEnt = palPtr->logpalette->palNumEntries;
633 prevVer = palPtr->logpalette->palVersion;
634 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
635 size += sizeof(int*) + sizeof(GDIOBJHDR);
636 XlateObj = palPtr->logicalToSystem;
638 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
642 XLATEOBJ *NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
643 if(NewXlateObj == NULL)
645 ERR("Can not resize logicalToSystem -- out of memory!");
646 GDI_ReleaseObj( hPal );
649 palPtr->logicalToSystem = NewXlateObj;
652 if(cEntries > cPrevEnt)
654 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
655 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
656 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
658 palPtr->logpalette->palNumEntries = cEntries;
659 palPtr->logpalette->palVersion = prevVer;
660 // GDI_ReleaseObj( hPal );
669 NtGdiGetColorAdjustment(
671 LPCOLORADJUSTMENT pca
)
679 NtGdiSetColorAdjustment(
681 LPCOLORADJUSTMENT pca
)
689 NtGdiGetNearestColor(
693 COLORREF nearest
= CLR_INVALID
;
702 EngSetLastError(ERROR_INVALID_HANDLE
);
706 if(dc
->dclevel
.pSurface
== NULL
)
709 ppal
= dc
->dclevel
.pSurface
->ppal
;
711 /* Translate the color to the DC format */
712 Color
= TranslateCOLORREF(dc
, Color
);
714 /* XLATE it back to RGB color space */
715 EXLATEOBJ_vInitialize(&exlo
,
719 RGB(0xff, 0xff, 0xff),
722 nearest
= XLATEOBJ_iXlate(&exlo
.xlo
, Color
);
724 EXLATEOBJ_vCleanup(&exlo
);
734 NtGdiGetNearestPaletteIndex(
738 PPALETTE ppal
= PALETTE_ShareLockPalette(hpal
);
743 if (ppal
->flFlags
& PAL_INDEXED
)
745 /* Return closest match for the given RGB color */
746 index
= PALETTE_ulGetNearestPaletteIndex(ppal
, crColor
);
748 // else SetLastError ?
749 PALETTE_ShareUnlockPalette(ppal
);
757 IntGdiRealizePalette(HDC hDC
)
761 PALETTE
*ppalSurf
, *ppalDC
;
763 pdc
= DC_LockDc(hDC
);
766 EngSetLastError(ERROR_INVALID_HANDLE
);
770 if (!pdc
->dclevel
.pSurface
)
775 if(pdc
->dctype
== DCTYPE_DIRECT
)
781 ppalSurf
= pdc
->dclevel
.pSurface
->ppal
;
782 ppalDC
= pdc
->dclevel
.ppal
;
784 if(!(ppalSurf
->flFlags
& PAL_INDEXED
))
790 ASSERT(ppalDC
->flFlags
& PAL_INDEXED
);
792 // FIXME: Should we resize ppalSurf if it's too small?
793 realize
= (ppalDC
->NumColors
< ppalSurf
->NumColors
) ? ppalDC
->NumColors
: ppalSurf
->NumColors
;
795 for(i
=0; i
<realize
; i
++)
797 InterlockedExchange((LONG
*)&ppalSurf
->IndexedColors
[i
], *(LONG
*)&ppalDC
->IndexedColors
[i
]);
806 IntAnimatePalette(HPALETTE hPal
,
809 CONST PPALETTEENTRY PaletteColors
)
813 if( hPal
!= NtGdiGetStockObject(DEFAULT_PALETTE
) )
820 const PALETTEENTRY
*pptr
= PaletteColors
;
822 palPtr
= PALETTE_ShareLockPalette(hPal
);
823 if (!palPtr
) return FALSE
;
825 pal_entries
= palPtr
->NumColors
;
826 if (StartIndex
>= pal_entries
)
828 PALETTE_ShareUnlockPalette(palPtr
);
831 if (StartIndex
+NumEntries
> pal_entries
) NumEntries
= pal_entries
- StartIndex
;
833 for (NumEntries
+= StartIndex
; StartIndex
< NumEntries
; StartIndex
++, pptr
++)
835 /* According to MSDN, only animate PC_RESERVED colours */
836 if (palPtr
->IndexedColors
[StartIndex
].peFlags
& PC_RESERVED
)
838 memcpy( &palPtr
->IndexedColors
[StartIndex
], pptr
,
839 sizeof(PALETTEENTRY
) );
841 PALETTE_ValidateFlags(&palPtr
->IndexedColors
[StartIndex
], 1);
845 PALETTE_ShareUnlockPalette(palPtr
);
847 /* Immediately apply the new palette if current window uses it */
848 Wnd
= UserGetDesktopWindow();
849 hDC
= UserGetWindowDC(Wnd
);
853 if (dc
->dclevel
.hpal
== hPal
)
856 IntGdiRealizePalette(hDC
);
861 UserReleaseDC(Wnd
,hDC
, FALSE
);
867 IntGetPaletteEntries(
876 palGDI
= (PPALETTE
) PALETTE_ShareLockPalette(hpal
);
882 numEntries
= palGDI
->NumColors
;
885 if (numEntries
< StartIndex
+ Entries
)
887 Entries
= numEntries
- StartIndex
;
889 if (numEntries
<= StartIndex
)
891 PALETTE_ShareUnlockPalette(palGDI
);
894 memcpy(pe
, palGDI
->IndexedColors
+ StartIndex
, Entries
* sizeof(PALETTEENTRY
));
898 Entries
= numEntries
;
901 PALETTE_ShareUnlockPalette(palGDI
);
906 IntGetSystemPaletteEntries(HDC hDC
,
911 PPALETTE palGDI
= NULL
;
913 UINT EntriesSize
= 0;
918 EngSetLastError(ERROR_INVALID_PARAMETER
);
924 EntriesSize
= Entries
* sizeof(pe
[0]);
925 if (Entries
!= EntriesSize
/ sizeof(pe
[0]))
927 /* Integer overflow! */
928 EngSetLastError(ERROR_INVALID_PARAMETER
);
933 if (!(dc
= DC_LockDc(hDC
)))
935 EngSetLastError(ERROR_INVALID_HANDLE
);
939 palGDI
= PALETTE_ShareLockPalette(dc
->dclevel
.hpal
);
944 if (StartIndex
>= palGDI
->NumColors
)
946 else if (Entries
> palGDI
->NumColors
- StartIndex
)
947 Entries
= palGDI
->NumColors
- StartIndex
;
950 palGDI
->IndexedColors
+ StartIndex
,
951 Entries
* sizeof(pe
[0]));
957 Ret
= dc
->ppdev
->gdiinfo
.ulNumPalReg
;
962 PALETTE_ShareUnlockPalette(palGDI
);
972 IntSetPaletteEntries(
976 CONST LPPALETTEENTRY pe
)
981 if ((UINT
)hpal
& GDI_HANDLE_STOCK_MASK
)
986 palGDI
= PALETTE_ShareLockPalette(hpal
);
987 if (!palGDI
) return 0;
989 numEntries
= palGDI
->NumColors
;
990 if (Start
>= numEntries
)
992 PALETTE_ShareUnlockPalette(palGDI
);
995 if (numEntries
< Start
+ Entries
)
997 Entries
= numEntries
- Start
;
999 memcpy(palGDI
->IndexedColors
+ Start
, pe
, Entries
* sizeof(PALETTEENTRY
));
1000 PALETTE_ShareUnlockPalette(palGDI
);
1007 GreGetSetColorTable(
1011 RGBQUAD
*prgbColors
,
1016 PPALETTE ppal
= NULL
;
1017 ULONG i
, iEndIndex
, iResult
= 0;
1020 pdc
= DC_LockDc(hdc
);
1026 /* Get the surace from the DC */
1027 psurf
= pdc
->dclevel
.pSurface
;
1029 /* Check if we have the default surface */
1032 /* Use a mono palette */
1033 if(!bSet
) ppal
= gppalMono
;
1035 else if (psurf
->SurfObj
.iType
== STYPE_BITMAP
)
1037 /* Get the palette of the surface */
1041 /* Check if this is an indexed palette and the range is ok */
1042 if (ppal
&& (ppal
->flFlags
& PAL_INDEXED
) &&
1043 (iStartIndex
< ppal
->NumColors
))
1045 /* Calculate the end of the operation */
1046 iEndIndex
= min(iStartIndex
+ cEntries
, ppal
->NumColors
);
1048 /* Check what operation to perform */
1051 /* Loop all colors and set the palette entries */
1052 for (i
= iStartIndex
; i
< iEndIndex
; i
++, prgbColors
++)
1054 ppal
->IndexedColors
[i
].peRed
= prgbColors
->rgbRed
;
1055 ppal
->IndexedColors
[i
].peGreen
= prgbColors
->rgbGreen
;
1056 ppal
->IndexedColors
[i
].peBlue
= prgbColors
->rgbBlue
;
1059 /* Mark the dc brushes invalid */
1060 pdc
->pdcattr
->ulDirty_
|= DIRTY_FILL
|DIRTY_LINE
|
1061 DIRTY_BACKGROUND
|DIRTY_TEXT
;
1065 /* Loop all colors and get the palette entries */
1066 for (i
= iStartIndex
; i
< iEndIndex
; i
++, prgbColors
++)
1068 prgbColors
->rgbRed
= ppal
->IndexedColors
[i
].peRed
;
1069 prgbColors
->rgbGreen
= ppal
->IndexedColors
[i
].peGreen
;
1070 prgbColors
->rgbBlue
= ppal
->IndexedColors
[i
].peBlue
;
1071 prgbColors
->rgbReserved
= 0;
1075 /* Calculate how many entries were modified */
1076 iResult
= iEndIndex
- iStartIndex
;
1092 IN LPVOID pUnsafeEntries
,
1097 LPVOID pEntries
= NULL
;
1099 /* FIXME: Handle bInbound correctly */
1102 (pUnsafeEntries
== NULL
|| cEntries
== 0))
1109 pEntries
= ExAllocatePoolWithTag(PagedPool
, cEntries
* sizeof(PALETTEENTRY
), TAG_PALETTE
);
1116 ProbeForRead(pUnsafeEntries
, cEntries
* sizeof(PALETTEENTRY
), 1);
1117 memcpy(pEntries
, pUnsafeEntries
, cEntries
* sizeof(PALETTEENTRY
));
1119 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1121 ExFreePoolWithTag(pEntries
, TAG_PALETTE
);
1122 _SEH2_YIELD(return 0);
1128 /* Zero it out, so we don't accidentally leak kernel data */
1129 RtlZeroMemory(pEntries
, cEntries
* sizeof(PALETTEENTRY
));
1138 ret
= IntAnimatePalette((HPALETTE
)hObj
, iStart
, cEntries
, (CONST PPALETTEENTRY
)pEntries
);
1141 case GdiPalSetEntries
:
1143 ret
= IntSetPaletteEntries((HPALETTE
)hObj
, iStart
, cEntries
, (CONST LPPALETTEENTRY
)pEntries
);
1146 case GdiPalGetEntries
:
1147 ret
= IntGetPaletteEntries((HPALETTE
)hObj
, iStart
, cEntries
, (LPPALETTEENTRY
)pEntries
);
1150 case GdiPalGetSystemEntries
:
1151 ret
= IntGetSystemPaletteEntries((HDC
)hObj
, iStart
, cEntries
, (LPPALETTEENTRY
)pEntries
);
1154 case GdiPalSetColorTable
:
1156 ret
= GreGetSetColorTable((HDC
)hObj
, iStart
, cEntries
, (RGBQUAD
*)pEntries
, TRUE
);
1159 case GdiPalGetColorTable
:
1161 ret
= GreGetSetColorTable((HDC
)hObj
, iStart
, cEntries
, (RGBQUAD
*)pEntries
, FALSE
);
1171 ProbeForWrite(pUnsafeEntries
, cEntries
* sizeof(PALETTEENTRY
), 1);
1172 memcpy(pUnsafeEntries
, pEntries
, cEntries
* sizeof(PALETTEENTRY
));
1174 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1180 ExFreePoolWithTag(pEntries
, TAG_PALETTE
);
1187 NtGdiSetSystemPaletteUse(HDC hDC
, UINT Usage
)
1189 UINT old
= SystemPaletteUse
;
1191 /* Device doesn't support colour palettes */
1192 if (!(NtGdiGetDeviceCaps(hDC
, RASTERCAPS
) & RC_PALETTE
)) {
1193 return SYSPAL_ERROR
;
1198 case SYSPAL_NOSTATIC
:
1199 case SYSPAL_NOSTATIC256
:
1201 SystemPaletteUse
= Usage
;
1214 NtGdiGetSystemPaletteUse(HDC hDC
)
1216 return SystemPaletteUse
;
1221 NtGdiUpdateColors(HDC hDC
)
1224 BOOL calledFromUser
, ret
;
1225 USER_REFERENCE_ENTRY Ref
;
1227 calledFromUser
= UserIsEntered();
1229 if (!calledFromUser
){
1230 UserEnterExclusive();
1233 Wnd
= UserGetWindowObject(IntWindowFromDC(hDC
));
1236 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1238 if (!calledFromUser
){
1245 UserRefObjectCo(Wnd
, &Ref
);
1246 ret
= co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_INVALIDATE
);
1247 UserDerefObjectCo(Wnd
);
1249 if (!calledFromUser
){
1258 NtGdiUnrealizeObject(HGDIOBJ hgdiobj
)
1264 ((UINT
)hgdiobj
& GDI_HANDLE_STOCK_MASK
) ||
1265 !GDI_HANDLE_IS_TYPE(hgdiobj
, GDI_OBJECT_TYPE_PALETTE
) )
1268 palGDI
= PALETTE_ShareLockPalette(hgdiobj
);
1269 if (!palGDI
) return FALSE
;
1272 // Need to do something!!!
1273 // Zero out Current and Old Translated pointers?
1276 PALETTE_ShareUnlockPalette(palGDI
);