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