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