1 #undef WIN32_LEAN_AND_MEAN
3 #include <win32k/debug.h>
4 #include <win32k/bitmaps.h>
5 #include <win32k/color.h>
7 #include "../include/palette.h"
9 static int PALETTE_firstFree = 0;
10 static unsigned char PALETTE_freeList[256];
12 int PALETTE_PaletteFlags = 0;
13 PALETTEENTRY *COLOR_sysPal = NULL;
19 PALETTEENTRY *ReturnSystemPalette(void)
24 // Create the system palette
25 HPALETTE PALETTE_Init(void)
31 const PALETTEENTRY* __sysPalTemplate = (const PALETTEENTRY*)COLOR_GetSystemPaletteTemplate();
33 // create default palette (20 system colors)
34 palPtr = ExAllocatePool(NonPagedPool, sizeof(LOGPALETTE) + (NB_RESERVED_COLORS * sizeof(PALETTEENTRY)));
35 if (!palPtr) return FALSE;
37 palPtr->palVersion = 0x300;
38 palPtr->palNumEntries = NB_RESERVED_COLORS;
39 for(i=0; i<NB_RESERVED_COLORS; i++)
41 palPtr->palPalEntry[i].peRed = __sysPalTemplate[i].peRed;
42 palPtr->palPalEntry[i].peGreen = __sysPalTemplate[i].peGreen;
43 palPtr->palPalEntry[i].peBlue = __sysPalTemplate[i].peBlue;
44 palPtr->palPalEntry[i].peFlags = 0;
47 hpalette = W32kCreatePalette(palPtr);
50 palObj = (PPALOBJ)AccessUserObject(hpalette);
53 if (!(palObj->mapping = ExAllocatePool(NonPagedPool, sizeof(int) * 20)))
55 DbgPrint("Win32k: Can not create palette mapping -- out of memory!");
58 // GDI_ReleaseObj( hpalette );
61 /* palette_size = visual->map_entries; */
66 static void PALETTE_FormatSystemPalette(void)
68 // Build free list so we'd have an easy way to find
69 // out if there are any available colorcells.
71 int i, j = PALETTE_firstFree = NB_RESERVED_COLORS/2;
73 COLOR_sysPal[j].peFlags = 0;
74 for(i = NB_RESERVED_COLORS/2 + 1 ; i < 256 - NB_RESERVED_COLORS/2 ; i++)
76 if( i < COLOR_gapStart || i > COLOR_gapEnd )
78 COLOR_sysPal[i].peFlags = 0; // unused tag
79 PALETTE_freeList[j] = i; // next
83 PALETTE_freeList[j] = 0;
86 /* Ported from WINE 20020804 (graphics\x11drv\palette.c) */
87 static int SysPaletteLookupPixel( COLORREF col, BOOL skipReserved )
89 int i, best = 0, diff = 0x7fffffff;
92 for( i = 0; i < palette_size && diff ; i++ )
94 if( !(COLOR_sysPal[i].peFlags & PC_SYS_USED) || (skipReserved && COLOR_sysPal[i].peFlags & PC_SYS_RESERVED) )
97 r = COLOR_sysPal[i].peRed - GetRValue(col);
98 g = COLOR_sysPal[i].peGreen - GetGValue(col);
99 b = COLOR_sysPal[i].peBlue - GetBValue(col);
103 if( r < diff ) { best = i; diff = r; }
108 /* Ported from WINE 20020804 (graphics\x11drv\palette.c) */
109 /* Make sure this is required - ROS's xlate may make this redundant */
110 UINT WINAPI GetNearestPaletteIndex(
111 HPALETTE hpalette, /* [in] Handle of logical color palette */
112 COLORREF color) /* [in] Color to be matched */
114 PPALOBJ palObj = (PPALOBJ)AccessUserObject(hpalette);
119 int i, diff = 0x7fffffff;
121 PALETTEENTRY* entry = palObj->logpalette->palPalEntry;
123 for( i = 0; i < palObj->logpalette->palNumEntries && diff ; i++, entry++)
125 if (!(entry->peFlags & PC_SYS_USED)) continue;
127 r = entry->peRed - GetRValue(color);
128 g = entry->peGreen - GetGValue(color);
129 b = entry->peBlue - GetBValue(color);
133 if( r < diff ) { index = i; diff = r; }
135 // GDI_ReleaseObj( hpalette );
137 DPRINT("(%04x,%06lx): returning %d\n", hpalette, color, index );
141 void PALETTE_ValidateFlags(PALETTEENTRY* lpPalE, int size)
144 for( ; i<size ; i++ )
145 lpPalE[i].peFlags = PC_SYS_USED | (lpPalE[i].peFlags & 0x07);
148 // Set the color-mapping table for selected palette.
149 // Return number of entries which mapping has changed.
150 int PALETTE_SetMapping(PPALOBJ palPtr, UINT uStart, UINT uNum, BOOL mapOnly)
153 int prevMapping = (palPtr->mapping) ? 1 : 0;
154 int index, iRemapped = 0;
157 // reset dynamic system palette entries
159 if( !mapOnly && PALETTE_firstFree != -1) PALETTE_FormatSystemPalette();
161 // initialize palette mapping table
163 //mapping = HeapReAlloc( GetProcessHeap(), 0, palPtr->mapping,
164 // sizeof(int)*palPtr->logpalette->palNumEntries);
165 ExFreePool(palPtr->mapping);
166 mapping = ExAllocatePool(NonPagedPool, sizeof(int)*palPtr->logpalette->palNumEntries);
168 palPtr->mapping = mapping;
170 for(uNum += uStart; uStart < uNum; uStart++)
175 switch( palPtr->logpalette->palPalEntry[uStart].peFlags & 0x07 )
177 case PC_EXPLICIT: // palette entries are indices into system palette
178 // The PC_EXPLICIT flag is used to copy an entry from the system palette into the logical palette
179 index = *(WORD*)(palPtr->logpalette->palPalEntry + uStart);
180 if(index > 255 || (index >= COLOR_gapStart && index <= COLOR_gapEnd))
182 DbgPrint("Win32k: PC_EXPLICIT: idx %d out of system palette, assuming black.\n", index);
187 case PC_RESERVED: // forbid future mappings to this entry
188 // For palette animation, the entries in the logical palette need the PC_RESERVED flag
189 flag |= PC_SYS_RESERVED;
192 default: // try to collapse identical colors
193 index = COLOR_PaletteLookupExactIndex(COLOR_sysPal, 256,
194 *(COLORREF*)(palPtr->logpalette->palPalEntry + uStart));
198 // If an entry in the logical palette is marked with the PC_NOCOLLAPSE flag, the palette
199 // manager allocates a free entry in the system palette if one is available and only uses the
200 // closest colour match if there are no (more) free entries in the system palette
202 DbgPrint("Win32k: WARNING: PC_NOCOLLAPSE is not yet working properly\n");
206 if(PALETTE_firstFree > 0 /* && !(PALETTE_PaletteFlags & PALETTE_FIXED) FIXME */ )
208 DbgPrint("Win32k: Unimplemented Palette Operation: PC_NOCOLLAPSE [objects/palette.c]\n");
210 index = PALETTE_firstFree; // ought to be available
211 PALETTE_firstFree = PALETTE_freeList[index];
213 color.pixel = (PALETTE_PaletteToXPixel) ? PALETTE_PaletteToXPixel[index] : index;
214 color.red = palPtr->logpalette->palPalEntry[uStart].peRed << 8;
215 color.green = palPtr->logpalette->palPalEntry[uStart].peGreen << 8;
216 color.blue = palPtr->logpalette->palPalEntry[uStart].peBlue << 8;
217 color.flags = DoRed | DoGreen | DoBlue;
218 TSXStoreColor(display, PALETTE_PaletteXColormap, &color);
220 COLOR_sysPal[index] = palPtr->logpalette->palPalEntry[uStart];
221 COLOR_sysPal[index].peFlags = flag;
222 PALETTE_freeList[index] = 0;
224 if(PALETTE_PaletteToXPixel) index = PALETTE_PaletteToXPixel[index]; */
227 /* else if (PALETTE_PaletteFlags & PALETTE_VIRTUAL)
229 index = PALETTE_ToPhysical(NULL, 0x00ffffff &
230 *(COLORREF*)(palPtr->logpalette->palPalEntry + uStart));
234 // we have to map to existing entry in the system palette
236 index = COLOR_PaletteLookupPixel(COLOR_sysPal, 256, NULL,
237 *(COLORREF*)(palPtr->logpalette->palPalEntry + uStart), TRUE);
239 palPtr->logpalette->palPalEntry[uStart].peFlags |= PC_SYS_USED;
241 /* if(PALETTE_PaletteToXPixel) index = PALETTE_PaletteToXPixel[index]; FIXME */
245 if( !prevMapping || palPtr->mapping[uStart] != index ) iRemapped++;
246 palPtr->mapping[uStart] = index;
252 /* Return the physical color closest to 'color'. */
253 /* Ported from WINE 20020804 (graphics\x11drv\palette.c) */
254 int PALETTE_ToPhysical( PDC dc, COLORREF color )
257 HPALETTE hPal = (dc)? dc->w.hPalette: W32kGetStockObject(DEFAULT_PALETTE);
258 unsigned char spec_type = color >> 24;
259 PPALOBJ palPtr = (PPALOBJ)AccessUserObject(hPal);
261 /* palPtr can be NULL when DC is being destroyed */
262 if( !palPtr ) return 0;
264 if ( PALETTE_PaletteFlags & PALETTE_FIXED )
266 /* there is no colormap limitation; we are going to have to compute
267 * the pixel value from the visual information stored earlier
270 unsigned long red, green, blue;
275 case 1: /* PALETTEINDEX */
277 if( (idx = color & 0xffff) >= palPtr->logpalette->palNumEntries)
279 DPRINT("RGB(%lx) : idx %d is out of bounds, assuming black\n", color, idx);
280 // GDI_ReleaseObj( hPal );
284 if( palPtr->mapping )
286 int ret = palPtr->mapping[idx];
287 // GDI_ReleaseObj( hPal );
290 color = *(COLORREF*)(palPtr->logpalette->palPalEntry + idx);
295 /* fall through to RGB */
298 if( dc && (dc->w.bitsPerPixel == 1) )
300 // GDI_ReleaseObj( hPal );
301 return (((color >> 16) & 0xff) +
302 ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? 1 : 0;
307 red = GetRValue(color); green = GetGValue(color); blue = GetBValue(color);
311 /* grayscale only; return scaled value */
312 // GDI_ReleaseObj( hPal );
313 return ( (red * 30 + green * 59 + blue * 11) * PALETTE_Graymax) / 25500;
317 /* scale each individually and construct the TrueColor pixel value */
318 if (PALETTE_PRed.scale < 8)
319 red = red >> (8-PALETTE_PRed.scale);
320 else if (PALETTE_PRed.scale > 8)
321 red = red << (PALETTE_PRed.scale-8) |
322 red >> (16-PALETTE_PRed.scale);
323 if (PALETTE_PGreen.scale < 8)
324 green = green >> (8-PALETTE_PGreen.scale);
325 else if (PALETTE_PGreen.scale > 8)
326 green = green << (PALETTE_PGreen.scale-8) |
327 green >> (16-PALETTE_PGreen.scale);
328 if (PALETTE_PBlue.scale < 8)
329 blue = blue >> (8-PALETTE_PBlue.scale);
330 else if (PALETTE_PBlue.scale > 8)
331 blue = blue << (PALETTE_PBlue.scale-8) |
332 blue >> (16-PALETTE_PBlue.scale);
334 // GDI_ReleaseObj( hPal );
335 return (red << PALETTE_PRed.shift) | (green << PALETTE_PGreen.shift) | (blue << PALETTE_PBlue.shift);
341 if( !palPtr->mapping )
342 DPRINT("Palette %04x is not realized\n", dc->w.hPalette);
344 switch(spec_type) /* we have to peruse DC and system palette */
348 /* fall through to RGB */
351 if( dc && (dc->w.bitsPerPixel == 1) )
353 // GDI_ReleaseObj( hPal );
354 return (((color >> 16) & 0xff) +
355 ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? 1 : 0;
358 index = SysPaletteLookupPixel( color, FALSE);
360 /* if (PALETTE_PaletteToXPixel) index = PALETTE_PaletteToXPixel[index]; */
362 /* DPRINT(palette,"RGB(%lx) -> pixel %i\n", color, index);
365 case 1: /* PALETTEINDEX */
366 index = color & 0xffff;
368 if( index >= palPtr->logpalette->palNumEntries )
369 DbgPrint("RGB(%lx) : index %i is out of bounds\n", color, index);
370 else if( palPtr->mapping ) index = palPtr->mapping[index];
372 /* DPRINT(palette,"PALETTEINDEX(%04x) -> pixel %i\n", (WORD)color, index);
375 case 2: /* PALETTERGB */
376 index = GetNearestPaletteIndex( hPal, color );
377 if (palPtr->mapping) index = palPtr->mapping[index];
378 /* DPRINT(palette,"PALETTERGB(%lx) -> pixel %i\n", color, index);
384 // GDI_ReleaseObj( hPal );