[WIN32K]
[reactos.git] / reactos / subsystems / win32 / win32k / objects / palette.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI Palette Functions
5 * FILE: subsys/win32k/eng/palette.c
6 * PROGRAMERS: Jason Filby
7 * Timo Kreuzer
8 */
9
10 #include <win32k.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 static UINT SystemPaletteUse = SYSPAL_NOSTATIC; /* the program need save the pallete and restore it */
16
17 PALETTE gpalRGB, gpalBGR, gpalMono, 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 INIT_FUNCTION
61 NTSTATUS
62 NTAPI
63 InitPaletteImpl()
64 {
65 int i;
66 HPALETTE hpalette;
67 PLOGPALETTE palPtr;
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 STATUS_NO_MEMORY;
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 /* palette_size = visual->map_entries; */
90
91 gpalRGB.flFlags = PAL_RGB;
92 gpalRGB.RedMask = RGB(0xFF, 0x00, 0x00);
93 gpalRGB.GreenMask = RGB(0x00, 0xFF, 0x00);
94 gpalRGB.BlueMask = RGB(0x00, 0x00, 0xFF);
95 gpalRGB.BaseObject.ulShareCount = 0;
96 gpalRGB.BaseObject.BaseFlags = 0 ;
97
98 gpalBGR.flFlags = PAL_BGR;
99 gpalBGR.RedMask = RGB(0x00, 0x00, 0xFF);
100 gpalBGR.GreenMask = RGB(0x00, 0xFF, 0x00);
101 gpalBGR.BlueMask = RGB(0xFF, 0x00, 0x00);
102 gpalBGR.BaseObject.ulShareCount = 0;
103 gpalBGR.BaseObject.BaseFlags = 0 ;
104
105 gpalRGB555.flFlags = PAL_RGB16_555 | PAL_BITFIELDS;
106 gpalRGB555.RedMask = 0x7C00;
107 gpalRGB555.GreenMask = 0x3E0;
108 gpalRGB555.BlueMask = 0x1F;
109 gpalRGB555.BaseObject.ulShareCount = 0;
110 gpalRGB555.BaseObject.BaseFlags = 0 ;
111
112 gpalRGB565.flFlags = PAL_RGB16_565 | PAL_BITFIELDS;
113 gpalRGB565.RedMask = 0xF800;
114 gpalRGB565.GreenMask = 0x7E0;
115 gpalRGB565.BlueMask = 0x1F;
116 gpalRGB565.BaseObject.ulShareCount = 0;
117 gpalRGB565.BaseObject.BaseFlags = 0 ;
118
119 memset(&gpalMono, 0, sizeof(PALETTE));
120 gpalMono.flFlags = PAL_MONOCHROME;
121 gpalMono.BaseObject.ulShareCount = 0;
122 gpalMono.BaseObject.BaseFlags = 0 ;
123
124 /* Initialize default surface palettes */
125 gppalDefault = PALETTE_ShareLockPalette(hpalette);
126 appalSurfaceDefault[BMF_1BPP] = &gpalMono;
127 appalSurfaceDefault[BMF_4BPP] = gppalDefault;
128 appalSurfaceDefault[BMF_8BPP] = gppalDefault;
129 appalSurfaceDefault[BMF_16BPP] = &gpalRGB565;
130 appalSurfaceDefault[BMF_24BPP] = &gpalBGR;
131 appalSurfaceDefault[BMF_32BPP] = &gpalBGR;
132 appalSurfaceDefault[BMF_4RLE] = gppalDefault;
133 appalSurfaceDefault[BMF_8RLE] = gppalDefault;
134 appalSurfaceDefault[BMF_JPEG] = &gpalRGB;
135 appalSurfaceDefault[BMF_PNG] = &gpalRGB;
136
137 return STATUS_SUCCESS;
138 }
139
140 VOID FASTCALL PALETTE_ValidateFlags(PALETTEENTRY* lpPalE, INT size)
141 {
142 int i = 0;
143 for (; i<size ; i++)
144 lpPalE[i].peFlags = PC_SYS_USED | (lpPalE[i].peFlags & 0x07);
145 }
146
147 HPALETTE
148 FASTCALL
149 PALETTE_AllocPalette(ULONG Mode,
150 ULONG NumColors,
151 ULONG *Colors,
152 ULONG Red,
153 ULONG Green,
154 ULONG Blue)
155 {
156 HPALETTE NewPalette;
157 PPALETTE PalGDI;
158
159 PalGDI = (PPALETTE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_PALETTE);
160 if (!PalGDI)
161 {
162 return NULL;
163 }
164
165 NewPalette = PalGDI->BaseObject.hHmgr;
166
167 PalGDI->Self = NewPalette;
168 PalGDI->flFlags = Mode;
169
170 if (NULL != Colors)
171 {
172 PalGDI->IndexedColors = ExAllocatePoolWithTag(PagedPool,
173 sizeof(PALETTEENTRY) * NumColors,
174 TAG_PALETTE);
175 if (NULL == PalGDI->IndexedColors)
176 {
177 PALETTE_UnlockPalette(PalGDI);
178 PALETTE_FreePaletteByHandle(NewPalette);
179 return NULL;
180 }
181 RtlCopyMemory(PalGDI->IndexedColors, Colors, sizeof(PALETTEENTRY) * NumColors);
182 }
183
184 if (Mode & PAL_INDEXED)
185 {
186 PalGDI->NumColors = NumColors;
187 }
188 else if (Mode & PAL_BITFIELDS)
189 {
190 PalGDI->RedMask = Red;
191 PalGDI->GreenMask = Green;
192 PalGDI->BlueMask = Blue;
193
194 if (Red == 0x7c00 && Green == 0x3E0 && Blue == 0x1F)
195 PalGDI->flFlags |= PAL_RGB16_555;
196 else if (Red == 0xF800 && Green == 0x7E0 && Blue == 0x1F)
197 PalGDI->flFlags |= PAL_RGB16_565;
198 else if (Red == 0xFF0000 && Green == 0xFF00 && Blue == 0xFF)
199 PalGDI->flFlags |= PAL_BGR;
200 }
201
202 PALETTE_UnlockPalette(PalGDI);
203
204 return NewPalette;
205 }
206
207 HPALETTE
208 FASTCALL
209 PALETTE_AllocPaletteIndexedRGB(ULONG NumColors,
210 CONST RGBQUAD *Colors)
211 {
212 HPALETTE NewPalette;
213 PPALETTE PalGDI;
214 UINT i;
215
216 PalGDI = (PPALETTE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_PALETTE);
217 if (!PalGDI)
218 {
219 return NULL;
220 }
221
222 NewPalette = PalGDI->BaseObject.hHmgr;
223
224 PalGDI->Self = NewPalette;
225 PalGDI->flFlags = PAL_INDEXED;
226
227 PalGDI->IndexedColors = ExAllocatePoolWithTag(PagedPool,
228 sizeof(PALETTEENTRY) * NumColors,
229 TAG_PALETTE);
230 if (NULL == PalGDI->IndexedColors)
231 {
232 PALETTE_UnlockPalette(PalGDI);
233 PALETTE_FreePaletteByHandle(NewPalette);
234 return NULL;
235 }
236
237 for (i = 0; i < NumColors; i++)
238 {
239 PalGDI->IndexedColors[i].peRed = Colors[i].rgbRed;
240 PalGDI->IndexedColors[i].peGreen = Colors[i].rgbGreen;
241 PalGDI->IndexedColors[i].peBlue = Colors[i].rgbBlue;
242 PalGDI->IndexedColors[i].peFlags = 0;
243 }
244
245 PalGDI->NumColors = NumColors;
246
247 PALETTE_UnlockPalette(PalGDI);
248
249 return NewPalette;
250 }
251
252 BOOL INTERNAL_CALL
253 PALETTE_Cleanup(PVOID ObjectBody)
254 {
255 PPALETTE pPal = (PPALETTE)ObjectBody;
256 if (NULL != pPal->IndexedColors)
257 {
258 ExFreePoolWithTag(pPal->IndexedColors, TAG_PALETTE);
259 }
260
261 return TRUE;
262 }
263
264 INT FASTCALL
265 PALETTE_GetObject(PPALETTE ppal, INT cbCount, LPLOGBRUSH lpBuffer)
266 {
267 if (!lpBuffer)
268 {
269 return sizeof(WORD);
270 }
271
272 if ((UINT)cbCount < sizeof(WORD)) return 0;
273 *((WORD*)lpBuffer) = (WORD)ppal->NumColors;
274 return sizeof(WORD);
275 }
276
277 ULONG
278 NTAPI
279 PALETTE_ulGetNearestPaletteIndex(PALETTE* ppal, ULONG iColor)
280 {
281 ULONG ulDiff, ulColorDiff, ulMinimalDiff = 0xFFFFFF;
282 ULONG i, ulBestIndex = 0;
283 PALETTEENTRY peColor = *(PPALETTEENTRY)&iColor;
284
285 /* Loop all palette entries, break on exact match */
286 for (i = 0; i < ppal->NumColors && ulMinimalDiff != 0; i++)
287 {
288 /* Calculate distance in the color cube */
289 ulDiff = peColor.peRed - ppal->IndexedColors[i].peRed;
290 ulColorDiff = ulDiff * ulDiff;
291 ulDiff = peColor.peGreen - ppal->IndexedColors[i].peGreen;
292 ulColorDiff += ulDiff * ulDiff;
293 ulDiff = peColor.peBlue - ppal->IndexedColors[i].peBlue;
294 ulColorDiff += ulDiff * ulDiff;
295
296 /* Check for a better match */
297 if (ulColorDiff < ulMinimalDiff)
298 {
299 ulBestIndex = i;
300 ulMinimalDiff = ulColorDiff;
301 }
302 }
303
304 return ulBestIndex;
305 }
306
307 ULONG
308 NTAPI
309 PALETTE_ulGetNearestBitFieldsIndex(PALETTE* ppal, ULONG ulColor)
310 {
311 ULONG ulNewColor;
312
313 // FIXME: HACK, should be stored already
314 ppal->ulRedShift = CalculateShift(RGB(0xff,0,0), ppal->RedMask);
315 ppal->ulGreenShift = CalculateShift(RGB(0,0xff,0), ppal->GreenMask);
316 ppal->ulBlueShift = CalculateShift(RGB(0,0,0xff), ppal->BlueMask);
317
318 ulNewColor = _rotl(ulColor, ppal->ulRedShift) & ppal->RedMask;
319 ulNewColor |= _rotl(ulColor, ppal->ulGreenShift) & ppal->GreenMask;
320 ulNewColor |= _rotl(ulColor, ppal->ulBlueShift) & ppal->BlueMask;
321
322 return ulNewColor;
323 }
324
325 ULONG
326 NTAPI
327 PALETTE_ulGetNearestIndex(PALETTE* ppal, ULONG ulColor)
328 {
329 if (ppal->flFlags & PAL_INDEXED) // use fl & PALINDEXED
330 return PALETTE_ulGetNearestPaletteIndex(ppal, ulColor);
331 else
332 return PALETTE_ulGetNearestBitFieldsIndex(ppal, ulColor);
333 }
334
335 VOID
336 NTAPI
337 PALETTE_vGetBitMasks(PPALETTE ppal, PULONG pulColors)
338 {
339 ASSERT(pulColors);
340
341 if (ppal->flFlags & PAL_INDEXED || ppal->flFlags & PAL_RGB)
342 {
343 pulColors[0] = RGB(0xFF, 0x00, 0x00);
344 pulColors[1] = RGB(0x00, 0xFF, 0x00);
345 pulColors[2] = RGB(0x00, 0x00, 0xFF);
346 }
347 else if (ppal->flFlags & PAL_BGR)
348 {
349 pulColors[0] = RGB(0x00, 0x00, 0xFF);
350 pulColors[1] = RGB(0x00, 0xFF, 0x00);
351 pulColors[2] = RGB(0xFF, 0x00, 0x00);
352 }
353 else if (ppal->flFlags & PAL_BITFIELDS)
354 {
355 pulColors[0] = ppal->RedMask;
356 pulColors[1] = ppal->GreenMask;
357 pulColors[2] = ppal->BlueMask;
358 }
359 }
360
361 VOID
362 FASTCALL
363 ColorCorrection(PPALETTE PalGDI, PPALETTEENTRY PaletteEntry, ULONG Colors)
364 {
365 PPDEVOBJ ppdev = (PPDEVOBJ)PalGDI->hPDev;
366
367 if (!ppdev) return;
368
369 if (ppdev->flFlags & PDEV_GAMMARAMP_TABLE)
370 {
371 INT i;
372 PGAMMARAMP GammaRamp = (PGAMMARAMP)ppdev->pvGammaRamp;
373 for ( i = 0; i < Colors; i++)
374 {
375 PaletteEntry[i].peRed += GammaRamp->Red[i];
376 PaletteEntry[i].peGreen += GammaRamp->Green[i];
377 PaletteEntry[i].peBlue += GammaRamp->Blue[i];
378 }
379 }
380 return;
381 }
382
383 /** Display Driver Interface **************************************************/
384
385 /*
386 * @implemented
387 */
388 HPALETTE
389 APIENTRY
390 EngCreatePalette(
391 ULONG Mode,
392 ULONG NumColors,
393 ULONG *Colors,
394 ULONG Red,
395 ULONG Green,
396 ULONG Blue)
397 {
398 HPALETTE Palette;
399
400 Palette = PALETTE_AllocPalette(Mode, NumColors, Colors, Red, Green, Blue);
401 if (Palette != NULL)
402 {
403 GDIOBJ_SetOwnership(Palette, NULL);
404 }
405
406 return Palette;
407 }
408
409 /*
410 * @implemented
411 */
412 BOOL
413 APIENTRY
414 EngDeletePalette(IN HPALETTE Palette)
415 {
416 GDIOBJ_SetOwnership(Palette, PsGetCurrentProcess());
417
418 return PALETTE_FreePaletteByHandle(Palette);
419 }
420
421 /*
422 * @implemented
423 */
424 ULONG
425 APIENTRY
426 PALOBJ_cGetColors(PALOBJ *PalObj, ULONG Start, ULONG Colors, ULONG *PaletteEntry)
427 {
428 PALETTE *PalGDI;
429
430 PalGDI = (PALETTE*)PalObj;
431 /* PalGDI = (PALETTE*)AccessInternalObjectFromUserObject(PalObj); */
432
433 if (Start >= PalGDI->NumColors)
434 return 0;
435
436 Colors = min(Colors, PalGDI->NumColors - Start);
437
438 /* NOTE: PaletteEntry ULONGs are in the same order as PALETTEENTRY. */
439 RtlCopyMemory(PaletteEntry, PalGDI->IndexedColors + Start, sizeof(ULONG) * Colors);
440
441 if (PalGDI->flFlags & PAL_GAMMACORRECTION)
442 ColorCorrection(PalGDI, (PPALETTEENTRY)PaletteEntry, Colors);
443
444 return Colors;
445 }
446
447
448 /** Systemcall Interface ******************************************************/
449
450 /*
451 * @implemented
452 */
453 HPALETTE APIENTRY
454 NtGdiCreatePaletteInternal ( IN LPLOGPALETTE pLogPal, IN UINT cEntries )
455 {
456 PPALETTE PalGDI;
457 HPALETTE NewPalette;
458
459 pLogPal->palNumEntries = cEntries;
460 NewPalette = PALETTE_AllocPalette( PAL_INDEXED,
461 cEntries,
462 (PULONG)pLogPal->palPalEntry,
463 0, 0, 0);
464
465 if (NewPalette == NULL)
466 {
467 return NULL;
468 }
469
470 PalGDI = (PPALETTE) PALETTE_LockPalette(NewPalette);
471 if (PalGDI != NULL)
472 {
473 PALETTE_ValidateFlags(PalGDI->IndexedColors, PalGDI->NumColors);
474 PALETTE_UnlockPalette(PalGDI);
475 }
476 else
477 {
478 /* FIXME - Handle PalGDI == NULL!!!! */
479 DPRINT1("PalGDI is NULL\n");
480 }
481 return NewPalette;
482 }
483
484 HPALETTE APIENTRY NtGdiCreateHalftonePalette(HDC hDC)
485 {
486 int i, r, g, b;
487 struct {
488 WORD Version;
489 WORD NumberOfEntries;
490 PALETTEENTRY aEntries[256];
491 } Palette;
492
493 Palette.Version = 0x300;
494 Palette.NumberOfEntries = 256;
495 if (IntGetSystemPaletteEntries(hDC, 0, 256, Palette.aEntries) == 0)
496 {
497 /* from wine, more that 256 color math */
498 Palette.NumberOfEntries = 20;
499 for (i = 0; i < Palette.NumberOfEntries; i++)
500 {
501 Palette.aEntries[i].peRed=0xff;
502 Palette.aEntries[i].peGreen=0xff;
503 Palette.aEntries[i].peBlue=0xff;
504 Palette.aEntries[i].peFlags=0x00;
505 }
506
507 Palette.aEntries[0].peRed=0x00;
508 Palette.aEntries[0].peBlue=0x00;
509 Palette.aEntries[0].peGreen=0x00;
510
511 /* the first 6 */
512 for (i=1; i <= 6; i++)
513 {
514 Palette.aEntries[i].peRed=(i%2)?0x80:0;
515 Palette.aEntries[i].peGreen=(i==2)?0x80:(i==3)?0x80:(i==6)?0x80:0;
516 Palette.aEntries[i].peBlue=(i>3)?0x80:0;
517 }
518
519 for (i=7; i <= 12; i++)
520 {
521 switch(i)
522 {
523 case 7:
524 Palette.aEntries[i].peRed=0xc0;
525 Palette.aEntries[i].peBlue=0xc0;
526 Palette.aEntries[i].peGreen=0xc0;
527 break;
528 case 8:
529 Palette.aEntries[i].peRed=0xc0;
530 Palette.aEntries[i].peGreen=0xdc;
531 Palette.aEntries[i].peBlue=0xc0;
532 break;
533 case 9:
534 Palette.aEntries[i].peRed=0xa6;
535 Palette.aEntries[i].peGreen=0xca;
536 Palette.aEntries[i].peBlue=0xf0;
537 break;
538 case 10:
539 Palette.aEntries[i].peRed=0xff;
540 Palette.aEntries[i].peGreen=0xfb;
541 Palette.aEntries[i].peBlue=0xf0;
542 break;
543 case 11:
544 Palette.aEntries[i].peRed=0xa0;
545 Palette.aEntries[i].peGreen=0xa0;
546 Palette.aEntries[i].peBlue=0xa4;
547 break;
548 case 12:
549 Palette.aEntries[i].peRed=0x80;
550 Palette.aEntries[i].peGreen=0x80;
551 Palette.aEntries[i].peBlue=0x80;
552 }
553 }
554
555 for (i=13; i <= 18; i++)
556 {
557 Palette.aEntries[i].peRed=(i%2)?0xff:0;
558 Palette.aEntries[i].peGreen=(i==14)?0xff:(i==15)?0xff:(i==18)?0xff:0;
559 Palette.aEntries[i].peBlue=(i>15)?0xff:0x00;
560 }
561 }
562 else
563 {
564 /* 256 color table */
565 for (r = 0; r < 6; r++)
566 for (g = 0; g < 6; g++)
567 for (b = 0; b < 6; b++)
568 {
569 i = r + g*6 + b*36 + 10;
570 Palette.aEntries[i].peRed = r * 51;
571 Palette.aEntries[i].peGreen = g * 51;
572 Palette.aEntries[i].peBlue = b * 51;
573 }
574
575 for (i = 216; i < 246; i++)
576 {
577 int v = (i - 216) << 3;
578 Palette.aEntries[i].peRed = v;
579 Palette.aEntries[i].peGreen = v;
580 Palette.aEntries[i].peBlue = v;
581 }
582 }
583
584 return NtGdiCreatePaletteInternal((LOGPALETTE *)&Palette, Palette.NumberOfEntries);
585 }
586
587 BOOL
588 APIENTRY
589 NtGdiResizePalette(
590 HPALETTE hpal,
591 UINT Entries)
592 {
593 /* PALOBJ *palPtr = (PALOBJ*)AccessUserObject(hPal);
594 UINT cPrevEnt, prevVer;
595 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
596 XLATEOBJ *XlateObj = NULL;
597
598 if(!palPtr) return FALSE;
599 cPrevEnt = palPtr->logpalette->palNumEntries;
600 prevVer = palPtr->logpalette->palVersion;
601 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
602 size += sizeof(int*) + sizeof(GDIOBJHDR);
603 XlateObj = palPtr->logicalToSystem;
604
605 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
606
607 if(XlateObj)
608 {
609 XLATEOBJ *NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
610 if(NewXlateObj == NULL)
611 {
612 ERR("Can not resize logicalToSystem -- out of memory!");
613 GDI_ReleaseObj( hPal );
614 return FALSE;
615 }
616 palPtr->logicalToSystem = NewXlateObj;
617 }
618
619 if(cEntries > cPrevEnt)
620 {
621 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
622 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
623 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
624 }
625 palPtr->logpalette->palNumEntries = cEntries;
626 palPtr->logpalette->palVersion = prevVer;
627 // GDI_ReleaseObj( hPal );
628 return TRUE; */
629
630 UNIMPLEMENTED;
631 return FALSE;
632 }
633
634 BOOL
635 APIENTRY
636 NtGdiGetColorAdjustment(
637 HDC hdc,
638 LPCOLORADJUSTMENT pca)
639 {
640 UNIMPLEMENTED;
641 return FALSE;
642 }
643
644 BOOL
645 APIENTRY
646 NtGdiSetColorAdjustment(
647 HDC hdc,
648 LPCOLORADJUSTMENT pca)
649 {
650 UNIMPLEMENTED;
651 return FALSE;
652 }
653
654 COLORREF APIENTRY NtGdiGetNearestColor(HDC hDC, COLORREF Color)
655 {
656 COLORREF nearest = CLR_INVALID;
657 PDC dc;
658 PPALETTE palGDI;
659 LONG RBits, GBits, BBits;
660
661 dc = DC_LockDc(hDC);
662 if (NULL != dc)
663 {
664 HPALETTE hpal = dc->dclevel.hpal;
665 palGDI = (PPALETTE) PALETTE_LockPalette(hpal);
666 if (!palGDI)
667 {
668 DC_UnlockDc(dc);
669 return nearest;
670 }
671
672 if (palGDI->flFlags & PAL_INDEXED)
673 {
674 ULONG index;
675 index = PALETTE_ulGetNearestPaletteIndex(palGDI, Color);
676 nearest = PALETTE_ulGetRGBColorFromIndex(palGDI, index);
677 }
678 else if (palGDI->flFlags & PAL_RGB || palGDI->flFlags & PAL_BGR)
679 {
680 nearest = Color;
681 }
682 else if (palGDI->flFlags & PAL_BITFIELDS)
683 {
684 RBits = 8 - GetNumberOfBits(palGDI->RedMask);
685 GBits = 8 - GetNumberOfBits(palGDI->GreenMask);
686 BBits = 8 - GetNumberOfBits(palGDI->BlueMask);
687 nearest = RGB(
688 (GetRValue(Color) >> RBits) << RBits,
689 (GetGValue(Color) >> GBits) << GBits,
690 (GetBValue(Color) >> BBits) << BBits);
691 }
692 PALETTE_UnlockPalette(palGDI);
693 DC_UnlockDc(dc);
694 }
695
696 return nearest;
697 }
698
699 UINT
700 APIENTRY
701 NtGdiGetNearestPaletteIndex(
702 HPALETTE hpal,
703 COLORREF crColor)
704 {
705 PPALETTE ppal = (PPALETTE) PALETTE_LockPalette(hpal);
706 UINT index = 0;
707
708 if (ppal)
709 {
710 if (ppal->flFlags & PAL_INDEXED)
711 {
712 /* Return closest match for the given RGB color */
713 index = PALETTE_ulGetNearestPaletteIndex(ppal, crColor);
714 }
715 // else SetLastError ?
716 PALETTE_UnlockPalette(ppal);
717 }
718
719 return index;
720 }
721
722 UINT
723 FASTCALL
724 IntGdiRealizePalette(HDC hDC)
725 {
726 /*
727 * This function doesn't do any real work now and there's plenty
728 * of bugs in it.
729 */
730
731 PPALETTE palGDI, sysGDI;
732 int realized = 0;
733 PDC dc;
734 HPALETTE systemPalette;
735
736 dc = DC_LockDc(hDC);
737 if (!dc) return 0;
738
739 systemPalette = NtGdiGetStockObject(DEFAULT_PALETTE);
740 palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
741
742 if (palGDI == NULL)
743 {
744 DPRINT1("IntGdiRealizePalette(): palGDI is NULL, exiting\n");
745 DC_UnlockDc(dc);
746 return 0;
747 }
748
749 sysGDI = PALETTE_LockPalette(systemPalette);
750
751 if (sysGDI == NULL)
752 {
753 DPRINT1("IntGdiRealizePalette(): sysGDI is NULL, exiting\n");
754 PALETTE_UnlockPalette(palGDI);
755 DC_UnlockDc(dc);
756 return 0;
757 }
758
759 // The RealizePalette function modifies the palette for the device associated with the specified device context. If the
760 // device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device
761 // context is a display DC, the physical palette for that device is modified.
762 if(dc->dctype == DC_TYPE_MEMORY)
763 {
764 // Memory managed DC
765 DPRINT1("RealizePalette unimplemented for memory managed DCs\n");
766 } else
767 {
768 DPRINT1("RealizePalette unimplemented for device DCs\n");
769 }
770
771 // need to pass this to IntEngCreateXlate with palettes unlocked
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 PWND 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 = ExAllocatePoolWithTag(PagedPool, cEntries * sizeof(PALETTEENTRY), TAG_PALETTE);
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 ExFreePoolWithTag(pEntries, TAG_PALETTE);
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 ExFreePoolWithTag(pEntries, TAG_PALETTE);
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 PWND 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 */