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