2 * X11DRV OEM bitmap objects
4 * Copyright 1994, 1995 Alexandre Julliard
16 #include "debugtools.h"
23 DEFAULT_DEBUG_CHANNEL(palette);
25 /* Palette indexed mode:
26 * logical palette -> mapping -> pixel
29 * Windows needs contiguous color space ( from 0 to n ) but
30 * it is possible only with the private colormap. Otherwise we
31 * have to map DC palette indices to real pixel values. With
32 * private colormaps it boils down to the identity mapping. The
33 * other special case is when we have a fixed color visual with
34 * the screendepth > 8 - we abandon palette mappings altogether
35 * because pixel values can be calculated without X server
38 * Windows palette manager is described in the
39 * http://premium.microsoft.com/msdn/library/techart/f30/f34/f40/d4d/sa942.htm
42 extern PALETTEENTRY *COLOR_sysPal;
43 extern int COLOR_gapStart;
44 extern int COLOR_gapEnd;
45 extern int COLOR_gapFilled;
48 extern const PALETTEENTRY COLOR_sysPalTemplate[NB_RESERVED_COLORS];
50 Colormap X11DRV_PALETTE_PaletteXColormap = 0;
51 UINT16 X11DRV_PALETTE_PaletteFlags = 0;
53 static int X11DRV_PALETTE_Redshift = 0; /* to handle abortive X11DRV_PALETTE_VIRTUAL visuals */
54 static int X11DRV_PALETTE_Redscale = 0;
55 static int X11DRV_PALETTE_Redmax = 0;
56 static int X11DRV_PALETTE_Greenshift = 0;
57 static int X11DRV_PALETTE_Greenscale = 0;
58 static int X11DRV_PALETTE_Greenmax = 0;
59 static int X11DRV_PALETTE_Blueshift = 0;
60 static int X11DRV_PALETTE_Bluescale = 0;
61 static int X11DRV_PALETTE_Bluemax = 0;
62 static int X11DRV_PALETTE_Graymax = 0;
64 static int palette_size;
66 /* First free dynamic color cell, 0 = full palette, -1 = fixed palette */
67 static int X11DRV_PALETTE_firstFree = 0;
68 static unsigned char X11DRV_PALETTE_freeList[256];
70 /**********************************************************************/
72 /* Map an EGA index (0..15) to a pixel value in the system color space. */
74 int X11DRV_PALETTE_mapEGAPixel[16];
76 /**********************************************************************/
78 #define NB_COLORCUBE_START_INDEX 63
80 /* Maps entry in the system palette to X pixel value */
81 int *X11DRV_PALETTE_PaletteToXPixel = NULL;
83 /* Maps pixel to the entry in the system palette */
84 int *X11DRV_PALETTE_XPixelToPalette = NULL;
86 /**********************************************************************/
88 static BOOL X11DRV_PALETTE_BuildPrivateMap(void);
89 static BOOL X11DRV_PALETTE_BuildSharedMap(void);
90 static void X11DRV_PALETTE_ComputeShifts(unsigned long maskbits, int *shift, int *max, int *scale);
91 static void X11DRV_PALETTE_FillDefaultColors(void);
92 static void X11DRV_PALETTE_FormatSystemPalette(void);
93 static BOOL X11DRV_PALETTE_CheckSysColor(COLORREF c);
94 static int X11DRV_PALETTE_LookupSystemXPixel(COLORREF col);
97 /***********************************************************************
100 * Initialize color management.
102 int X11DRV_PALETTE_Init(void)
104 int mask, white, black;
107 TRACE("initializing palette manager...\n");
109 white = WhitePixel( gdi_display, DefaultScreen(gdi_display) );
110 black = BlackPixel( gdi_display, DefaultScreen(gdi_display) );
112 for( mask = 1; !((white & mask)^(black & mask)); mask <<= 1 )
114 X11DRV_PALETTE_PaletteFlags = (white & mask) ? X11DRV_PALETTE_WHITESET : 0;
115 palette_size = visual->map_entries;
117 switch(visual->class)
120 X11DRV_PALETTE_PaletteFlags |= X11DRV_PALETTE_VIRTUAL;
125 BOOL private_color_map = FALSE;
126 if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", &hkey))
129 DWORD type, count = sizeof(buffer);
130 if(!RegQueryValueExA(hkey, "PrivateColorMap", 0, &type, buffer, &count))
133 private_color_map = (ch == 'y' || ch == 'Y' || ch == 't' || ch == 'T' || ch == '1');
138 if (private_color_map)
140 XSetWindowAttributes win_attr;
142 X11DRV_PALETTE_PaletteXColormap = TSXCreateColormap( gdi_display, root_window,
144 if (X11DRV_PALETTE_PaletteXColormap)
146 X11DRV_PALETTE_PaletteFlags |= (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_WHITESET);
149 for( white = palette_size - 1; !(white & 1); white >>= 1 )
152 if( root_window != DefaultRootWindow(gdi_display) )
154 win_attr.colormap = X11DRV_PALETTE_PaletteXColormap;
155 TSXChangeWindowAttributes( gdi_display, root_window, CWColormap, &win_attr );
160 X11DRV_PALETTE_PaletteXColormap = TSXCreateColormap(gdi_display, root_window,
166 X11DRV_PALETTE_PaletteXColormap = TSXCreateColormap(gdi_display, root_window,
168 X11DRV_PALETTE_PaletteFlags |= X11DRV_PALETTE_FIXED;
169 X11DRV_PALETTE_Graymax = (1 << screen_depth)-1;
173 X11DRV_PALETTE_PaletteFlags |= X11DRV_PALETTE_VIRTUAL;
175 int *depths,nrofdepths;
176 /* FIXME: hack to detect XFree32 XF_VGA16 ... We just have
179 depths=TSXListDepths(gdi_display,DefaultScreen(gdi_display),&nrofdepths);
180 if ((nrofdepths==2) && ((depths[0]==4) || depths[1]==4)) {
182 for( white = palette_size - 1; !(white & 1); white >>= 1 )
184 X11DRV_PALETTE_PaletteFlags = (white & mask) ? X11DRV_PALETTE_WHITESET : 0;
185 X11DRV_PALETTE_PaletteXColormap = TSXCreateColormap(gdi_display, root_window,
191 X11DRV_PALETTE_PaletteXColormap = TSXCreateColormap(gdi_display, root_window,
193 X11DRV_PALETTE_PaletteFlags |= X11DRV_PALETTE_FIXED;
194 X11DRV_PALETTE_ComputeShifts(visual->red_mask, &X11DRV_PALETTE_Redshift, &X11DRV_PALETTE_Redmax, &X11DRV_PALETTE_Redscale);
195 X11DRV_PALETTE_ComputeShifts(visual->green_mask, &X11DRV_PALETTE_Greenshift, &X11DRV_PALETTE_Greenmax, &X11DRV_PALETTE_Greenscale);
196 X11DRV_PALETTE_ComputeShifts(visual->blue_mask, &X11DRV_PALETTE_Blueshift, &X11DRV_PALETTE_Bluemax, &X11DRV_PALETTE_Bluescale);
201 TRACE(" visual class %i (%i)\n", visual->class, monoPlane);
203 memset(X11DRV_PALETTE_freeList, 0, 256*sizeof(unsigned char));
205 if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE)
206 X11DRV_PALETTE_BuildPrivateMap();
208 X11DRV_PALETTE_BuildSharedMap();
210 /* Build free list */
212 if( X11DRV_PALETTE_firstFree != -1 )
213 X11DRV_PALETTE_FormatSystemPalette();
215 X11DRV_PALETTE_FillDefaultColors();
217 if( X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL )
220 palette_size = visual->map_entries;
225 /***********************************************************************
226 * X11DRV_PALETTE_Cleanup
228 * Free external colors we grabbed in the FillDefaultPalette()
230 void X11DRV_PALETTE_Cleanup(void)
232 if( COLOR_gapFilled )
233 TSXFreeColors(gdi_display, X11DRV_PALETTE_PaletteXColormap,
234 (unsigned long*)(X11DRV_PALETTE_PaletteToXPixel + COLOR_gapStart),
238 /***********************************************************************
239 * X11DRV_PALETTE_ComputeShifts
241 * Calculate conversion parameters for direct mapped visuals
243 static void X11DRV_PALETTE_ComputeShifts(unsigned long maskbits, int *shift, int *max, int *scale)
254 for(i=0;!(maskbits&1);i++)
260 for(i=0;maskbits!=0;i++)
265 /***********************************************************************
266 * X11DRV_PALETTE_BuildPrivateMap
268 * Allocate colorcells and initialize mapping tables.
270 static BOOL X11DRV_PALETTE_BuildPrivateMap(void)
272 /* Private colormap - identity mapping */
277 if((COLOR_sysPal = (PALETTEENTRY*)HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY)*palette_size)) == NULL) {
278 WARN("Can not allocate system palette\n");
282 TRACE("Building private map - %i palette entries\n", palette_size);
284 /* Allocate system palette colors */
286 for( i=0; i < palette_size; i++ )
288 if( i < NB_RESERVED_COLORS/2 )
290 color.red = COLOR_sysPalTemplate[i].peRed * 65535 / 255;
291 color.green = COLOR_sysPalTemplate[i].peGreen * 65535 / 255;
292 color.blue = COLOR_sysPalTemplate[i].peBlue * 65535 / 255;
293 COLOR_sysPal[i] = COLOR_sysPalTemplate[i];
295 else if( i >= palette_size - NB_RESERVED_COLORS/2 )
297 int j = NB_RESERVED_COLORS + i - palette_size;
298 color.red = COLOR_sysPalTemplate[j].peRed * 65535 / 255;
299 color.green = COLOR_sysPalTemplate[j].peGreen * 65535 / 255;
300 color.blue = COLOR_sysPalTemplate[j].peBlue * 65535 / 255;
301 COLOR_sysPal[i] = COLOR_sysPalTemplate[j];
304 color.flags = DoRed | DoGreen | DoBlue;
306 TSXStoreColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &color);
308 /* Set EGA mapping if color is from the first or last eight */
311 X11DRV_PALETTE_mapEGAPixel[i] = color.pixel;
312 else if (i >= palette_size - 8 )
313 X11DRV_PALETTE_mapEGAPixel[i - (palette_size - 16)] = color.pixel;
316 X11DRV_PALETTE_XPixelToPalette = X11DRV_PALETTE_PaletteToXPixel = NULL;
318 COLOR_gapStart = 256; COLOR_gapEnd = -1;
320 X11DRV_PALETTE_firstFree = (palette_size > NB_RESERVED_COLORS)?NB_RESERVED_COLORS/2 : -1;
325 /***********************************************************************
326 * X11DRV_PALETTE_BuildSharedMap
328 * Allocate colorcells and initialize mapping tables.
330 static BOOL X11DRV_PALETTE_BuildSharedMap(void)
333 unsigned long sysPixel[NB_RESERVED_COLORS];
334 unsigned long* pixDynMapping = NULL;
335 unsigned long plane_masks[1];
337 int diff, r, g, b, max = 256, bp = 0, wp = 1;
339 int defaultCM_max_copy;
341 XColor defaultColors[256];
344 defaultCM_max_copy = 128;
347 if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", &hkey))
352 count = sizeof(buffer);
353 if(!RegQueryValueExA(hkey, "CopyDefaultColors", 0, &type, buffer, &count))
354 defaultCM_max_copy = atoi(buffer);
356 count = sizeof(buffer);
357 if(!RegQueryValueExA(hkey, "AllocSystemColors", 0, &type, buffer, &count))
358 COLOR_max = atoi(buffer);
363 /* Copy the first bunch of colors out of the default colormap to prevent
364 * colormap flashing as much as possible. We're likely to get the most
365 * important Window Manager colors, etc in the first 128 colors */
366 defaultCM = DefaultColormap( gdi_display, DefaultScreen(gdi_display) );
368 for (i = 0; i < defaultCM_max_copy; i++)
369 defaultColors[i].pixel = (long) i;
370 TSXQueryColors(gdi_display, defaultCM, &defaultColors[0], defaultCM_max_copy);
371 for (i = 0; i < defaultCM_max_copy; i++)
372 TSXAllocColor( gdi_display, X11DRV_PALETTE_PaletteXColormap, &defaultColors[i] );
374 if (COLOR_max > 256) COLOR_max = 256;
375 else if (COLOR_max < 20) COLOR_max = 20;
376 TRACE("%d colors configured.\n", COLOR_max);
378 TRACE("Building shared map - %i palette entries\n", palette_size);
380 /* Be nice and allocate system colors as read-only */
382 for( i = 0; i < NB_RESERVED_COLORS; i++ )
384 color.red = COLOR_sysPalTemplate[i].peRed * 65535 / 255;
385 color.green = COLOR_sysPalTemplate[i].peGreen * 65535 / 255;
386 color.blue = COLOR_sysPalTemplate[i].peBlue * 65535 / 255;
387 color.flags = DoRed | DoGreen | DoBlue;
389 if (!TSXAllocColor( gdi_display, X11DRV_PALETTE_PaletteXColormap, &color ))
395 WARN("Not enough colors for the full system palette.\n");
397 bp = BlackPixel(gdi_display, DefaultScreen(gdi_display));
398 wp = WhitePixel(gdi_display, DefaultScreen(gdi_display));
400 max = (0xffffffff)>>(32 - screen_depth);
408 /* reinit color (XAllocColor() may change it)
409 * and map to the best shared colorcell */
411 color.red = COLOR_sysPalTemplate[i].peRed * 65535 / 255;
412 color.green = COLOR_sysPalTemplate[i].peGreen * 65535 / 255;
413 color.blue = COLOR_sysPalTemplate[i].peBlue * 65535 / 255;
415 best.pixel = best.red = best.green = best.blue = 0;
416 for( c.pixel = 0, diff = 0x7fffffff; c.pixel < max; c.pixel += step )
418 TSXQueryColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &c);
419 r = (c.red - color.red)>>8;
420 g = (c.green - color.green)>>8;
421 b = (c.blue - color.blue)>>8;
423 if( r < diff ) { best = c; diff = r; }
426 if( TSXAllocColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &best) )
427 color.pixel = best.pixel;
428 else color.pixel = (i < NB_RESERVED_COLORS/2)? bp : wp;
431 sysPixel[i] = color.pixel;
433 TRACE("syscolor(%lx) -> pixel %i\n",
434 *(COLORREF*)(COLOR_sysPalTemplate+i), (int)color.pixel);
436 /* Set EGA mapping if color in the first or last eight */
439 X11DRV_PALETTE_mapEGAPixel[i] = color.pixel;
440 else if (i >= NB_RESERVED_COLORS - 8 )
441 X11DRV_PALETTE_mapEGAPixel[i - (NB_RESERVED_COLORS-16)] = color.pixel;
444 /* now allocate changeable set */
446 if( !(X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED) )
448 int c_min = 0, c_max = palette_size, c_val;
450 TRACE("Dynamic colormap... \n");
452 /* let's become the first client that actually follows
453 * X guidelines and does binary search...
456 if((pixDynMapping = (unsigned long*)HeapAlloc(GetProcessHeap(), 0, sizeof(long)*palette_size)) == NULL) {
457 WARN("Out of memory while building system palette.\n");
461 /* comment this out if you want to debug palette init */
462 TSXGrabServer(gdi_display);
464 while( c_max - c_min > 0 )
466 c_val = (c_max + c_min)/2 + (c_max + c_min)%2;
468 if( !TSXAllocColorCells(gdi_display, X11DRV_PALETTE_PaletteXColormap, False,
469 plane_masks, 0, pixDynMapping, c_val) )
473 TSXFreeColors(gdi_display, X11DRV_PALETTE_PaletteXColormap, pixDynMapping, c_val, 0);
478 if( c_min > COLOR_max - NB_RESERVED_COLORS)
479 c_min = COLOR_max - NB_RESERVED_COLORS;
481 c_min = (c_min/2) + (c_min/2); /* need even set for split palette */
484 if( !TSXAllocColorCells(gdi_display, X11DRV_PALETTE_PaletteXColormap, False,
485 plane_masks, 0, pixDynMapping, c_min) )
487 WARN("Inexplicable failure during colorcell allocation.\n");
491 palette_size = c_min + NB_RESERVED_COLORS;
493 TSXUngrabServer(gdi_display);
495 TRACE("adjusted size %i colorcells\n", palette_size);
497 else if( X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL )
499 /* virtual colorspace - ToPhysical takes care of
500 * color translations but we have to allocate full palette
501 * to maintain compatibility
504 TRACE("Virtual colorspace - screendepth %i\n", screen_depth);
506 else palette_size = NB_RESERVED_COLORS; /* system palette only - however we can alloc a bunch
507 * of colors and map to them */
509 TRACE("Shared system palette uses %i colors.\n", palette_size);
511 /* set gap to account for pixel shortage. It has to be right in the center
512 * of the system palette because otherwise raster ops get screwed. */
514 if( palette_size >= 256 )
515 { COLOR_gapStart = 256; COLOR_gapEnd = -1; }
517 { COLOR_gapStart = palette_size/2; COLOR_gapEnd = 255 - palette_size/2; }
519 X11DRV_PALETTE_firstFree = ( palette_size > NB_RESERVED_COLORS &&
520 (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL || !(X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED)) )
521 ? NB_RESERVED_COLORS/2 : -1;
523 COLOR_sysPal = (PALETTEENTRY*)HeapAlloc(GetProcessHeap(),0,sizeof(PALETTEENTRY)*256);
524 if(COLOR_sysPal == NULL) {
525 ERR("Can not allocate system palette!\n");
529 /* setup system palette entry <-> pixel mappings and fill in 20 fixed entries */
531 if (screen_depth <= 8)
533 X11DRV_PALETTE_XPixelToPalette = (int*)calloc(256, sizeof(int));
534 if(X11DRV_PALETTE_XPixelToPalette == NULL) {
535 ERR("Out of memory: XPixelToPalette!\n");
540 /* for hicolor visuals PaletteToPixel mapping is used to skip
541 * RGB->pixel calculation in X11DRV_PALETTE_ToPhysical().
544 X11DRV_PALETTE_PaletteToXPixel = (int*)HeapAlloc(GetProcessHeap(),0,sizeof(int)*256);
545 if(X11DRV_PALETTE_PaletteToXPixel == NULL) {
546 ERR("Out of memory: PaletteToXPixel!\n");
550 for( i = j = 0; i < 256; i++ )
552 if( i >= COLOR_gapStart && i <= COLOR_gapEnd )
554 X11DRV_PALETTE_PaletteToXPixel[i] = 0;
555 COLOR_sysPal[i].peFlags = 0; /* mark as unused */
559 if( i < NB_RESERVED_COLORS/2 )
561 X11DRV_PALETTE_PaletteToXPixel[i] = sysPixel[i];
562 COLOR_sysPal[i] = COLOR_sysPalTemplate[i];
564 else if( i >= 256 - NB_RESERVED_COLORS/2 )
566 X11DRV_PALETTE_PaletteToXPixel[i] = sysPixel[(i + NB_RESERVED_COLORS) - 256];
567 COLOR_sysPal[i] = COLOR_sysPalTemplate[(i + NB_RESERVED_COLORS) - 256];
569 else if( pixDynMapping )
570 X11DRV_PALETTE_PaletteToXPixel[i] = pixDynMapping[j++];
572 X11DRV_PALETTE_PaletteToXPixel[i] = i;
574 TRACE("index %i -> pixel %i\n", i, X11DRV_PALETTE_PaletteToXPixel[i]);
576 if( X11DRV_PALETTE_XPixelToPalette )
577 X11DRV_PALETTE_XPixelToPalette[X11DRV_PALETTE_PaletteToXPixel[i]] = i;
580 if( pixDynMapping ) HeapFree(GetProcessHeap(), 0, pixDynMapping);
585 /***********************************************************************
586 * Colormap Initialization
588 static void X11DRV_PALETTE_FillDefaultColors(void)
590 /* initialize unused entries to what Windows uses as a color
591 * cube - based on Greg Kreider's code.
595 int red, no_r, inc_r;
596 int green, no_g, inc_g;
597 int blue, no_b, inc_b;
599 if (palette_size <= NB_RESERVED_COLORS)
601 while (i*i*i < (palette_size - NB_RESERVED_COLORS)) i++;
602 no_r = no_g = no_b = --i;
603 if ((no_r * (no_g+1) * no_b) < (palette_size - NB_RESERVED_COLORS)) no_g++;
604 if ((no_r * no_g * (no_b+1)) < (palette_size - NB_RESERVED_COLORS)) no_b++;
605 inc_r = (255 - NB_COLORCUBE_START_INDEX)/no_r;
606 inc_g = (255 - NB_COLORCUBE_START_INDEX)/no_g;
607 inc_b = (255 - NB_COLORCUBE_START_INDEX)/no_b;
609 idx = X11DRV_PALETTE_firstFree;
612 for (blue = NB_COLORCUBE_START_INDEX; blue < 256 && idx; blue += inc_b )
613 for (green = NB_COLORCUBE_START_INDEX; green < 256 && idx; green += inc_g )
614 for (red = NB_COLORCUBE_START_INDEX; red < 256 && idx; red += inc_r )
618 if( red == NB_COLORCUBE_START_INDEX && green == red && blue == green ) continue;
620 COLOR_sysPal[idx].peRed = red;
621 COLOR_sysPal[idx].peGreen = green;
622 COLOR_sysPal[idx].peBlue = blue;
626 if( X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL )
628 if (X11DRV_PALETTE_Redmax != 255) no_r = (red * X11DRV_PALETTE_Redmax) / 255;
629 if (X11DRV_PALETTE_Greenmax != 255) no_g = (green * X11DRV_PALETTE_Greenmax) / 255;
630 if (X11DRV_PALETTE_Bluemax != 255) no_b = (blue * X11DRV_PALETTE_Bluemax) / 255;
632 X11DRV_PALETTE_PaletteToXPixel[idx] = (no_r << X11DRV_PALETTE_Redshift) | (no_g << X11DRV_PALETTE_Greenshift) | (no_b << X11DRV_PALETTE_Blueshift);
634 else if( !(X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED) )
637 color.pixel = (X11DRV_PALETTE_PaletteToXPixel)? X11DRV_PALETTE_PaletteToXPixel[idx] : idx;
638 color.red = COLOR_sysPal[idx].peRed << 8;
639 color.green = COLOR_sysPal[idx].peGreen << 8;
640 color.blue = COLOR_sysPal[idx].peBlue << 8;
641 color.flags = DoRed | DoGreen | DoBlue;
642 TSXStoreColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &color);
644 idx = X11DRV_PALETTE_freeList[idx];
647 /* try to fill some entries in the "gap" with
648 * what's already in the colormap - they will be
649 * mappable to but not changeable. */
651 if( COLOR_gapStart < COLOR_gapEnd && X11DRV_PALETTE_XPixelToPalette )
656 max = COLOR_max - (256 - (COLOR_gapEnd - COLOR_gapStart));
657 for ( i = 0, idx = COLOR_gapStart; i < 256 && idx <= COLOR_gapEnd; i++ )
658 if( X11DRV_PALETTE_XPixelToPalette[i] == 0 )
662 TSXQueryColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &xc);
663 r = xc.red>>8; g = xc.green>>8; b = xc.blue>>8;
665 if( xc.pixel < 256 && X11DRV_PALETTE_CheckSysColor(RGB(r, g, b)) &&
666 TSXAllocColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &xc) )
668 X11DRV_PALETTE_XPixelToPalette[xc.pixel] = idx;
669 X11DRV_PALETTE_PaletteToXPixel[idx] = xc.pixel;
670 *(COLORREF*)(COLOR_sysPal + idx) = RGB(r, g, b);
671 COLOR_sysPal[idx++].peFlags |= PC_SYS_USED;
672 if( --max <= 0 ) break;
675 COLOR_gapFilled = idx - COLOR_gapStart;
680 /***********************************************************************
681 * X11DRV_PALETTE_ToLogical
683 * Return RGB color for given X pixel.
685 COLORREF X11DRV_PALETTE_ToLogical(int pixel)
690 /* truecolor visual */
692 if (screen_depth >= 24) return pixel;
695 /* check for hicolor visuals first */
697 if ( (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED) && !X11DRV_PALETTE_Graymax )
699 color.red = (pixel >> X11DRV_PALETTE_Redshift) & X11DRV_PALETTE_Redmax;
700 color.green = (pixel >> X11DRV_PALETTE_Greenshift) & X11DRV_PALETTE_Greenmax;
701 color.blue = (pixel >> X11DRV_PALETTE_Blueshift) & X11DRV_PALETTE_Bluemax;
702 return RGB(color.red << (8-X11DRV_PALETTE_Redscale) |
703 color.red >> (2*X11DRV_PALETTE_Redscale-8),
704 color.green << (8-X11DRV_PALETTE_Greenscale) |
705 color.green >> (2*X11DRV_PALETTE_Greenscale-8),
706 color.blue << (8-X11DRV_PALETTE_Bluescale) |
707 color.blue >> (2*X11DRV_PALETTE_Bluescale-8));
710 /* check if we can bypass X */
712 if ((screen_depth <= 8) && (pixel < 256) &&
713 !(X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_VIRTUAL | X11DRV_PALETTE_FIXED)) ) {
714 return ( *(COLORREF*)(COLOR_sysPal +
715 ((X11DRV_PALETTE_XPixelToPalette)?X11DRV_PALETTE_XPixelToPalette[pixel]:pixel)) ) & 0x00ffffff;
719 TSXQueryColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &color);
720 return RGB(color.red >> 8, color.green >> 8, color.blue >> 8);
723 /***********************************************************************
724 * X11DRV_PALETTE_ToPhysical
726 * Return the physical color closest to 'color'.
728 int X11DRV_PALETTE_ToPhysical( DC *dc, COLORREF color )
731 HPALETTE16 hPal = (dc)? dc->hPalette: GetStockObject(DEFAULT_PALETTE);
732 unsigned char spec_type = color >> 24;
733 PALETTEOBJ* palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hPal, PALETTE_MAGIC );
735 /* palPtr can be NULL when DC is being destroyed */
736 if( !palPtr ) return 0;
738 if ( X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED )
740 /* there is no colormap limitation; we are going to have to compute
741 * the pixel value from the visual information stored earlier
744 unsigned long red, green, blue;
749 case 1: /* PALETTEINDEX */
751 if( (idx = color & 0xffff) >= palPtr->logpalette.palNumEntries)
753 WARN("RGB(%lx) : idx %d is out of bounds, assuming black\n", color, idx);
754 GDI_ReleaseObj( hPal );
758 if( palPtr->mapping )
760 int ret = palPtr->mapping[idx];
761 GDI_ReleaseObj( hPal );
764 color = *(COLORREF*)(palPtr->logpalette.palPalEntry + idx);
769 /* fall through to RGB */
772 if( dc && (dc->bitsPerPixel == 1) )
774 GDI_ReleaseObj( hPal );
775 return (((color >> 16) & 0xff) +
776 ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? 1 : 0;
781 red = GetRValue(color); green = GetGValue(color); blue = GetBValue(color);
783 if (X11DRV_PALETTE_Graymax)
785 /* grayscale only; return scaled value */
786 GDI_ReleaseObj( hPal );
787 return ( (red * 30 + green * 59 + blue * 11) * X11DRV_PALETTE_Graymax) / 25500;
791 /* scale each individually and construct the TrueColor pixel value */
792 if (X11DRV_PALETTE_Redscale != 8)
793 red = red >> (8-X11DRV_PALETTE_Redscale);
794 if (X11DRV_PALETTE_Greenscale != 8)
795 green = green >> (8-X11DRV_PALETTE_Greenscale);
796 if (X11DRV_PALETTE_Bluescale != 8)
797 blue = blue >> (8-X11DRV_PALETTE_Bluescale);
799 GDI_ReleaseObj( hPal );
800 return (red << X11DRV_PALETTE_Redshift) | (green << X11DRV_PALETTE_Greenshift) | (blue << X11DRV_PALETTE_Blueshift);
806 if( !palPtr->mapping )
807 WARN("Palette %04x is not realized\n", dc->hPalette);
809 switch(spec_type) /* we have to peruse DC and system palette */
813 /* fall through to RGB */
816 if( dc && (dc->bitsPerPixel == 1) )
818 GDI_ReleaseObj( hPal );
819 return (((color >> 16) & 0xff) +
820 ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? 1 : 0;
823 index = COLOR_PaletteLookupPixel( COLOR_sysPal, 256,
824 X11DRV_PALETTE_PaletteToXPixel, color, FALSE);
826 /* TRACE(palette,"RGB(%lx) -> pixel %i\n", color, index);
829 case 1: /* PALETTEINDEX */
830 index = color & 0xffff;
832 if( index >= palPtr->logpalette.palNumEntries )
833 WARN("RGB(%lx) : index %i is out of bounds\n", color, index);
834 else if( palPtr->mapping ) index = palPtr->mapping[index];
836 /* TRACE(palette,"PALETTEINDEX(%04x) -> pixel %i\n", (WORD)color, index);
839 case 2: /* PALETTERGB */
840 index = COLOR_PaletteLookupPixel( palPtr->logpalette.palPalEntry,
841 palPtr->logpalette.palNumEntries,
842 palPtr->mapping, color, FALSE);
843 /* TRACE(palette,"PALETTERGB(%lx) -> pixel %i\n", color, index);
849 GDI_ReleaseObj( hPal );
853 /***********************************************************************
854 * X11DRV_PALETTE_LookupSystemXPixel
856 static int X11DRV_PALETTE_LookupSystemXPixel(COLORREF col)
858 int i, best = 0, diff = 0x7fffffff;
859 int size = palette_size;
862 for( i = 0; i < size && diff ; i++ )
864 if( i == NB_RESERVED_COLORS/2 )
866 int newi = size - NB_RESERVED_COLORS/2;
870 r = COLOR_sysPal[i].peRed - GetRValue(col);
871 g = COLOR_sysPal[i].peGreen - GetGValue(col);
872 b = COLOR_sysPal[i].peBlue - GetBValue(col);
876 if( r < diff ) { best = i; diff = r; }
879 return (X11DRV_PALETTE_PaletteToXPixel)? X11DRV_PALETTE_PaletteToXPixel[best] : best;
882 /***********************************************************************
883 * X11DRV_PALETTE_FormatSystemPalette
885 static void X11DRV_PALETTE_FormatSystemPalette(void)
887 /* Build free list so we'd have an easy way to find
888 * out if there are any available colorcells.
891 int i, j = X11DRV_PALETTE_firstFree = NB_RESERVED_COLORS/2;
893 COLOR_sysPal[j].peFlags = 0;
894 for( i = NB_RESERVED_COLORS/2 + 1 ; i < 256 - NB_RESERVED_COLORS/2 ; i++ )
895 if( i < COLOR_gapStart || i > COLOR_gapEnd )
897 COLOR_sysPal[i].peFlags = 0; /* unused tag */
898 X11DRV_PALETTE_freeList[j] = i; /* next */
901 X11DRV_PALETTE_freeList[j] = 0;
904 /***********************************************************************
905 * X11DRV_PALETTE_CheckSysColor
907 static BOOL X11DRV_PALETTE_CheckSysColor(COLORREF c)
910 for( i = 0; i < NB_RESERVED_COLORS; i++ )
911 if( c == (*(COLORREF*)(COLOR_sysPalTemplate + i) & 0x00ffffff) )
916 /***********************************************************************
917 * X11DRV_PALETTE_SetMapping
919 * Set the color-mapping table for selected palette.
920 * Return number of entries which mapping has changed.
922 int X11DRV_PALETTE_SetMapping( PALETTEOBJ* palPtr, UINT uStart, UINT uNum, BOOL mapOnly )
925 int prevMapping = (palPtr->mapping) ? 1 : 0;
926 int index, iRemapped = 0;
929 /* reset dynamic system palette entries */
931 if( !mapOnly && X11DRV_PALETTE_firstFree != -1)
932 X11DRV_PALETTE_FormatSystemPalette();
934 /* initialize palette mapping table */
936 mapping = HeapReAlloc( GetProcessHeap(), 0, palPtr->mapping,
937 sizeof(int)*palPtr->logpalette.palNumEntries);
938 if(mapping == NULL) {
939 ERR("Can not allocate new mapping -- memory exausted!\n");
942 palPtr->mapping = mapping;
944 for( uNum += uStart; uStart < uNum; uStart++ )
949 switch( palPtr->logpalette.palPalEntry[uStart].peFlags & 0x07 )
951 case PC_EXPLICIT: /* palette entries are indices into system palette */
952 index = *(WORD*)(palPtr->logpalette.palPalEntry + uStart);
953 if( index > 255 || (index >= COLOR_gapStart && index <= COLOR_gapEnd) )
955 WARN("PC_EXPLICIT: idx %d out of system palette, assuming black.\n", index);
960 case PC_RESERVED: /* forbid future mappings to this entry */
961 flag |= PC_SYS_RESERVED;
964 default: /* try to collapse identical colors */
965 index = COLOR_PaletteLookupExactIndex(COLOR_sysPal, 256,
966 *(COLORREF*)(palPtr->logpalette.palPalEntry + uStart));
971 if( X11DRV_PALETTE_firstFree > 0 && !(X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_FIXED) )
974 index = X11DRV_PALETTE_firstFree; /* ought to be available */
975 X11DRV_PALETTE_firstFree = X11DRV_PALETTE_freeList[index];
977 color.pixel = (X11DRV_PALETTE_PaletteToXPixel) ? X11DRV_PALETTE_PaletteToXPixel[index] : index;
978 color.red = palPtr->logpalette.palPalEntry[uStart].peRed << 8;
979 color.green = palPtr->logpalette.palPalEntry[uStart].peGreen << 8;
980 color.blue = palPtr->logpalette.palPalEntry[uStart].peBlue << 8;
981 color.flags = DoRed | DoGreen | DoBlue;
982 TSXStoreColor(gdi_display, X11DRV_PALETTE_PaletteXColormap, &color);
984 COLOR_sysPal[index] = palPtr->logpalette.palPalEntry[uStart];
985 COLOR_sysPal[index].peFlags = flag;
986 X11DRV_PALETTE_freeList[index] = 0;
988 if( X11DRV_PALETTE_PaletteToXPixel ) index = X11DRV_PALETTE_PaletteToXPixel[index];
991 else if ( X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL )
993 index = X11DRV_PALETTE_ToPhysical( NULL, 0x00ffffff &
994 *(COLORREF*)(palPtr->logpalette.palPalEntry + uStart));
998 /* we have to map to existing entry in the system palette */
1000 index = COLOR_PaletteLookupPixel(COLOR_sysPal, 256, NULL,
1001 *(COLORREF*)(palPtr->logpalette.palPalEntry + uStart), TRUE);
1003 palPtr->logpalette.palPalEntry[uStart].peFlags |= PC_SYS_USED;
1005 if( X11DRV_PALETTE_PaletteToXPixel ) index = X11DRV_PALETTE_PaletteToXPixel[index];
1009 if( !prevMapping || palPtr->mapping[uStart] != index ) iRemapped++;
1010 palPtr->mapping[uStart] = index;
1012 TRACE("entry %i (%lx) -> pixel %i\n", uStart,
1013 *(COLORREF*)(palPtr->logpalette.palPalEntry + uStart), index);
1019 /***********************************************************************
1020 * X11DRV_PALETTE_UpdateMapping
1022 * Update the color-mapping table for selected palette.
1023 * Return number of entries which mapping has changed.
1025 int X11DRV_PALETTE_UpdateMapping(PALETTEOBJ *palPtr)
1027 int i, index, realized = 0;
1032 for( i = 0; i < 20; i++ )
1034 index = X11DRV_PALETTE_LookupSystemXPixel(*(COLORREF*)(palPtr->logpalette.palPalEntry + i));
1036 /* mapping is allocated in COLOR_InitPalette() */
1038 if( index != palPtr->mapping[i] ) { palPtr->mapping[i]=index; realized++; }
1044 /**************************************************************************
1045 * X11DRV_PALETTE_IsDark
1047 BOOL X11DRV_PALETTE_IsDark(int pixel)
1049 COLORREF col = X11DRV_PALETTE_ToLogical(pixel);
1050 return (GetRValue(col) + GetGValue(col) + GetBValue(col)) <= 0x180;