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