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