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