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