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