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