8fcbbe4077c50b699e6f991705c02edb2960ecf8
[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 <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;
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 }
851 else
852 {
853 Entries = numEntries;
854 }
855
856 PALETTE_UnlockPalette(palGDI);
857 return Entries;
858 }
859
860 UINT APIENTRY
861 IntGetSystemPaletteEntries(HDC hDC,
862 UINT StartIndex,
863 UINT Entries,
864 LPPALETTEENTRY pe)
865 {
866 PPALETTE palGDI = NULL;
867 PDC dc = NULL;
868 UINT EntriesSize = 0;
869 UINT Ret = 0;
870
871 if (Entries == 0)
872 {
873 SetLastWin32Error(ERROR_INVALID_PARAMETER);
874 return 0;
875 }
876
877 if (pe != NULL)
878 {
879 EntriesSize = Entries * sizeof(pe[0]);
880 if (Entries != EntriesSize / sizeof(pe[0]))
881 {
882 /* Integer overflow! */
883 SetLastWin32Error(ERROR_INVALID_PARAMETER);
884 return 0;
885 }
886 }
887
888 if (!(dc = DC_LockDc(hDC)))
889 {
890 SetLastWin32Error(ERROR_INVALID_HANDLE);
891 return 0;
892 }
893
894 palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
895 if (palGDI != NULL)
896 {
897 if (pe != NULL)
898 {
899 if (StartIndex >= palGDI->NumColors)
900 Entries = 0;
901 else if (Entries > palGDI->NumColors - StartIndex)
902 Entries = palGDI->NumColors - StartIndex;
903
904 memcpy(pe,
905 palGDI->IndexedColors + StartIndex,
906 Entries * sizeof(pe[0]));
907
908 Ret = Entries;
909 }
910 else
911 {
912 Ret = dc->ppdev->gdiinfo.ulNumPalReg;
913 }
914 }
915
916 if (palGDI != NULL)
917 PALETTE_UnlockPalette(palGDI);
918
919 if (dc != NULL)
920 DC_UnlockDc(dc);
921
922 return Ret;
923 }
924
925 UINT
926 APIENTRY
927 IntSetPaletteEntries(
928 HPALETTE hpal,
929 UINT Start,
930 UINT Entries,
931 CONST LPPALETTEENTRY pe)
932 {
933 PPALETTE palGDI;
934 WORD numEntries;
935
936 if ((UINT)hpal & GDI_HANDLE_STOCK_MASK)
937 {
938 return 0;
939 }
940
941 palGDI = PALETTE_LockPalette(hpal);
942 if (!palGDI) return 0;
943
944 numEntries = palGDI->NumColors;
945 if (Start >= numEntries)
946 {
947 PALETTE_UnlockPalette(palGDI);
948 return 0;
949 }
950 if (numEntries < Start + Entries)
951 {
952 Entries = numEntries - Start;
953 }
954 memcpy(palGDI->IndexedColors + Start, pe, Entries * sizeof(PALETTEENTRY));
955 PALETTE_UnlockPalette(palGDI);
956
957 return Entries;
958 }
959
960 W32KAPI
961 LONG
962 APIENTRY
963 NtGdiDoPalette(
964 IN HGDIOBJ hObj,
965 IN WORD iStart,
966 IN WORD cEntries,
967 IN LPVOID pUnsafeEntries,
968 IN DWORD iFunc,
969 IN BOOL bInbound)
970 {
971 LONG ret;
972 LPVOID pEntries = NULL;
973
974 /* FIXME: Handle bInbound correctly */
975
976 if (bInbound &&
977 (pUnsafeEntries == NULL || cEntries == 0))
978 {
979 return 0;
980 }
981
982 if (pUnsafeEntries)
983 {
984 pEntries = ExAllocatePool(PagedPool, cEntries * sizeof(PALETTEENTRY));
985 if (!pEntries)
986 return 0;
987 if (bInbound)
988 {
989 _SEH2_TRY
990 {
991 ProbeForRead(pUnsafeEntries, cEntries * sizeof(PALETTEENTRY), 1);
992 memcpy(pEntries, pUnsafeEntries, cEntries * sizeof(PALETTEENTRY));
993 }
994 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
995 {
996 ExFreePool(pEntries);
997 _SEH2_YIELD(return 0);
998 }
999 _SEH2_END
1000 }
1001 }
1002
1003 ret = 0;
1004 switch(iFunc)
1005 {
1006 case GdiPalAnimate:
1007 if (pEntries)
1008 ret = IntAnimatePalette((HPALETTE)hObj, iStart, cEntries, (CONST PPALETTEENTRY)pEntries);
1009 break;
1010
1011 case GdiPalSetEntries:
1012 if (pEntries)
1013 ret = IntSetPaletteEntries((HPALETTE)hObj, iStart, cEntries, (CONST LPPALETTEENTRY)pEntries);
1014 break;
1015
1016 case GdiPalGetEntries:
1017 ret = IntGetPaletteEntries((HPALETTE)hObj, iStart, cEntries, (LPPALETTEENTRY)pEntries);
1018 break;
1019
1020 case GdiPalGetSystemEntries:
1021 ret = IntGetSystemPaletteEntries((HDC)hObj, iStart, cEntries, (LPPALETTEENTRY)pEntries);
1022 break;
1023
1024 case GdiPalSetColorTable:
1025 if (pEntries)
1026 ret = IntSetDIBColorTable((HDC)hObj, iStart, cEntries, (RGBQUAD*)pEntries);
1027 break;
1028
1029 case GdiPalGetColorTable:
1030 if (pEntries)
1031 ret = IntGetDIBColorTable((HDC)hObj, iStart, cEntries, (RGBQUAD*)pEntries);
1032 break;
1033 }
1034
1035 if (pEntries)
1036 {
1037 if (!bInbound)
1038 {
1039 _SEH2_TRY
1040 {
1041 ProbeForWrite(pUnsafeEntries, cEntries * sizeof(PALETTEENTRY), 1);
1042 memcpy(pUnsafeEntries, pEntries, cEntries * sizeof(PALETTEENTRY));
1043 }
1044 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1045 {
1046 ret = 0;
1047 }
1048 _SEH2_END
1049 }
1050 ExFreePool(pEntries);
1051 }
1052
1053 return ret;
1054 }
1055
1056 UINT APIENTRY
1057 NtGdiSetSystemPaletteUse(HDC hDC, UINT Usage)
1058 {
1059 UINT old = SystemPaletteUse;
1060
1061 /* Device doesn't support colour palettes */
1062 if (!(NtGdiGetDeviceCaps(hDC, RASTERCAPS) & RC_PALETTE)) {
1063 return SYSPAL_ERROR;
1064 }
1065
1066 switch (Usage)
1067 {
1068 case SYSPAL_NOSTATIC:
1069 case SYSPAL_NOSTATIC256:
1070 case SYSPAL_STATIC:
1071 SystemPaletteUse = Usage;
1072 break;
1073
1074 default:
1075 old=SYSPAL_ERROR;
1076 break;
1077 }
1078
1079 return old;
1080 }
1081
1082 UINT
1083 APIENTRY
1084 NtGdiGetSystemPaletteUse(HDC hDC)
1085 {
1086 return SystemPaletteUse;
1087 }
1088
1089 BOOL
1090 APIENTRY
1091 NtGdiUpdateColors(HDC hDC)
1092 {
1093 PWINDOW_OBJECT Wnd;
1094 BOOL calledFromUser, ret;
1095 USER_REFERENCE_ENTRY Ref;
1096
1097 calledFromUser = UserIsEntered();
1098
1099 if (!calledFromUser){
1100 UserEnterExclusive();
1101 }
1102
1103 Wnd = UserGetWindowObject(IntWindowFromDC(hDC));
1104 if (Wnd == NULL)
1105 {
1106 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
1107
1108 if (!calledFromUser){
1109 UserLeave();
1110 }
1111
1112 return FALSE;
1113 }
1114
1115 UserRefObjectCo(Wnd, &Ref);
1116 ret = co_UserRedrawWindow(Wnd, NULL, 0, RDW_INVALIDATE);
1117 UserDerefObjectCo(Wnd);
1118
1119 if (!calledFromUser){
1120 UserLeave();
1121 }
1122
1123 return ret;
1124 }
1125
1126 BOOL
1127 APIENTRY
1128 NtGdiUnrealizeObject(HGDIOBJ hgdiobj)
1129 {
1130 BOOL Ret = FALSE;
1131 PPALETTE palGDI;
1132
1133 if ( !hgdiobj ||
1134 ((UINT)hgdiobj & GDI_HANDLE_STOCK_MASK) ||
1135 !GDI_HANDLE_IS_TYPE(hgdiobj, GDI_OBJECT_TYPE_PALETTE) )
1136 return Ret;
1137
1138 palGDI = PALETTE_LockPalette(hgdiobj);
1139 if (!palGDI) return FALSE;
1140
1141 // FIXME!!
1142 // Need to do something!!!
1143 // Zero out Current and Old Translated pointers?
1144 //
1145 Ret = TRUE;
1146 PALETTE_UnlockPalette(palGDI);
1147 return Ret;
1148 }
1149
1150
1151 /* EOF */