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