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