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