[WIN32K]
[reactos.git] / subsystems / win32 / win32k / objects / palette.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI Palette Functions
5 * FILE: subsys/win32k/eng/palette.c
6 * PROGRAMERS: Jason Filby
7 * Timo Kreuzer
8 */
9
10 #include <win32k.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 static UINT SystemPaletteUse = SYSPAL_NOSTATIC; /* the program need save the pallete and restore it */
16
17 PALETTE gpalRGB, gpalBGR, gpalMono, gpalRGB555, gpalRGB565, *gppalDefault;
18 PPALETTE appalSurfaceDefault[11];
19
20 const PALETTEENTRY g_sysPalTemplate[NB_RESERVED_COLORS] =
21 {
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 },
34
35 // ... c_min/2 dynamic colorcells
36 // ... gap (for sparse palettes)
37 // ... c_min/2 dynamic colorcells
38
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
49 };
50
51 unsigned short GetNumberOfBits(unsigned int dwMask)
52 {
53 unsigned short wBits;
54 for (wBits = 0; dwMask; dwMask = dwMask & (dwMask - 1))
55 wBits++;
56 return wBits;
57 }
58
59 // Create the system palette
60 HPALETTE FASTCALL PALETTE_Init(VOID)
61 {
62 int i;
63 HPALETTE hpalette;
64 PLOGPALETTE palPtr;
65
66 // create default palette (20 system colors)
67 palPtr = ExAllocatePoolWithTag(PagedPool,
68 sizeof(LOGPALETTE) +
69 (NB_RESERVED_COLORS * sizeof(PALETTEENTRY)),
70 TAG_PALETTE);
71 if (!palPtr) return FALSE;
72
73 palPtr->palVersion = 0x300;
74 palPtr->palNumEntries = NB_RESERVED_COLORS;
75 for (i=0; i<NB_RESERVED_COLORS; i++)
76 {
77 palPtr->palPalEntry[i].peRed = g_sysPalTemplate[i].peRed;
78 palPtr->palPalEntry[i].peGreen = g_sysPalTemplate[i].peGreen;
79 palPtr->palPalEntry[i].peBlue = g_sysPalTemplate[i].peBlue;
80 palPtr->palPalEntry[i].peFlags = 0;
81 }
82
83 hpalette = NtGdiCreatePaletteInternal(palPtr,NB_RESERVED_COLORS);
84 ExFreePoolWithTag(palPtr, TAG_PALETTE);
85
86 /* palette_size = visual->map_entries; */
87
88 gpalRGB.Mode = PAL_RGB;
89 gpalRGB.RedMask = RGB(0xFF, 0x00, 0x00);
90 gpalRGB.GreenMask = RGB(0x00, 0xFF, 0x00);
91 gpalRGB.BlueMask = RGB(0x00, 0x00, 0xFF);
92 gpalRGB.BaseObject.ulShareCount = 0;
93 gpalRGB.BaseObject.BaseFlags = 0 ;
94
95 gpalBGR.Mode = PAL_BGR;
96 gpalBGR.RedMask = RGB(0x00, 0x00, 0xFF);
97 gpalBGR.GreenMask = RGB(0x00, 0xFF, 0x00);
98 gpalBGR.BlueMask = RGB(0xFF, 0x00, 0x00);
99 gpalBGR.BaseObject.ulShareCount = 0;
100 gpalBGR.BaseObject.BaseFlags = 0 ;
101
102 gpalRGB555.Mode = PAL_RGB16_555 | PAL_BITFIELDS;
103 gpalRGB555.RedMask = 0x7C00;
104 gpalRGB555.GreenMask = 0x3E0;
105 gpalRGB555.BlueMask = 0x1F;
106 gpalRGB555.BaseObject.ulShareCount = 0;
107 gpalRGB555.BaseObject.BaseFlags = 0 ;
108
109 gpalRGB565.Mode = PAL_RGB16_565 | PAL_BITFIELDS;
110 gpalRGB565.RedMask = 0xF800;
111 gpalRGB565.GreenMask = 0x7E0;
112 gpalRGB565.BlueMask = 0x1F;
113 gpalRGB565.BaseObject.ulShareCount = 0;
114 gpalRGB565.BaseObject.BaseFlags = 0 ;
115
116 memset(&gpalMono, 0, sizeof(PALETTE));
117 gpalMono.Mode = PAL_MONOCHROME;
118 gpalMono.BaseObject.ulShareCount = 0;
119 gpalMono.BaseObject.BaseFlags = 0 ;
120
121 /* Initialize default surface palettes */
122 gppalDefault = PALETTE_ShareLockPalette(hpalette);
123 appalSurfaceDefault[BMF_1BPP] = &gpalMono;
124 appalSurfaceDefault[BMF_4BPP] = gppalDefault;
125 appalSurfaceDefault[BMF_8BPP] = gppalDefault;
126 appalSurfaceDefault[BMF_16BPP] = &gpalRGB565;
127 appalSurfaceDefault[BMF_24BPP] = &gpalRGB;
128 appalSurfaceDefault[BMF_32BPP] = &gpalRGB;
129 appalSurfaceDefault[BMF_4RLE] = gppalDefault;
130 appalSurfaceDefault[BMF_8RLE] = gppalDefault;
131 appalSurfaceDefault[BMF_JPEG] = &gpalRGB;
132 appalSurfaceDefault[BMF_PNG] = &gpalRGB;
133
134 return hpalette;
135 }
136
137 VOID FASTCALL PALETTE_ValidateFlags(PALETTEENTRY* lpPalE, INT size)
138 {
139 int i = 0;
140 for (; i<size ; i++)
141 lpPalE[i].peFlags = PC_SYS_USED | (lpPalE[i].peFlags & 0x07);
142 }
143
144 HPALETTE
145 FASTCALL
146 PALETTE_AllocPalette(ULONG Mode,
147 ULONG NumColors,
148 ULONG *Colors,
149 ULONG Red,
150 ULONG Green,
151 ULONG Blue)
152 {
153 HPALETTE NewPalette;
154 PPALETTE PalGDI;
155
156 PalGDI = (PPALETTE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_PALETTE);
157 if (!PalGDI)
158 {
159 return NULL;
160 }
161
162 NewPalette = PalGDI->BaseObject.hHmgr;
163
164 PalGDI->Self = NewPalette;
165 PalGDI->Mode = Mode;
166
167 if (NULL != Colors)
168 {
169 PalGDI->IndexedColors = ExAllocatePoolWithTag(PagedPool,
170 sizeof(PALETTEENTRY) * NumColors,
171 TAG_PALETTE);
172 if (NULL == PalGDI->IndexedColors)
173 {
174 PALETTE_UnlockPalette(PalGDI);
175 PALETTE_FreePaletteByHandle(NewPalette);
176 return NULL;
177 }
178 RtlCopyMemory(PalGDI->IndexedColors, Colors, sizeof(PALETTEENTRY) * NumColors);
179 }
180
181 if (PAL_INDEXED == Mode)
182 {
183 PalGDI->NumColors = NumColors;
184 }
185 else if (PAL_BITFIELDS == Mode)
186 {
187 PalGDI->RedMask = Red;
188 PalGDI->GreenMask = Green;
189 PalGDI->BlueMask = Blue;
190
191 if (Red == 0x7c00 && Green == 0x3E0 && Blue == 0x1F)
192 PalGDI->Mode |= PAL_RGB16_555;
193 else if (Red == 0xF800 && Green == 0x7E0 && Blue == 0x1F)
194 PalGDI->Mode |= PAL_RGB16_565;
195 }
196
197 PALETTE_UnlockPalette(PalGDI);
198
199 return NewPalette;
200 }
201
202 HPALETTE
203 FASTCALL
204 PALETTE_AllocPaletteIndexedRGB(ULONG NumColors,
205 CONST RGBQUAD *Colors)
206 {
207 HPALETTE NewPalette;
208 PPALETTE PalGDI;
209 UINT i;
210
211 PalGDI = (PPALETTE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_PALETTE);
212 if (!PalGDI)
213 {
214 return NULL;
215 }
216
217 NewPalette = PalGDI->BaseObject.hHmgr;
218
219 PalGDI->Self = NewPalette;
220 PalGDI->Mode = PAL_INDEXED;
221
222 PalGDI->IndexedColors = ExAllocatePoolWithTag(PagedPool,
223 sizeof(PALETTEENTRY) * NumColors,
224 TAG_PALETTE);
225 if (NULL == PalGDI->IndexedColors)
226 {
227 PALETTE_UnlockPalette(PalGDI);
228 PALETTE_FreePaletteByHandle(NewPalette);
229 return NULL;
230 }
231
232 for (i = 0; i < NumColors; i++)
233 {
234 PalGDI->IndexedColors[i].peRed = Colors[i].rgbRed;
235 PalGDI->IndexedColors[i].peGreen = Colors[i].rgbGreen;
236 PalGDI->IndexedColors[i].peBlue = Colors[i].rgbBlue;
237 PalGDI->IndexedColors[i].peFlags = 0;
238 }
239
240 PalGDI->NumColors = NumColors;
241
242 PALETTE_UnlockPalette(PalGDI);
243
244 return NewPalette;
245 }
246
247 BOOL INTERNAL_CALL
248 PALETTE_Cleanup(PVOID ObjectBody)
249 {
250 PPALETTE pPal = (PPALETTE)ObjectBody;
251 if (NULL != pPal->IndexedColors)
252 {
253 ExFreePoolWithTag(pPal->IndexedColors, TAG_PALETTE);
254 }
255
256 return TRUE;
257 }
258
259 INT FASTCALL
260 PALETTE_GetObject(PPALETTE ppal, INT cbCount, LPLOGBRUSH lpBuffer)
261 {
262 if (!lpBuffer)
263 {
264 return sizeof(WORD);
265 }
266
267 if ((UINT)cbCount < sizeof(WORD)) return 0;
268 *((WORD*)lpBuffer) = (WORD)ppal->NumColors;
269 return sizeof(WORD);
270 }
271
272 ULONG
273 NTAPI
274 PALETTE_ulGetNearestPaletteIndex(PALETTE* ppal, ULONG iColor)
275 {
276 ULONG ulDiff, ulColorDiff, ulMinimalDiff = 0xFFFFFF;
277 ULONG i, ulBestIndex = 0;
278 PALETTEENTRY peColor = *(PPALETTEENTRY)&iColor;
279
280 /* Loop all palette entries, break on exact match */
281 for (i = 0; i < ppal->NumColors && ulMinimalDiff != 0; i++)
282 {
283 /* Calculate distance in the color cube */
284 ulDiff = peColor.peRed - ppal->IndexedColors[i].peRed;
285 ulColorDiff = ulDiff * ulDiff;
286 ulDiff = peColor.peGreen - ppal->IndexedColors[i].peGreen;
287 ulColorDiff += ulDiff * ulDiff;
288 ulDiff = peColor.peBlue - ppal->IndexedColors[i].peBlue;
289 ulColorDiff += ulDiff * ulDiff;
290
291 /* Check for a better match */
292 if (ulColorDiff < ulMinimalDiff)
293 {
294 ulBestIndex = i;
295 ulMinimalDiff = ulColorDiff;
296 }
297 }
298
299 return ulBestIndex;
300 }
301
302 ULONG
303 NTAPI
304 PALETTE_ulGetNearestBitFieldsIndex(PALETTE* ppal, ULONG ulColor)
305 {
306 ULONG ulNewColor;
307
308 // FIXME: HACK, should be stored already
309 ppal->ulRedShift = CalculateShift(RGB(0xff,0,0), ppal->RedMask);
310 ppal->ulGreenShift = CalculateShift(RGB(0,0xff,0), ppal->GreenMask);
311 ppal->ulBlueShift = CalculateShift(RGB(0,0,0xff), ppal->BlueMask);
312
313 ulNewColor = _rotl(ulColor, ppal->ulRedShift) & ppal->RedMask;
314 ulNewColor |= _rotl(ulColor, ppal->ulGreenShift) & ppal->GreenMask;
315 ulNewColor |= _rotl(ulColor, ppal->ulBlueShift) & ppal->BlueMask;
316
317 return ulNewColor;
318 }
319
320 ULONG
321 NTAPI
322 PALETTE_ulGetNearestIndex(PALETTE* ppal, ULONG ulColor)
323 {
324 if (ppal->Mode & PAL_INDEXED) // use fl & PALINDEXED
325 return PALETTE_ulGetNearestPaletteIndex(ppal, ulColor);
326 else
327 return PALETTE_ulGetNearestBitFieldsIndex(ppal, ulColor);
328 }
329
330 VOID
331 NTAPI
332 PALETTE_vGetBitMasks(PPALETTE ppal, PULONG pulColors)
333 {
334 ASSERT(pulColors);
335
336 if (ppal->Mode & PAL_INDEXED || ppal->Mode & PAL_RGB)
337 {
338 pulColors[0] = RGB(0xFF, 0x00, 0x00);
339 pulColors[1] = RGB(0x00, 0xFF, 0x00);
340 pulColors[2] = RGB(0x00, 0x00, 0xFF);
341 }
342 else if (ppal->Mode & PAL_BGR)
343 {
344 pulColors[0] = RGB(0x00, 0x00, 0xFF);
345 pulColors[1] = RGB(0x00, 0xFF, 0x00);
346 pulColors[2] = RGB(0xFF, 0x00, 0x00);
347 }
348 else if (ppal->Mode & PAL_BITFIELDS)
349 {
350 pulColors[0] = ppal->RedMask;
351 pulColors[1] = ppal->GreenMask;
352 pulColors[2] = ppal->BlueMask;
353 }
354 }
355
356 VOID
357 FASTCALL
358 ColorCorrection(PPALETTE PalGDI, PPALETTEENTRY PaletteEntry, ULONG Colors)
359 {
360 PPDEVOBJ ppdev = (PPDEVOBJ)PalGDI->hPDev;
361
362 if (!ppdev) return;
363
364 if (ppdev->flFlags & PDEV_GAMMARAMP_TABLE)
365 {
366 INT i;
367 PGAMMARAMP GammaRamp = (PGAMMARAMP)ppdev->pvGammaRamp;
368 for ( i = 0; i < Colors; i++)
369 {
370 PaletteEntry[i].peRed += GammaRamp->Red[i];
371 PaletteEntry[i].peGreen += GammaRamp->Green[i];
372 PaletteEntry[i].peBlue += GammaRamp->Blue[i];
373 }
374 }
375 return;
376 }
377
378 /** Display Driver Interface **************************************************/
379
380 /*
381 * @implemented
382 */
383 HPALETTE
384 APIENTRY
385 EngCreatePalette(
386 ULONG Mode,
387 ULONG NumColors,
388 ULONG *Colors,
389 ULONG Red,
390 ULONG Green,
391 ULONG Blue)
392 {
393 HPALETTE Palette;
394
395 Palette = PALETTE_AllocPalette(Mode, NumColors, Colors, Red, Green, Blue);
396 if (Palette != NULL)
397 {
398 GDIOBJ_SetOwnership(Palette, NULL);
399 }
400
401 return Palette;
402 }
403
404 /*
405 * @implemented
406 */
407 BOOL
408 APIENTRY
409 EngDeletePalette(IN HPALETTE Palette)
410 {
411 GDIOBJ_SetOwnership(Palette, PsGetCurrentProcess());
412
413 return PALETTE_FreePaletteByHandle(Palette);
414 }
415
416 /*
417 * @implemented
418 */
419 ULONG
420 APIENTRY
421 PALOBJ_cGetColors(PALOBJ *PalObj, ULONG Start, ULONG Colors, ULONG *PaletteEntry)
422 {
423 PALETTE *PalGDI;
424
425 PalGDI = (PALETTE*)PalObj;
426 /* PalGDI = (PALETTE*)AccessInternalObjectFromUserObject(PalObj); */
427
428 if (Start >= PalGDI->NumColors)
429 return 0;
430
431 Colors = min(Colors, PalGDI->NumColors - Start);
432
433 /* NOTE: PaletteEntry ULONGs are in the same order as PALETTEENTRY. */
434 RtlCopyMemory(PaletteEntry, PalGDI->IndexedColors + Start, sizeof(ULONG) * Colors);
435
436 if (PalGDI->Mode & PAL_GAMMACORRECTION)
437 ColorCorrection(PalGDI, (PPALETTEENTRY)PaletteEntry, Colors);
438
439 return Colors;
440 }
441
442
443 /** Systemcall Interface ******************************************************/
444
445 /*
446 * @implemented
447 */
448 HPALETTE APIENTRY
449 NtGdiCreatePaletteInternal ( IN LPLOGPALETTE pLogPal, IN UINT cEntries )
450 {
451 PPALETTE PalGDI;
452 HPALETTE NewPalette;
453
454 pLogPal->palNumEntries = cEntries;
455 NewPalette = PALETTE_AllocPalette( PAL_INDEXED,
456 cEntries,
457 (PULONG)pLogPal->palPalEntry,
458 0, 0, 0);
459
460 if (NewPalette == NULL)
461 {
462 return NULL;
463 }
464
465 PalGDI = (PPALETTE) PALETTE_LockPalette(NewPalette);
466 if (PalGDI != NULL)
467 {
468 PALETTE_ValidateFlags(PalGDI->IndexedColors, PalGDI->NumColors);
469 PALETTE_UnlockPalette(PalGDI);
470 }
471 else
472 {
473 /* FIXME - Handle PalGDI == NULL!!!! */
474 DPRINT1("PalGDI is NULL\n");
475 }
476 return NewPalette;
477 }
478
479 HPALETTE APIENTRY NtGdiCreateHalftonePalette(HDC hDC)
480 {
481 int i, r, g, b;
482 struct {
483 WORD Version;
484 WORD NumberOfEntries;
485 PALETTEENTRY aEntries[256];
486 } Palette;
487
488 Palette.Version = 0x300;
489 Palette.NumberOfEntries = 256;
490 if (IntGetSystemPaletteEntries(hDC, 0, 256, Palette.aEntries) == 0)
491 {
492 /* from wine, more that 256 color math */
493 Palette.NumberOfEntries = 20;
494 for (i = 0; i < Palette.NumberOfEntries; i++)
495 {
496 Palette.aEntries[i].peRed=0xff;
497 Palette.aEntries[i].peGreen=0xff;
498 Palette.aEntries[i].peBlue=0xff;
499 Palette.aEntries[i].peFlags=0x00;
500 }
501
502 Palette.aEntries[0].peRed=0x00;
503 Palette.aEntries[0].peBlue=0x00;
504 Palette.aEntries[0].peGreen=0x00;
505
506 /* the first 6 */
507 for (i=1; i <= 6; i++)
508 {
509 Palette.aEntries[i].peRed=(i%2)?0x80:0;
510 Palette.aEntries[i].peGreen=(i==2)?0x80:(i==3)?0x80:(i==6)?0x80:0;
511 Palette.aEntries[i].peBlue=(i>3)?0x80:0;
512 }
513
514 for (i=7; i <= 12; i++)
515 {
516 switch(i)
517 {
518 case 7:
519 Palette.aEntries[i].peRed=0xc0;
520 Palette.aEntries[i].peBlue=0xc0;
521 Palette.aEntries[i].peGreen=0xc0;
522 break;
523 case 8:
524 Palette.aEntries[i].peRed=0xc0;
525 Palette.aEntries[i].peGreen=0xdc;
526 Palette.aEntries[i].peBlue=0xc0;
527 break;
528 case 9:
529 Palette.aEntries[i].peRed=0xa6;
530 Palette.aEntries[i].peGreen=0xca;
531 Palette.aEntries[i].peBlue=0xf0;
532 break;
533 case 10:
534 Palette.aEntries[i].peRed=0xff;
535 Palette.aEntries[i].peGreen=0xfb;
536 Palette.aEntries[i].peBlue=0xf0;
537 break;
538 case 11:
539 Palette.aEntries[i].peRed=0xa0;
540 Palette.aEntries[i].peGreen=0xa0;
541 Palette.aEntries[i].peBlue=0xa4;
542 break;
543 case 12:
544 Palette.aEntries[i].peRed=0x80;
545 Palette.aEntries[i].peGreen=0x80;
546 Palette.aEntries[i].peBlue=0x80;
547 }
548 }
549
550 for (i=13; i <= 18; i++)
551 {
552 Palette.aEntries[i].peRed=(i%2)?0xff:0;
553 Palette.aEntries[i].peGreen=(i==14)?0xff:(i==15)?0xff:(i==18)?0xff:0;
554 Palette.aEntries[i].peBlue=(i>15)?0xff:0x00;
555 }
556 }
557 else
558 {
559 /* 256 color table */
560 for (r = 0; r < 6; r++)
561 for (g = 0; g < 6; g++)
562 for (b = 0; b < 6; b++)
563 {
564 i = r + g*6 + b*36 + 10;
565 Palette.aEntries[i].peRed = r * 51;
566 Palette.aEntries[i].peGreen = g * 51;
567 Palette.aEntries[i].peBlue = b * 51;
568 }
569
570 for (i = 216; i < 246; i++)
571 {
572 int v = (i - 216) << 3;
573 Palette.aEntries[i].peRed = v;
574 Palette.aEntries[i].peGreen = v;
575 Palette.aEntries[i].peBlue = v;
576 }
577 }
578
579 return NtGdiCreatePaletteInternal((LOGPALETTE *)&Palette, Palette.NumberOfEntries);
580 }
581
582 BOOL
583 APIENTRY
584 NtGdiResizePalette(
585 HPALETTE hpal,
586 UINT Entries)
587 {
588 /* PALOBJ *palPtr = (PALOBJ*)AccessUserObject(hPal);
589 UINT cPrevEnt, prevVer;
590 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
591 XLATEOBJ *XlateObj = NULL;
592
593 if(!palPtr) return FALSE;
594 cPrevEnt = palPtr->logpalette->palNumEntries;
595 prevVer = palPtr->logpalette->palVersion;
596 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
597 size += sizeof(int*) + sizeof(GDIOBJHDR);
598 XlateObj = palPtr->logicalToSystem;
599
600 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
601
602 if(XlateObj)
603 {
604 XLATEOBJ *NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
605 if(NewXlateObj == NULL)
606 {
607 ERR("Can not resize logicalToSystem -- out of memory!");
608 GDI_ReleaseObj( hPal );
609 return FALSE;
610 }
611 palPtr->logicalToSystem = NewXlateObj;
612 }
613
614 if(cEntries > cPrevEnt)
615 {
616 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
617 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
618 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
619 }
620 palPtr->logpalette->palNumEntries = cEntries;
621 palPtr->logpalette->palVersion = prevVer;
622 // GDI_ReleaseObj( hPal );
623 return TRUE; */
624
625 UNIMPLEMENTED;
626 return FALSE;
627 }
628
629 BOOL
630 APIENTRY
631 NtGdiGetColorAdjustment(
632 HDC hdc,
633 LPCOLORADJUSTMENT pca)
634 {
635 UNIMPLEMENTED;
636 return FALSE;
637 }
638
639 BOOL
640 APIENTRY
641 NtGdiSetColorAdjustment(
642 HDC hdc,
643 LPCOLORADJUSTMENT pca)
644 {
645 UNIMPLEMENTED;
646 return FALSE;
647 }
648
649 COLORREF APIENTRY NtGdiGetNearestColor(HDC hDC, COLORREF Color)
650 {
651 COLORREF nearest = CLR_INVALID;
652 PDC dc;
653 PPALETTE palGDI;
654 LONG RBits, GBits, BBits;
655
656 dc = DC_LockDc(hDC);
657 if (NULL != dc)
658 {
659 HPALETTE hpal = dc->dclevel.hpal;
660 palGDI = (PPALETTE) PALETTE_LockPalette(hpal);
661 if (!palGDI)
662 {
663 DC_UnlockDc(dc);
664 return nearest;
665 }
666
667 if (palGDI->Mode & PAL_INDEXED)
668 {
669 ULONG index;
670 index = PALETTE_ulGetNearestPaletteIndex(palGDI, Color);
671 nearest = PALETTE_ulGetRGBColorFromIndex(palGDI, index);
672 }
673 else if (palGDI->Mode & PAL_RGB || palGDI->Mode & PAL_BGR)
674 {
675 nearest = Color;
676 }
677 else if (palGDI->Mode & PAL_BITFIELDS)
678 {
679 RBits = 8 - GetNumberOfBits(palGDI->RedMask);
680 GBits = 8 - GetNumberOfBits(palGDI->GreenMask);
681 BBits = 8 - GetNumberOfBits(palGDI->BlueMask);
682 nearest = RGB(
683 (GetRValue(Color) >> RBits) << RBits,
684 (GetGValue(Color) >> GBits) << GBits,
685 (GetBValue(Color) >> BBits) << BBits);
686 }
687 PALETTE_UnlockPalette(palGDI);
688 DC_UnlockDc(dc);
689 }
690
691 return nearest;
692 }
693
694 UINT
695 APIENTRY
696 NtGdiGetNearestPaletteIndex(
697 HPALETTE hpal,
698 COLORREF crColor)
699 {
700 PPALETTE ppal = (PPALETTE) PALETTE_LockPalette(hpal);
701 UINT index = 0;
702
703 if (ppal)
704 {
705 if (ppal->Mode & PAL_INDEXED)
706 {
707 /* Return closest match for the given RGB color */
708 index = PALETTE_ulGetNearestPaletteIndex(ppal, crColor);
709 }
710 // else SetLastError ?
711 PALETTE_UnlockPalette(ppal);
712 }
713
714 return index;
715 }
716
717 UINT
718 FASTCALL
719 IntGdiRealizePalette(HDC hDC)
720 {
721 /*
722 * This function doesn't do any real work now and there's plenty
723 * of bugs in it.
724 */
725
726 PPALETTE palGDI, sysGDI;
727 int realized = 0;
728 PDC dc;
729 HPALETTE systemPalette;
730 USHORT sysMode, palMode;
731
732 dc = DC_LockDc(hDC);
733 if (!dc) return 0;
734
735 systemPalette = NtGdiGetStockObject(DEFAULT_PALETTE);
736 palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
737
738 if (palGDI == NULL)
739 {
740 DPRINT1("IntGdiRealizePalette(): palGDI is NULL, exiting\n");
741 DC_UnlockDc(dc);
742 return 0;
743 }
744
745 sysGDI = PALETTE_LockPalette(systemPalette);
746
747 if (sysGDI == NULL)
748 {
749 DPRINT1("IntGdiRealizePalette(): sysGDI is NULL, exiting\n");
750 PALETTE_UnlockPalette(palGDI);
751 DC_UnlockDc(dc);
752 return 0;
753 }
754
755 // The RealizePalette function modifies the palette for the device associated with the specified device context. If the
756 // device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device
757 // context is a display DC, the physical palette for that device is modified.
758 if(dc->dctype == DC_TYPE_MEMORY)
759 {
760 // Memory managed DC
761 DPRINT1("RealizePalette unimplemented for memory managed DCs\n");
762 } else
763 {
764 DPRINT1("RealizePalette unimplemented for device DCs\n");
765 }
766
767 // need to pass this to IntEngCreateXlate with palettes unlocked
768 sysMode = sysGDI->Mode;
769 palMode = palGDI->Mode;
770 PALETTE_UnlockPalette(sysGDI);
771 PALETTE_UnlockPalette(palGDI);
772
773 DC_UnlockDc(dc);
774
775 return realized;
776 }
777
778 UINT APIENTRY
779 IntAnimatePalette(HPALETTE hPal,
780 UINT StartIndex,
781 UINT NumEntries,
782 CONST PPALETTEENTRY PaletteColors)
783 {
784 UINT ret = 0;
785
786 if( hPal != NtGdiGetStockObject(DEFAULT_PALETTE) )
787 {
788 PPALETTE palPtr;
789 UINT pal_entries;
790 HDC hDC;
791 PDC dc;
792 PWINDOW_OBJECT Wnd;
793 const PALETTEENTRY *pptr = PaletteColors;
794
795 palPtr = (PPALETTE)PALETTE_LockPalette(hPal);
796 if (!palPtr) return FALSE;
797
798 pal_entries = palPtr->NumColors;
799 if (StartIndex >= pal_entries)
800 {
801 PALETTE_UnlockPalette(palPtr);
802 return FALSE;
803 }
804 if (StartIndex+NumEntries > pal_entries) NumEntries = pal_entries - StartIndex;
805
806 for (NumEntries += StartIndex; StartIndex < NumEntries; StartIndex++, pptr++)
807 {
808 /* According to MSDN, only animate PC_RESERVED colours */
809 if (palPtr->IndexedColors[StartIndex].peFlags & PC_RESERVED)
810 {
811 memcpy( &palPtr->IndexedColors[StartIndex], pptr,
812 sizeof(PALETTEENTRY) );
813 ret++;
814 PALETTE_ValidateFlags(&palPtr->IndexedColors[StartIndex], 1);
815 }
816 }
817
818 PALETTE_UnlockPalette(palPtr);
819
820 /* Immediately apply the new palette if current window uses it */
821 Wnd = UserGetDesktopWindow();
822 hDC = UserGetWindowDC(Wnd);
823 dc = DC_LockDc(hDC);
824 if (NULL != dc)
825 {
826 if (dc->dclevel.hpal == hPal)
827 {
828 DC_UnlockDc(dc);
829 IntGdiRealizePalette(hDC);
830 }
831 else
832 DC_UnlockDc(dc);
833 }
834 UserReleaseDC(Wnd,hDC, FALSE);
835 }
836 return ret;
837 }
838
839 UINT APIENTRY
840 IntGetPaletteEntries(
841 HPALETTE hpal,
842 UINT StartIndex,
843 UINT Entries,
844 LPPALETTEENTRY pe)
845 {
846 PPALETTE palGDI;
847 UINT numEntries;
848
849 palGDI = (PPALETTE) PALETTE_LockPalette(hpal);
850 if (NULL == palGDI)
851 {
852 return 0;
853 }
854
855 numEntries = palGDI->NumColors;
856 if (NULL != pe)
857 {
858 if (numEntries < StartIndex + Entries)
859 {
860 Entries = numEntries - StartIndex;
861 }
862 if (numEntries <= StartIndex)
863 {
864 PALETTE_UnlockPalette(palGDI);
865 return 0;
866 }
867 memcpy(pe, palGDI->IndexedColors + StartIndex, Entries * sizeof(PALETTEENTRY));
868 }
869 else
870 {
871 Entries = numEntries;
872 }
873
874 PALETTE_UnlockPalette(palGDI);
875 return Entries;
876 }
877
878 UINT APIENTRY
879 IntGetSystemPaletteEntries(HDC hDC,
880 UINT StartIndex,
881 UINT Entries,
882 LPPALETTEENTRY pe)
883 {
884 PPALETTE palGDI = NULL;
885 PDC dc = NULL;
886 UINT EntriesSize = 0;
887 UINT Ret = 0;
888
889 if (Entries == 0)
890 {
891 SetLastWin32Error(ERROR_INVALID_PARAMETER);
892 return 0;
893 }
894
895 if (pe != NULL)
896 {
897 EntriesSize = Entries * sizeof(pe[0]);
898 if (Entries != EntriesSize / sizeof(pe[0]))
899 {
900 /* Integer overflow! */
901 SetLastWin32Error(ERROR_INVALID_PARAMETER);
902 return 0;
903 }
904 }
905
906 if (!(dc = DC_LockDc(hDC)))
907 {
908 SetLastWin32Error(ERROR_INVALID_HANDLE);
909 return 0;
910 }
911
912 palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
913 if (palGDI != NULL)
914 {
915 if (pe != NULL)
916 {
917 if (StartIndex >= palGDI->NumColors)
918 Entries = 0;
919 else if (Entries > palGDI->NumColors - StartIndex)
920 Entries = palGDI->NumColors - StartIndex;
921
922 memcpy(pe,
923 palGDI->IndexedColors + StartIndex,
924 Entries * sizeof(pe[0]));
925
926 Ret = Entries;
927 }
928 else
929 {
930 Ret = dc->ppdev->gdiinfo.ulNumPalReg;
931 }
932 }
933
934 if (palGDI != NULL)
935 PALETTE_UnlockPalette(palGDI);
936
937 if (dc != NULL)
938 DC_UnlockDc(dc);
939
940 return Ret;
941 }
942
943 UINT
944 APIENTRY
945 IntSetPaletteEntries(
946 HPALETTE hpal,
947 UINT Start,
948 UINT Entries,
949 CONST LPPALETTEENTRY pe)
950 {
951 PPALETTE palGDI;
952 WORD numEntries;
953
954 if ((UINT)hpal & GDI_HANDLE_STOCK_MASK)
955 {
956 return 0;
957 }
958
959 palGDI = PALETTE_LockPalette(hpal);
960 if (!palGDI) return 0;
961
962 numEntries = palGDI->NumColors;
963 if (Start >= numEntries)
964 {
965 PALETTE_UnlockPalette(palGDI);
966 return 0;
967 }
968 if (numEntries < Start + Entries)
969 {
970 Entries = numEntries - Start;
971 }
972 memcpy(palGDI->IndexedColors + Start, pe, Entries * sizeof(PALETTEENTRY));
973 PALETTE_UnlockPalette(palGDI);
974
975 return Entries;
976 }
977
978 W32KAPI
979 LONG
980 APIENTRY
981 NtGdiDoPalette(
982 IN HGDIOBJ hObj,
983 IN WORD iStart,
984 IN WORD cEntries,
985 IN LPVOID pUnsafeEntries,
986 IN DWORD iFunc,
987 IN BOOL bInbound)
988 {
989 LONG ret;
990 LPVOID pEntries = NULL;
991
992 /* FIXME: Handle bInbound correctly */
993
994 if (bInbound &&
995 (pUnsafeEntries == NULL || cEntries == 0))
996 {
997 return 0;
998 }
999
1000 if (pUnsafeEntries)
1001 {
1002 pEntries = ExAllocatePoolWithTag(PagedPool, cEntries * sizeof(PALETTEENTRY), TAG_PALETTE);
1003 if (!pEntries)
1004 return 0;
1005 if (bInbound)
1006 {
1007 _SEH2_TRY
1008 {
1009 ProbeForRead(pUnsafeEntries, cEntries * sizeof(PALETTEENTRY), 1);
1010 memcpy(pEntries, pUnsafeEntries, cEntries * sizeof(PALETTEENTRY));
1011 }
1012 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1013 {
1014 ExFreePoolWithTag(pEntries, TAG_PALETTE);
1015 _SEH2_YIELD(return 0);
1016 }
1017 _SEH2_END
1018 }
1019 }
1020
1021 ret = 0;
1022 switch(iFunc)
1023 {
1024 case GdiPalAnimate:
1025 if (pEntries)
1026 ret = IntAnimatePalette((HPALETTE)hObj, iStart, cEntries, (CONST PPALETTEENTRY)pEntries);
1027 break;
1028
1029 case GdiPalSetEntries:
1030 if (pEntries)
1031 ret = IntSetPaletteEntries((HPALETTE)hObj, iStart, cEntries, (CONST LPPALETTEENTRY)pEntries);
1032 break;
1033
1034 case GdiPalGetEntries:
1035 ret = IntGetPaletteEntries((HPALETTE)hObj, iStart, cEntries, (LPPALETTEENTRY)pEntries);
1036 break;
1037
1038 case GdiPalGetSystemEntries:
1039 ret = IntGetSystemPaletteEntries((HDC)hObj, iStart, cEntries, (LPPALETTEENTRY)pEntries);
1040 break;
1041
1042 case GdiPalSetColorTable:
1043 if (pEntries)
1044 ret = IntSetDIBColorTable((HDC)hObj, iStart, cEntries, (RGBQUAD*)pEntries);
1045 break;
1046
1047 case GdiPalGetColorTable:
1048 if (pEntries)
1049 ret = IntGetDIBColorTable((HDC)hObj, iStart, cEntries, (RGBQUAD*)pEntries);
1050 break;
1051 }
1052
1053 if (pEntries)
1054 {
1055 if (!bInbound)
1056 {
1057 _SEH2_TRY
1058 {
1059 ProbeForWrite(pUnsafeEntries, cEntries * sizeof(PALETTEENTRY), 1);
1060 memcpy(pUnsafeEntries, pEntries, cEntries * sizeof(PALETTEENTRY));
1061 }
1062 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1063 {
1064 ret = 0;
1065 }
1066 _SEH2_END
1067 }
1068 ExFreePoolWithTag(pEntries, TAG_PALETTE);
1069 }
1070
1071 return ret;
1072 }
1073
1074 UINT APIENTRY
1075 NtGdiSetSystemPaletteUse(HDC hDC, UINT Usage)
1076 {
1077 UINT old = SystemPaletteUse;
1078
1079 /* Device doesn't support colour palettes */
1080 if (!(NtGdiGetDeviceCaps(hDC, RASTERCAPS) & RC_PALETTE)) {
1081 return SYSPAL_ERROR;
1082 }
1083
1084 switch (Usage)
1085 {
1086 case SYSPAL_NOSTATIC:
1087 case SYSPAL_NOSTATIC256:
1088 case SYSPAL_STATIC:
1089 SystemPaletteUse = Usage;
1090 break;
1091
1092 default:
1093 old=SYSPAL_ERROR;
1094 break;
1095 }
1096
1097 return old;
1098 }
1099
1100 UINT
1101 APIENTRY
1102 NtGdiGetSystemPaletteUse(HDC hDC)
1103 {
1104 return SystemPaletteUse;
1105 }
1106
1107 BOOL
1108 APIENTRY
1109 NtGdiUpdateColors(HDC hDC)
1110 {
1111 PWINDOW_OBJECT Wnd;
1112 BOOL calledFromUser, ret;
1113 USER_REFERENCE_ENTRY Ref;
1114
1115 calledFromUser = UserIsEntered();
1116
1117 if (!calledFromUser){
1118 UserEnterExclusive();
1119 }
1120
1121 Wnd = UserGetWindowObject(IntWindowFromDC(hDC));
1122 if (Wnd == NULL)
1123 {
1124 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1125
1126 if (!calledFromUser){
1127 UserLeave();
1128 }
1129
1130 return FALSE;
1131 }
1132
1133 UserRefObjectCo(Wnd, &Ref);
1134 ret = co_UserRedrawWindow(Wnd, NULL, 0, RDW_INVALIDATE);
1135 UserDerefObjectCo(Wnd);
1136
1137 if (!calledFromUser){
1138 UserLeave();
1139 }
1140
1141 return ret;
1142 }
1143
1144 BOOL
1145 APIENTRY
1146 NtGdiUnrealizeObject(HGDIOBJ hgdiobj)
1147 {
1148 BOOL Ret = FALSE;
1149 PPALETTE palGDI;
1150
1151 if ( !hgdiobj ||
1152 ((UINT)hgdiobj & GDI_HANDLE_STOCK_MASK) ||
1153 !GDI_HANDLE_IS_TYPE(hgdiobj, GDI_OBJECT_TYPE_PALETTE) )
1154 return Ret;
1155
1156 palGDI = PALETTE_LockPalette(hgdiobj);
1157 if (!palGDI) return FALSE;
1158
1159 // FIXME!!
1160 // Need to do something!!!
1161 // Zero out Current and Old Translated pointers?
1162 //
1163 Ret = TRUE;
1164 PALETTE_UnlockPalette(palGDI);
1165 return Ret;
1166 }
1167
1168
1169 /* EOF */