1 // FIXME: Use PXLATEOBJ logicalToSystem instead of int *mapping
3 #undef WIN32_LEAN_AND_MEAN
6 #include <ddk/winddi.h>
8 #include <win32k/color.h>
9 #include "../eng/handle.h"
12 #include <win32k/debug1.h>
14 int COLOR_gapStart = 256;
15 int COLOR_gapEnd = -1;
16 int COLOR_gapFilled = 0;
19 static HPALETTE hPrimaryPalette = 0; // used for WM_PALETTECHANGED
20 static HPALETTE hLastRealizedPalette = 0; // UnrealizeObject() needs it
22 const PALETTEENTRY COLOR_sysPalTemplate[NB_RESERVED_COLORS] =
24 // first 10 entries in the system palette
25 // red green blue flags
26 { 0x00, 0x00, 0x00, PC_SYS_USED },
27 { 0x80, 0x00, 0x00, PC_SYS_USED },
28 { 0x00, 0x80, 0x00, PC_SYS_USED },
29 { 0x80, 0x80, 0x00, PC_SYS_USED },
30 { 0x00, 0x00, 0x80, PC_SYS_USED },
31 { 0x80, 0x00, 0x80, PC_SYS_USED },
32 { 0x00, 0x80, 0x80, PC_SYS_USED },
33 { 0xc0, 0xc0, 0xc0, PC_SYS_USED },
34 { 0xc0, 0xdc, 0xc0, PC_SYS_USED },
35 { 0xa6, 0xca, 0xf0, PC_SYS_USED },
37 // ... c_min/2 dynamic colorcells
38 // ... gap (for sparse palettes)
39 // ... c_min/2 dynamic colorcells
41 { 0xff, 0xfb, 0xf0, PC_SYS_USED },
42 { 0xa0, 0xa0, 0xa4, PC_SYS_USED },
43 { 0x80, 0x80, 0x80, PC_SYS_USED },
44 { 0xff, 0x00, 0x00, PC_SYS_USED },
45 { 0x00, 0xff, 0x00, PC_SYS_USED },
46 { 0xff, 0xff, 0x00, PC_SYS_USED },
47 { 0x00, 0x00, 0xff, PC_SYS_USED },
48 { 0xff, 0x00, 0xff, PC_SYS_USED },
49 { 0x00, 0xff, 0xff, PC_SYS_USED },
50 { 0xff, 0xff, 0xff, PC_SYS_USED } // last 10
53 //forward declarations
54 COLORREF COLOR_LookupNearestColor( PALETTEENTRY* palPalEntry, int size, COLORREF color );
57 const PALETTEENTRY* COLOR_GetSystemPaletteTemplate(void)
59 return (const PALETTEENTRY*)&COLOR_sysPalTemplate;
62 BOOL STDCALL W32kAnimatePalette(HPALETTE hpal,
65 CONST PPALETTEENTRY ppe)
68 if( hPal != W32kGetStockObject(DEFAULT_PALETTE) )
70 PALETTEOBJ* palPtr = (PALETTEOBJ *)GDI_GetObjPtr(hPal, PALETTE_MAGIC);
71 if (!palPtr) return FALSE;
73 if( (StartIndex + NumEntries) <= palPtr->logpalette.palNumEntries )
76 for( u = 0; u < NumEntries; u++ )
77 palPtr->logpalette.palPalEntry[u + StartIndex] = PaletteColors[u];
78 PALETTE_Driver->pSetMapping(palPtr, StartIndex, NumEntries, hPal != hPrimaryPalette );
89 HPALETTE STDCALL W32kCreateHalftonePalette(HDC hDC)
95 PALETTEENTRY aEntries[256];
98 Palette.Version = 0x300;
99 Palette.NumberOfEntries = 256;
100 W32kGetSystemPaletteEntries(hDC, 0, 256, Palette.aEntries);
102 for (r = 0; r < 6; r++) {
103 for (g = 0; g < 6; g++) {
104 for (b = 0; b < 6; b++) {
105 i = r + g*6 + b*36 + 10;
106 Palette.aEntries[i].peRed = r * 51;
107 Palette.aEntries[i].peGreen = g * 51;
108 Palette.aEntries[i].peBlue = b * 51;
113 for (i = 216; i < 246; i++) {
114 int v = (i - 216) * 8;
115 Palette.aEntries[i].peRed = v;
116 Palette.aEntries[i].peGreen = v;
117 Palette.aEntries[i].peBlue = v;
120 return W32kCreatePalette((LOGPALETTE *)&Palette);
123 HPALETTE STDCALL W32kCreatePalette(CONST PLOGPALETTE palette)
127 HPALETTE NewPalette = (HPALETTE)EngCreatePalette(PAL_INDEXED, palette->palNumEntries, (PULONG*) palette->palPalEntry, 0, 0, 0);
130 PalObj = (PPALOBJ)AccessUserObject(NewPalette);
132 size = sizeof(LOGPALETTE) + (palette->palNumEntries * sizeof(PALETTEENTRY));
133 PalObj->logpalette = ExAllocatePool(NonPagedPool, size);
134 memcpy(PalObj->logpalette, palette, size);
135 PALETTE_ValidateFlags(PalObj->logpalette->palPalEntry, PalObj->logpalette->palNumEntries);
136 PalObj->logicalToSystem = NULL;
141 BOOL STDCALL W32kGetColorAdjustment(HDC hDC,
142 LPCOLORADJUSTMENT ca)
147 COLORREF STDCALL W32kGetNearestColor(HDC hDC,
150 COLORREF nearest = CLR_INVALID;
154 if( (dc = DC_HandleToPtr(hDC) ) )
156 HPALETTE hpal = (dc->w.hPalette)? dc->w.hPalette : W32kGetStockObject(DEFAULT_PALETTE);
157 palObj = (PPALOBJ)AccessUserObject(hpal);
159 // GDI_ReleaseObj(hdc);
163 nearest = COLOR_LookupNearestColor(palObj->logpalette->palPalEntry,
164 palObj->logpalette->palNumEntries, Color);
165 // FIXME: release hpal!!
166 // GDI_ReleaseObj( hpal );
167 DC_ReleasePtr( hDC );
173 UINT STDCALL W32kGetNearestPaletteIndex(HPALETTE hpal,
176 PPALOBJ palObj = (PPALOBJ)AccessUserObject(hpal);
181 // Return closest match for the given RGB color
182 index = COLOR_PaletteLookupPixel(palObj->logpalette->palPalEntry, palObj->logpalette->palNumEntries, NULL, Color, FALSE);
183 // GDI_ReleaseObj( hpalette );
189 UINT STDCALL W32kGetPaletteEntries(HPALETTE hpal,
197 palPtr = (PPALOBJ)AccessUserObject(hpal);
198 if (!palPtr) return 0;
200 numEntries = palPtr->logpalette->palNumEntries;
201 if (StartIndex + Entries > numEntries) Entries = numEntries - StartIndex;
204 if (StartIndex >= numEntries)
206 // GDI_ReleaseObj( hpalette );
209 memcpy(pe, &palPtr->logpalette->palPalEntry[StartIndex], Entries * sizeof(PALETTEENTRY));
210 for(numEntries = 0; numEntries < Entries ; numEntries++)
211 if (pe[numEntries].peFlags & 0xF0)
212 pe[numEntries].peFlags = 0;
215 // GDI_ReleaseObj( hpalette );
219 UINT STDCALL W32kGetSystemPaletteEntries(HDC hDC,
227 if (!(dc = AccessUserObject(hdc))) return 0;
231 Entries = dc->devCaps->sizePalette;
235 if (StartIndex >= dc->devCaps->sizePalette)
241 if (StartIndex + Entries >= dc->devCaps->sizePalette) Entries = dc->devCaps->sizePalette - StartIndex;
243 for (i = 0; i < Entries; i++)
245 *(COLORREF*)(entries + i) = COLOR_GetSystemPaletteEntry(StartIndex + i);
249 // GDI_ReleaseObj(hdc);
253 UINT STDCALL W32kGetSystemPaletteUse(HDC hDC)
258 UINT STDCALL W32kRealizePalette(HDC hDC)
260 The RealizePalette function modifies the palette for the device associated with the specified device context. If the device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device context is a display DC, the physical palette for that device is modified.
262 A logical palette is a buffer between color-intensive applications and the system, allowing these applications to use as many colors as needed without interfering with colors displayed by other windows.
264 1= IF DRAWING TO A DEVICE
265 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
267 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the system palette.
269 2= IF DRAWING TO A MEMORY DC\BITMAP
270 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
272 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the dc palette.
275 PPALOBJ palPtr, sysPtr;
276 PPALGDI palGDI, sysGDI;
278 PDC dc = (PDC)AccessUserObject(hDC);
279 HPALETTE systemPalette;
285 palPtr = (PPALOBJ)AccessUserObject(dc->w.hPalette);
286 SurfGDI = (PSURFGDI)AccessInternalObjectFromUserObject(dc->Surface);
287 systemPalette = W32kGetStockObject(STOCK_DEFAULT_PALETTE);
288 sysPtr = (PPALOBJ)AccessInternalObject(systemPalette);
289 palGDI = (PPALGDI)AccessInternalObject(dc->w.hPalette);
290 sysGDI = (PPALGDI)AccessInternalObject(systemPalette);
292 // Step 1: Create mapping of system palette\DC palette
293 realized = PALETTE_SetMapping(palPtr, 0, palPtr->logpalette->palNumEntries,
294 (dc->w.hPalette != hPrimaryPalette) ||
295 (dc->w.hPalette == W32kGetStockObject(DEFAULT_PALETTE)));
298 // The RealizePalette function modifies the palette for the device associated with the specified device context. If the
299 // device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device
300 // context is a display DC, the physical palette for that device is modified.
301 if(dc->w.flags == DC_MEMORY)
304 DbgPrint("win32k: realizepalette unimplemented step 2 for DC_MEMORY");
306 if(SurfGDI->SetPalette)
308 success = SurfGDI->SetPalette(dc->PDev, sysPtr, 0, 0, sysPtr->logpalette->palNumEntries);
312 // Step 3: Create the XLATEOBJ for device managed DCs
313 if(dc->w.flags != DC_MEMORY)
316 palPtr->logicalToSystem = EngCreateXlate(sysGDI->Mode, palGDI->Mode, systemPalette, dc->w.hPalette);
319 // GDI_ReleaseObj(dc->w.hPalette);
320 // GDI_ReleaseObj(hdc);
325 BOOL STDCALL W32kResizePalette(HPALETTE hpal,
328 /* PPALOBJ palPtr = (PPALOBJ)AccessUserObject(hPal);
329 UINT cPrevEnt, prevVer;
330 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
331 PXLATEOBJ XlateObj = NULL;
333 if(!palPtr) return FALSE;
334 cPrevEnt = palPtr->logpalette->palNumEntries;
335 prevVer = palPtr->logpalette->palVersion;
336 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
337 size += sizeof(int*) + sizeof(GDIOBJHDR);
338 XlateObj = palPtr->logicalToSystem;
340 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
344 PXLATEOBJ NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
345 if(NewXlateObj == NULL)
347 ERR("Can not resize logicalToSystem -- out of memory!");
348 GDI_ReleaseObj( hPal );
351 palPtr->logicalToSystem = NewXlateObj;
354 if(cEntries > cPrevEnt)
356 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
357 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
358 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
360 palPtr->logpalette->palNumEntries = cEntries;
361 palPtr->logpalette->palVersion = prevVer;
362 // GDI_ReleaseObj( hPal );
368 HPALETTE STDCALL W32kSelectPalette(HDC hDC,
370 BOOL ForceBackground)
372 PDC dc = (PDC)AccessUserObject(hDC);
375 oldPal = dc->w.hPalette;
376 dc->w.hPalette = hpal;
378 // FIXME: mark the palette as a [fore\back]ground pal
383 BOOL STDCALL W32kSetColorAdjustment(HDC hDC,
384 CONST LPCOLORADJUSTMENT ca)
389 UINT STDCALL W32kSetPaletteEntries(HPALETTE hpal,
392 CONST LPPALETTEENTRY pe)
397 palPtr = (PPALOBJ)AccessUserObject(hpal);
398 if (!palPtr) return 0;
400 numEntries = palPtr->logpalette->palNumEntries;
401 if (Start >= numEntries)
403 // GDI_ReleaseObj( hpalette );
406 if (Start + Entries > numEntries) Entries = numEntries - Start;
407 memcpy(&palPtr->logpalette->palPalEntry[Start], pe, Entries * sizeof(PALETTEENTRY));
408 PALETTE_ValidateFlags(palPtr->logpalette->palPalEntry, palPtr->logpalette->palNumEntries);
409 ExFreePool(palPtr->logicalToSystem);
410 palPtr->logicalToSystem = NULL;
411 // GDI_ReleaseObj( hpalette );
415 UINT STDCALL W32kSetSystemPaletteUse(HDC hDC,
421 BOOL STDCALL W32kUnrealizeObject(HGDIOBJ hgdiobj)
426 BOOL STDCALL W32kUpdateColors(HDC hDC)
432 if (!(dc = AccessUserObject(hDC))) return 0;
433 size = dc->devCaps->sizePalette;
434 // GDI_ReleaseObj( hDC );
436 if (Callout.WindowFromDC)
438 hWnd = Callout.WindowFromDC( hDC );
440 // Docs say that we have to remap current drawable pixel by pixel
441 // but it would take forever given the speed of XGet/PutPixel.
442 if (hWnd && size) Callout.RedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE );
447 int COLOR_PaletteLookupPixel(PALETTEENTRY *palPalEntry, int size,
448 PXLATEOBJ XlateObj, COLORREF col, BOOL skipReserved)
450 int i, best = 0, diff = 0x7fffffff;
453 for( i = 0; i < size && diff ; i++ )
455 if(!(palPalEntry[i].peFlags & PC_SYS_USED) || (skipReserved && palPalEntry[i].peFlags & PC_SYS_RESERVED))
458 r = palPalEntry[i].peRed - GetRValue(col);
459 g = palPalEntry[i].peGreen - GetGValue(col);
460 b = palPalEntry[i].peBlue - GetBValue(col);
464 if( r < diff ) { best = i; diff = r; }
466 return (XlateObj->pulXlate) ? XlateObj->pulXlate[best] : best;
469 COLORREF COLOR_LookupNearestColor( PALETTEENTRY* palPalEntry, int size, COLORREF color )
471 unsigned char spec_type = color >> 24;
473 PALETTEENTRY *COLOR_sysPal = (PALETTEENTRY*)ReturnSystemPalette();
475 // we need logical palette for PALETTERGB and PALETTEINDEX colorrefs
477 if( spec_type == 2 ) /* PALETTERGB */
478 color = *(COLORREF*)(palPalEntry + COLOR_PaletteLookupPixel(palPalEntry,size,NULL,color,FALSE));
480 else if( spec_type == 1 ) /* PALETTEINDEX */
482 if( (i = color & 0x0000ffff) >= size )
484 DbgPrint("RGB(%lx) : idx %d is out of bounds, assuming NULL\n", color, i);
485 color = *(COLORREF*)palPalEntry;
487 else color = *(COLORREF*)(palPalEntry + i);
491 return (0x00ffffff & *(COLORREF*)(COLOR_sysPal + COLOR_PaletteLookupPixel(COLOR_sysPal, 256, NULL, color, FALSE)));
494 int COLOR_PaletteLookupExactIndex( PALETTEENTRY* palPalEntry, int size,
498 BYTE r = GetRValue(col), g = GetGValue(col), b = GetBValue(col);
499 for( i = 0; i < size; i++ )
501 if( palPalEntry[i].peFlags & PC_SYS_USED ) /* skips gap */
502 if(palPalEntry[i].peRed == r && palPalEntry[i].peGreen == g && palPalEntry[i].peBlue == b) return i;