[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 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(PDC pdc)
727 {
728 UINT i, realize = 0;
729 PALETTE *ppalSurf, *ppalDC;
730
731 ppalSurf = pdc->dclevel.pSurface->ppal;
732 ppalDC = pdc->dclevel.ppal;
733
734 if(!(ppalSurf->flFlags & PAL_INDEXED))
735 {
736 // FIXME : set error?
737 return 0;
738 }
739
740 ASSERT(ppalDC->flFlags & PAL_INDEXED);
741
742 // FIXME : should we resize ppalSurf if it's too small?
743 realize = (ppalDC->NumColors < ppalSurf->NumColors) ? ppalDC->NumColors : ppalSurf->NumColors;
744
745 for(i=0; i<realize; i++)
746 {
747 InterlockedExchange((LONG*)&ppalSurf->IndexedColors[i], *(LONG*)&ppalDC->IndexedColors[i]);
748 }
749
750 return realize;
751 }
752
753 UINT APIENTRY
754 IntAnimatePalette(HPALETTE hPal,
755 UINT StartIndex,
756 UINT NumEntries,
757 CONST PPALETTEENTRY PaletteColors)
758 {
759 UINT ret = 0;
760
761 if( hPal != NtGdiGetStockObject(DEFAULT_PALETTE) )
762 {
763 PPALETTE palPtr;
764 UINT pal_entries;
765 HDC hDC;
766 PDC dc;
767 PWND Wnd;
768 const PALETTEENTRY *pptr = PaletteColors;
769
770 palPtr = (PPALETTE)PALETTE_LockPalette(hPal);
771 if (!palPtr) return FALSE;
772
773 pal_entries = palPtr->NumColors;
774 if (StartIndex >= pal_entries)
775 {
776 PALETTE_UnlockPalette(palPtr);
777 return FALSE;
778 }
779 if (StartIndex+NumEntries > pal_entries) NumEntries = pal_entries - StartIndex;
780
781 for (NumEntries += StartIndex; StartIndex < NumEntries; StartIndex++, pptr++)
782 {
783 /* According to MSDN, only animate PC_RESERVED colours */
784 if (palPtr->IndexedColors[StartIndex].peFlags & PC_RESERVED)
785 {
786 memcpy( &palPtr->IndexedColors[StartIndex], pptr,
787 sizeof(PALETTEENTRY) );
788 ret++;
789 PALETTE_ValidateFlags(&palPtr->IndexedColors[StartIndex], 1);
790 }
791 }
792
793 PALETTE_UnlockPalette(palPtr);
794
795 /* Immediately apply the new palette if current window uses it */
796 Wnd = UserGetDesktopWindow();
797 hDC = UserGetWindowDC(Wnd);
798 dc = DC_LockDc(hDC);
799 if (NULL != dc)
800 {
801 if (dc->dclevel.hpal == hPal)
802 {
803 IntGdiRealizePalette(dc);
804 }
805 DC_UnlockDc(dc);
806 }
807 UserReleaseDC(Wnd,hDC, FALSE);
808 }
809 return ret;
810 }
811
812 UINT APIENTRY
813 IntGetPaletteEntries(
814 HPALETTE hpal,
815 UINT StartIndex,
816 UINT Entries,
817 LPPALETTEENTRY pe)
818 {
819 PPALETTE palGDI;
820 UINT numEntries;
821
822 palGDI = (PPALETTE) PALETTE_LockPalette(hpal);
823 if (NULL == palGDI)
824 {
825 return 0;
826 }
827
828 numEntries = palGDI->NumColors;
829 if (NULL != pe)
830 {
831 if (numEntries < StartIndex + Entries)
832 {
833 Entries = numEntries - StartIndex;
834 }
835 if (numEntries <= StartIndex)
836 {
837 PALETTE_UnlockPalette(palGDI);
838 return 0;
839 }
840 memcpy(pe, palGDI->IndexedColors + StartIndex, Entries * sizeof(PALETTEENTRY));
841 }
842 else
843 {
844 Entries = numEntries;
845 }
846
847 PALETTE_UnlockPalette(palGDI);
848 return Entries;
849 }
850
851 UINT APIENTRY
852 IntGetSystemPaletteEntries(HDC hDC,
853 UINT StartIndex,
854 UINT Entries,
855 LPPALETTEENTRY pe)
856 {
857 PPALETTE palGDI = NULL;
858 PDC dc = NULL;
859 UINT EntriesSize = 0;
860 UINT Ret = 0;
861
862 if (Entries == 0)
863 {
864 EngSetLastError(ERROR_INVALID_PARAMETER);
865 return 0;
866 }
867
868 if (pe != NULL)
869 {
870 EntriesSize = Entries * sizeof(pe[0]);
871 if (Entries != EntriesSize / sizeof(pe[0]))
872 {
873 /* Integer overflow! */
874 EngSetLastError(ERROR_INVALID_PARAMETER);
875 return 0;
876 }
877 }
878
879 if (!(dc = DC_LockDc(hDC)))
880 {
881 EngSetLastError(ERROR_INVALID_HANDLE);
882 return 0;
883 }
884
885 palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
886 if (palGDI != NULL)
887 {
888 if (pe != NULL)
889 {
890 if (StartIndex >= palGDI->NumColors)
891 Entries = 0;
892 else if (Entries > palGDI->NumColors - StartIndex)
893 Entries = palGDI->NumColors - StartIndex;
894
895 memcpy(pe,
896 palGDI->IndexedColors + StartIndex,
897 Entries * sizeof(pe[0]));
898
899 Ret = Entries;
900 }
901 else
902 {
903 Ret = dc->ppdev->gdiinfo.ulNumPalReg;
904 }
905 }
906
907 if (palGDI != NULL)
908 PALETTE_UnlockPalette(palGDI);
909
910 if (dc != NULL)
911 DC_UnlockDc(dc);
912
913 return Ret;
914 }
915
916 UINT
917 APIENTRY
918 IntSetPaletteEntries(
919 HPALETTE hpal,
920 UINT Start,
921 UINT Entries,
922 CONST LPPALETTEENTRY pe)
923 {
924 PPALETTE palGDI;
925 WORD numEntries;
926
927 if ((UINT)hpal & GDI_HANDLE_STOCK_MASK)
928 {
929 return 0;
930 }
931
932 palGDI = PALETTE_LockPalette(hpal);
933 if (!palGDI) return 0;
934
935 numEntries = palGDI->NumColors;
936 if (Start >= numEntries)
937 {
938 PALETTE_UnlockPalette(palGDI);
939 return 0;
940 }
941 if (numEntries < Start + Entries)
942 {
943 Entries = numEntries - Start;
944 }
945 memcpy(palGDI->IndexedColors + Start, pe, Entries * sizeof(PALETTEENTRY));
946 PALETTE_UnlockPalette(palGDI);
947
948 return Entries;
949 }
950
951 W32KAPI
952 LONG
953 APIENTRY
954 NtGdiDoPalette(
955 IN HGDIOBJ hObj,
956 IN WORD iStart,
957 IN WORD cEntries,
958 IN LPVOID pUnsafeEntries,
959 IN DWORD iFunc,
960 IN BOOL bInbound)
961 {
962 LONG ret;
963 LPVOID pEntries = NULL;
964
965 /* FIXME: Handle bInbound correctly */
966
967 if (bInbound &&
968 (pUnsafeEntries == NULL || cEntries == 0))
969 {
970 return 0;
971 }
972
973 if (pUnsafeEntries)
974 {
975 pEntries = ExAllocatePoolWithTag(PagedPool, cEntries * sizeof(PALETTEENTRY), TAG_PALETTE);
976 if (!pEntries)
977 return 0;
978 if (bInbound)
979 {
980 _SEH2_TRY
981 {
982 ProbeForRead(pUnsafeEntries, cEntries * sizeof(PALETTEENTRY), 1);
983 memcpy(pEntries, pUnsafeEntries, cEntries * sizeof(PALETTEENTRY));
984 }
985 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
986 {
987 ExFreePoolWithTag(pEntries, TAG_PALETTE);
988 _SEH2_YIELD(return 0);
989 }
990 _SEH2_END
991 }
992 }
993
994 ret = 0;
995 switch(iFunc)
996 {
997 case GdiPalAnimate:
998 if (pEntries)
999 ret = IntAnimatePalette((HPALETTE)hObj, iStart, cEntries, (CONST PPALETTEENTRY)pEntries);
1000 break;
1001
1002 case GdiPalSetEntries:
1003 if (pEntries)
1004 ret = IntSetPaletteEntries((HPALETTE)hObj, iStart, cEntries, (CONST LPPALETTEENTRY)pEntries);
1005 break;
1006
1007 case GdiPalGetEntries:
1008 ret = IntGetPaletteEntries((HPALETTE)hObj, iStart, cEntries, (LPPALETTEENTRY)pEntries);
1009 break;
1010
1011 case GdiPalGetSystemEntries:
1012 ret = IntGetSystemPaletteEntries((HDC)hObj, iStart, cEntries, (LPPALETTEENTRY)pEntries);
1013 break;
1014
1015 case GdiPalSetColorTable:
1016 if (pEntries)
1017 ret = IntSetDIBColorTable((HDC)hObj, iStart, cEntries, (RGBQUAD*)pEntries);
1018 break;
1019
1020 case GdiPalGetColorTable:
1021 if (pEntries)
1022 ret = IntGetDIBColorTable((HDC)hObj, iStart, cEntries, (RGBQUAD*)pEntries);
1023 break;
1024 }
1025
1026 if (pEntries)
1027 {
1028 if (!bInbound)
1029 {
1030 _SEH2_TRY
1031 {
1032 ProbeForWrite(pUnsafeEntries, cEntries * sizeof(PALETTEENTRY), 1);
1033 memcpy(pUnsafeEntries, pEntries, cEntries * sizeof(PALETTEENTRY));
1034 }
1035 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1036 {
1037 ret = 0;
1038 }
1039 _SEH2_END
1040 }
1041 ExFreePoolWithTag(pEntries, TAG_PALETTE);
1042 }
1043
1044 return ret;
1045 }
1046
1047 UINT APIENTRY
1048 NtGdiSetSystemPaletteUse(HDC hDC, UINT Usage)
1049 {
1050 UINT old = SystemPaletteUse;
1051
1052 /* Device doesn't support colour palettes */
1053 if (!(NtGdiGetDeviceCaps(hDC, RASTERCAPS) & RC_PALETTE)) {
1054 return SYSPAL_ERROR;
1055 }
1056
1057 switch (Usage)
1058 {
1059 case SYSPAL_NOSTATIC:
1060 case SYSPAL_NOSTATIC256:
1061 case SYSPAL_STATIC:
1062 SystemPaletteUse = Usage;
1063 break;
1064
1065 default:
1066 old=SYSPAL_ERROR;
1067 break;
1068 }
1069
1070 return old;
1071 }
1072
1073 UINT
1074 APIENTRY
1075 NtGdiGetSystemPaletteUse(HDC hDC)
1076 {
1077 return SystemPaletteUse;
1078 }
1079
1080 BOOL
1081 APIENTRY
1082 NtGdiUpdateColors(HDC hDC)
1083 {
1084 PWND Wnd;
1085 BOOL calledFromUser, ret;
1086 USER_REFERENCE_ENTRY Ref;
1087
1088 calledFromUser = UserIsEntered();
1089
1090 if (!calledFromUser){
1091 UserEnterExclusive();
1092 }
1093
1094 Wnd = UserGetWindowObject(IntWindowFromDC(hDC));
1095 if (Wnd == NULL)
1096 {
1097 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
1098
1099 if (!calledFromUser){
1100 UserLeave();
1101 }
1102
1103 return FALSE;
1104 }
1105
1106 UserRefObjectCo(Wnd, &Ref);
1107 ret = co_UserRedrawWindow(Wnd, NULL, 0, RDW_INVALIDATE);
1108 UserDerefObjectCo(Wnd);
1109
1110 if (!calledFromUser){
1111 UserLeave();
1112 }
1113
1114 return ret;
1115 }
1116
1117 BOOL
1118 APIENTRY
1119 NtGdiUnrealizeObject(HGDIOBJ hgdiobj)
1120 {
1121 BOOL Ret = FALSE;
1122 PPALETTE palGDI;
1123
1124 if ( !hgdiobj ||
1125 ((UINT)hgdiobj & GDI_HANDLE_STOCK_MASK) ||
1126 !GDI_HANDLE_IS_TYPE(hgdiobj, GDI_OBJECT_TYPE_PALETTE) )
1127 return Ret;
1128
1129 palGDI = PALETTE_LockPalette(hgdiobj);
1130 if (!palGDI) return FALSE;
1131
1132 // FIXME!!
1133 // Need to do something!!!
1134 // Zero out Current and Old Translated pointers?
1135 //
1136 Ret = TRUE;
1137 PALETTE_UnlockPalette(palGDI);
1138 return Ret;
1139 }
1140
1141
1142 /* EOF */