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