4 * Copyright 1993 Alexandre Julliard
17 Colormap COLOR_WinColormap
= 0;
18 static int COLOR_FixedMap
= 0;
20 static int COLOR_Redshift
= 0;
21 static int COLOR_Redmax
= 0;
22 static int COLOR_Greenshift
= 0;
23 static int COLOR_Greenmax
= 0;
24 static int COLOR_Blueshift
= 0;
25 static int COLOR_Bluemax
= 0;
26 static int COLOR_Graymax
= 0;
28 /* System palette static colors */
30 #define NB_RESERVED_COLORS 20
32 /* The first and last eight colors are EGA colors */
33 static PALETTEENTRY COLOR_sysPaletteEntries
[NB_RESERVED_COLORS
] =
35 /* red green blue flags */
36 { 0x00, 0x00, 0x00, 0 },
37 { 0x80, 0x00, 0x00, 0 },
38 { 0x00, 0x80, 0x00, 0 },
39 { 0x80, 0x80, 0x00, 0 },
40 { 0x00, 0x00, 0x80, 0 },
41 { 0x80, 0x00, 0x80, 0 },
42 { 0x00, 0x80, 0x80, 0 },
43 { 0xc0, 0xc0, 0xc0, 0 },
44 { 0xc0, 0xdc, 0xc0, 0 },
45 { 0xa6, 0xca, 0xf0, 0 },
47 { 0xff, 0xfb, 0xf0, 0 },
48 { 0xa0, 0xa0, 0xa4, 0 },
49 { 0x80, 0x80, 0x80, 0 },
50 { 0xff, 0x00, 0x00, 0 },
51 { 0x00, 0xff, 0x00, 0 },
52 { 0xff, 0xff, 0x00, 0 },
53 { 0x00, 0x00, 0xff, 0 },
54 { 0xff, 0x00, 0xff, 0 },
55 { 0x00, 0xff, 0xff, 0 },
56 { 0xff, 0xff, 0xff, 0 }
59 static HANDLE hSysColorTranslation
= 0;
60 static HANDLE hRevSysColorTranslation
= 0;
62 /* Map an EGA index (0..15) to a pixel value. Used for dithering. */
63 int COLOR_mapEGAPixel
[16];
65 int* COLOR_PaletteToPixel
= NULL
;
66 int* COLOR_PixelToPalette
= NULL
;
67 int COLOR_ColormapSize
= 0;
69 /***********************************************************************
72 * Fill the private colormap.
74 static BOOL
COLOR_BuildMap( Colormap map
, int depth
, int size
)
77 int r
, g
, b
, red_incr
, green_incr
, blue_incr
;
80 /* Fill the whole map with a range of colors */
82 blue_incr
= 0x10000 >> (depth
/ 3);
83 red_incr
= 0x10000 >> ((depth
+ 1) / 3);
84 green_incr
= 0x10000 >> ((depth
+ 2) / 3);
86 for (r
= red_incr
- 1; r
< 0x10000; r
+= red_incr
)
87 for (g
= green_incr
- 1; g
< 0x10000; g
+= green_incr
)
88 for (b
= blue_incr
- 1; b
< 0x10000; b
+= blue_incr
)
90 if (index
>= size
) break;
91 color
.pixel
= index
++;
95 XStoreColor( display
, map
, &color
);
102 /***********************************************************************
105 * Create the system palette.
107 static HPALETTE
COLOR_InitPalette(void)
113 WORD
*colorTranslation
, *revTranslation
;
115 size
= DefaultVisual( display
, DefaultScreen(display
) )->map_entries
;
116 COLOR_ColormapSize
= size
;
117 if (screenDepth
<= 8)
119 if (!(hSysColorTranslation
= GDI_HEAP_ALLOC(sizeof(WORD
)*NB_RESERVED_COLORS
)))
121 if (!(hRevSysColorTranslation
= GDI_HEAP_ALLOC( sizeof(WORD
)*size
)))
123 colorTranslation
= (WORD
*) GDI_HEAP_LIN_ADDR( hSysColorTranslation
);
124 revTranslation
= (WORD
*) GDI_HEAP_LIN_ADDR( hRevSysColorTranslation
);
126 else colorTranslation
= revTranslation
= NULL
;
128 if ((COLOR_WinColormap
== DefaultColormapOfScreen(screen
)) && (screenDepth
<= 8))
130 COLOR_PaletteToPixel
= (int *)xmalloc( sizeof(int) * size
);
131 COLOR_PixelToPalette
= (int *)xmalloc( sizeof(int) * size
);
132 for (i
= 0; i
< size
; i
++) /* Set the default mapping */
133 COLOR_PaletteToPixel
[i
] = COLOR_PixelToPalette
[i
] = i
;
136 for (i
= 0; i
< NB_RESERVED_COLORS
; i
++)
138 color
.red
= COLOR_sysPaletteEntries
[i
].peRed
* 65535 / 255;
139 color
.green
= COLOR_sysPaletteEntries
[i
].peGreen
* 65535 / 255;
140 color
.blue
= COLOR_sysPaletteEntries
[i
].peBlue
* 65535 / 255;
141 color
.flags
= DoRed
| DoGreen
| DoBlue
;
143 if (i
< NB_RESERVED_COLORS
/2)
145 /* Bottom half of the colormap */
147 if (pixel
>= size
/2) continue;
151 /* Top half of the colormap */
152 pixel
= size
- NB_RESERVED_COLORS
+ i
;
153 if (pixel
< size
/2) continue;
155 if (COLOR_WinColormap
!= DefaultColormapOfScreen(screen
))
158 XStoreColor( display
, COLOR_WinColormap
, &color
);
162 if (!XAllocColor( display
, COLOR_WinColormap
, &color
))
164 fprintf(stderr
, "Warning: Not enough free colors. Try using the -privatemap option.\n" );
165 color
.pixel
= color
.red
= color
.green
= color
.blue
= 0;
167 else if (COLOR_PaletteToPixel
)
169 COLOR_PaletteToPixel
[pixel
] = color
.pixel
;
170 COLOR_PixelToPalette
[color
.pixel
] = pixel
;
173 if (colorTranslation
) colorTranslation
[i
] = color
.pixel
;
174 if (revTranslation
) revTranslation
[color
.pixel
] = i
;
175 /* Set EGA mapping if color in the first or last eight */
177 COLOR_mapEGAPixel
[i
] = color
.pixel
;
178 else if (i
>= NB_RESERVED_COLORS
-8)
179 COLOR_mapEGAPixel
[i
- (NB_RESERVED_COLORS
-16)] = color
.pixel
;
182 palPtr
= malloc( sizeof(LOGPALETTE
) + (NB_RESERVED_COLORS
-1)*sizeof(PALETTEENTRY
) );
183 if (!palPtr
) return FALSE
;
184 palPtr
->palVersion
= 0x300;
185 palPtr
->palNumEntries
= NB_RESERVED_COLORS
;
186 memcpy( palPtr
->palPalEntry
, COLOR_sysPaletteEntries
,
187 sizeof(COLOR_sysPaletteEntries
) );
188 hpalette
= CreatePalette( palPtr
);
194 COLOR_Computeshifts(unsigned long maskbits
, int *shift
, int *max
)
204 for(i
=0;!(maskbits
&1);i
++)
211 /***********************************************************************
214 * Initialize color map and system palette.
216 HPALETTE
COLOR_Init(void)
218 Visual
* visual
= DefaultVisual( display
, DefaultScreen(display
) );
220 switch(visual
->class)
226 if (Options
.usePrivateMap
)
228 COLOR_WinColormap
= XCreateColormap( display
, rootWindow
,
230 if (COLOR_WinColormap
)
232 COLOR_BuildMap( COLOR_WinColormap
, screenDepth
,
233 visual
->map_entries
);
234 if (rootWindow
!= DefaultRootWindow(display
))
236 XSetWindowAttributes win_attr
;
237 win_attr
.colormap
= COLOR_WinColormap
;
238 XChangeWindowAttributes( display
, rootWindow
,
239 CWColormap
, &win_attr
);
244 COLOR_WinColormap
= DefaultColormapOfScreen( screen
);
247 COLOR_WinColormap
= DefaultColormapOfScreen( screen
);
249 COLOR_Graymax
= (1<<screenDepth
)-1;
253 COLOR_WinColormap
= DefaultColormapOfScreen( screen
);
255 COLOR_Computeshifts(visual
->red_mask
, &COLOR_Redshift
, &COLOR_Redmax
);
256 COLOR_Computeshifts(visual
->green_mask
, &COLOR_Greenshift
, &COLOR_Greenmax
);
257 COLOR_Computeshifts(visual
->blue_mask
, &COLOR_Blueshift
, &COLOR_Bluemax
);
260 return COLOR_InitPalette();
264 /***********************************************************************
267 * Check whether 'color' can be represented with a solid color.
269 BOOL
COLOR_IsSolid( COLORREF color
)
272 PALETTEENTRY
*pEntry
= COLOR_sysPaletteEntries
;
274 if (color
& 0xff000000) return TRUE
;
275 if (!color
|| (color
== 0xffffff)) return TRUE
;
276 for (i
= NB_RESERVED_COLORS
; i
> 0; i
--, pEntry
++)
278 if ((GetRValue(color
) == pEntry
->peRed
) &&
279 (GetGValue(color
) == pEntry
->peGreen
) &&
280 (GetBValue(color
) == pEntry
->peBlue
)) return TRUE
;
286 /***********************************************************************
289 * Return the physical color closest to 'color'.
291 * ESW: This still needs a lot of work; in particular, what happens when
292 * we have really large (> 8 bit) DirectColor boards?
293 * But it should work better in 16 and 24 bit modes now.
294 * (At least it pays attention to the X server's description
295 * in TrueColor mode, instead of blindly passing through the
296 * color spec and swapping red to blue or losing blue and part of the
297 * green entirely, depending on what mode one is in!)
300 int COLOR_ToPhysical( DC
*dc
, COLORREF color
)
305 if (dc
&& (dc
->w
.bitsPerPixel
== 1) && ((color
>> 24) == 0))
308 if (((color
>> 16) & 0xff) +
309 ((color
>> 8) & 0xff) + (color
& 0xff) > 255*3/2)
310 return 1; /* white */
311 else return 0; /* black */
316 /* there is no colormap possible; we are going to have to compute
317 the pixel value from the visual information stored earlier */
319 unsigned long red
, green
, blue
;
326 case 2: /* PALETTERGB -- needs some work, but why bother; we've got a REALLY LARGE number of colors...? */
328 red
= GetRValue(color
);
329 green
= GetGValue(color
);
330 blue
= GetBValue(color
);
333 case 1: /* PALETTEIDX -- hmm, get the real color from the stock palette */
334 palPtr
= (PALETTEOBJ
*) GDI_GetObjPtr( STOCK_DEFAULT_PALETTE
, PALETTE_MAGIC
);
335 idx
= color
& 0xffff;
336 if (idx
>= palPtr
->logpalette
.palNumEntries
)
338 fprintf(stderr
, "COLOR_ToPhysical(%lx) : idx %d is out of bounds, assuming black\n", color
, idx
);
340 red
= green
= blue
= 0;
344 red
= palPtr
->logpalette
.palPalEntry
[idx
].peRed
;
345 green
= palPtr
->logpalette
.palPalEntry
[idx
].peGreen
;
346 blue
= palPtr
->logpalette
.palPalEntry
[idx
].peBlue
;
352 /* grayscale only; return scaled value */
353 return ( (red
* 30 + green
* 69 + blue
* 11) * COLOR_Graymax
) / 25500;
357 /* scale each individually and construct the TrueColor pixel value */
358 if (COLOR_Redmax
!= 255) red
= (red
* COLOR_Redmax
) / 255;
359 if (COLOR_Greenmax
!= 255) green
= (green
* COLOR_Greenmax
) / 255;
360 if (COLOR_Bluemax
!= 255) blue
= (blue
* COLOR_Bluemax
) / 255;
362 return (red
<< COLOR_Redshift
) | (green
<< COLOR_Greenshift
) | (blue
<< COLOR_Blueshift
);
365 else switch(color
>> 24)
368 index
= GetNearestPaletteIndex( STOCK_DEFAULT_PALETTE
, color
);
370 case 1: /* PALETTEINDEX */
371 index
= color
& 0xffff;
373 case 2: /* PALETTERGB */
374 if (dc
) index
= GetNearestPaletteIndex( dc
->w
.hPalette
, color
);
378 if (dc
&&dc
->u
.x
.pal
.mappingSize
)
380 if (index
>= dc
->u
.x
.pal
.mappingSize
)
382 fprintf(stderr
, "COLOR_ToPhysical(%lx) : idx %d is >= dc->u.x.pal.mappingSize, assuming pixel 0\n", color
, index
);
385 mapping
= (WORD
*) GDI_HEAP_LIN_ADDR( dc
->u
.x
.pal
.hMapping
);
389 if (index
>= NB_RESERVED_COLORS
)
391 fprintf(stderr
, "COLOR_ToPhysical(%lx) : idx %d is >= NB_RESERVED_COLORS, assuming pixel 0\n", color
, index
);
394 mapping
= (WORD
*) GDI_HEAP_LIN_ADDR( hSysColorTranslation
);
396 if (mapping
) return mapping
[index
];
397 else return index
; /* Identity mapping */
401 /***********************************************************************
404 * Set the color-mapping table in a DC.
406 void COLOR_SetMapping( DC
*dc
, HANDLE map
, HANDLE revMap
, WORD size
)
408 WORD
*pmap
, *pnewmap
;
411 if (dc
->u
.x
.pal
.hMapping
&& (dc
->u
.x
.pal
.hMapping
!= hSysColorTranslation
))
412 GDI_HEAP_FREE( dc
->u
.x
.pal
.hMapping
);
413 if (dc
->u
.x
.pal
.hRevMapping
&&
414 (dc
->u
.x
.pal
.hRevMapping
!= hRevSysColorTranslation
))
415 GDI_HEAP_FREE( dc
->u
.x
.pal
.hRevMapping
);
416 if (map
&& (map
!= hSysColorTranslation
))
418 /* Copy mapping table */
419 dc
->u
.x
.pal
.hMapping
= GDI_HEAP_ALLOC( sizeof(WORD
) * size
);
420 pmap
= (WORD
*) GDI_HEAP_LIN_ADDR( map
);
421 pnewmap
= (WORD
*) GDI_HEAP_LIN_ADDR( dc
->u
.x
.pal
.hMapping
);
422 memcpy( pnewmap
, pmap
, sizeof(WORD
)*size
);
423 /* Build reverse table */
424 dc
->u
.x
.pal
.hRevMapping
= GDI_HEAP_ALLOC(sizeof(WORD
)*COLOR_ColormapSize
);
425 pmap
= (WORD
*) GDI_HEAP_LIN_ADDR( dc
->u
.x
.pal
.hRevMapping
);
426 for (i
= 0; i
< size
; i
++) pmap
[pnewmap
[i
]] = i
;
430 dc
->u
.x
.pal
.hMapping
= map
;
431 dc
->u
.x
.pal
.hRevMapping
= map
? hRevSysColorTranslation
: 0;
433 dc
->u
.x
.pal
.mappingSize
= size
;
437 /***********************************************************************
438 * RealizeDefaultPalette (GDI.365)
440 WORD
RealizeDefaultPalette( HDC hdc
)
443 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return 0;
444 dc
->w
.hPalette
= STOCK_DEFAULT_PALETTE
;
445 COLOR_SetMapping( dc
, hSysColorTranslation
,
446 hRevSysColorTranslation
, NB_RESERVED_COLORS
);
447 return NB_RESERVED_COLORS
;