4 * Copyright 1993 Alexandre Julliard
16 Colormap COLOR_WinColormap
= 0;
17 int COLOR_FixedMap
= 0;
19 int COLOR_Redshift
= 0;
21 int COLOR_Greenshift
= 0;
22 int COLOR_Greenmax
= 0;
23 int COLOR_Blueshift
= 0;
24 int COLOR_Bluemax
= 0;
25 int COLOR_Graymax
= 0;
27 /* System palette static colors */
29 #define NB_RESERVED_COLORS 20
31 /* The first and last eight colors are EGA colors */
32 static PALETTEENTRY COLOR_sysPaletteEntries
[NB_RESERVED_COLORS
] =
34 /* red green blue flags */
35 { 0x00, 0x00, 0x00, 0 },
36 { 0x80, 0x00, 0x00, 0 },
37 { 0x00, 0x80, 0x00, 0 },
38 { 0x80, 0x80, 0x00, 0 },
39 { 0x00, 0x00, 0x80, 0 },
40 { 0x80, 0x00, 0x80, 0 },
41 { 0x00, 0x80, 0x80, 0 },
42 { 0xc0, 0xc0, 0xc0, 0 },
43 { 0xc0, 0xdc, 0xc0, 0 },
44 { 0xa6, 0xca, 0xf0, 0 },
46 { 0xff, 0xfb, 0xf0, 0 },
47 { 0xa0, 0xa0, 0xa4, 0 },
48 { 0x80, 0x80, 0x80, 0 },
49 { 0xff, 0x00, 0x00, 0 },
50 { 0x00, 0xff, 0x00, 0 },
51 { 0xff, 0xff, 0x00, 0 },
52 { 0x00, 0x00, 0xff, 0 },
53 { 0xff, 0x00, 0xff, 0 },
54 { 0x00, 0xff, 0xff, 0 },
55 { 0xff, 0xff, 0xff, 0 }
58 static HANDLE hSysColorTranslation
= 0;
59 static HANDLE hRevSysColorTranslation
= 0;
61 /* Map an EGA index (0..15) to a pixel value. Used for dithering. */
62 int COLOR_mapEGAPixel
[16];
64 int* COLOR_PaletteToPixel
= NULL
;
65 int* COLOR_PixelToPalette
= NULL
;
66 int COLOR_ColormapSize
= 0;
68 /***********************************************************************
71 * Fill the private colormap.
73 static BOOL
COLOR_BuildMap( Colormap map
, int depth
, int size
)
76 int r
, g
, b
, red_incr
, green_incr
, blue_incr
;
79 /* Fill the whole map with a range of colors */
81 blue_incr
= 0x10000 >> (depth
/ 3);
82 red_incr
= 0x10000 >> ((depth
+ 1) / 3);
83 green_incr
= 0x10000 >> ((depth
+ 2) / 3);
85 for (r
= red_incr
- 1; r
< 0x10000; r
+= red_incr
)
86 for (g
= green_incr
- 1; g
< 0x10000; g
+= green_incr
)
87 for (b
= blue_incr
- 1; b
< 0x10000; b
+= blue_incr
)
89 if (index
>= size
) break;
90 color
.pixel
= index
++;
94 XStoreColor( display
, map
, &color
);
101 /***********************************************************************
104 * Create the system palette.
106 static HPALETTE
COLOR_InitPalette(void)
112 WORD
*colorTranslation
, *revTranslation
;
114 size
= DefaultVisual( display
, DefaultScreen(display
) )->map_entries
;
115 COLOR_ColormapSize
= size
;
116 if (screenDepth
<= 8)
118 if (!(hSysColorTranslation
= GDI_HEAP_ALLOC(sizeof(WORD
)*NB_RESERVED_COLORS
)))
120 if (!(hRevSysColorTranslation
= GDI_HEAP_ALLOC( sizeof(WORD
)*size
)))
122 colorTranslation
= (WORD
*) GDI_HEAP_LIN_ADDR( hSysColorTranslation
);
123 revTranslation
= (WORD
*) GDI_HEAP_LIN_ADDR( hRevSysColorTranslation
);
125 else colorTranslation
= revTranslation
= NULL
;
127 if ((COLOR_WinColormap
== DefaultColormapOfScreen(screen
)) && (screenDepth
<= 8))
129 COLOR_PaletteToPixel
= (int *)malloc( sizeof(int) * size
);
130 COLOR_PixelToPalette
= (int *)malloc( sizeof(int) * size
);
131 for (i
= 0; i
< size
; i
++) /* Set the default mapping */
132 COLOR_PaletteToPixel
[i
] = COLOR_PixelToPalette
[i
] = i
;
135 for (i
= 0; i
< NB_RESERVED_COLORS
; i
++)
137 color
.red
= COLOR_sysPaletteEntries
[i
].peRed
* 65535 / 255;
138 color
.green
= COLOR_sysPaletteEntries
[i
].peGreen
* 65535 / 255;
139 color
.blue
= COLOR_sysPaletteEntries
[i
].peBlue
* 65535 / 255;
140 color
.flags
= DoRed
| DoGreen
| DoBlue
;
142 if (i
< NB_RESERVED_COLORS
/2)
144 /* Bottom half of the colormap */
146 if (pixel
>= size
/2) continue;
150 /* Top half of the colormap */
151 pixel
= size
- NB_RESERVED_COLORS
+ i
;
152 if (pixel
< size
/2) continue;
154 if (COLOR_WinColormap
!= DefaultColormapOfScreen(screen
))
157 XStoreColor( display
, COLOR_WinColormap
, &color
);
161 if (!XAllocColor( display
, COLOR_WinColormap
, &color
))
163 fprintf(stderr
, "Warning: Not enough free colors. Try using the -privatemap option.\n" );
164 color
.pixel
= color
.red
= color
.green
= color
.blue
= 0;
166 else if (COLOR_PaletteToPixel
)
168 COLOR_PaletteToPixel
[pixel
] = color
.pixel
;
169 COLOR_PixelToPalette
[color
.pixel
] = pixel
;
172 if (colorTranslation
) colorTranslation
[i
] = color
.pixel
;
173 if (revTranslation
) revTranslation
[color
.pixel
] = i
;
174 /* Set EGA mapping if color in the first or last eight */
176 COLOR_mapEGAPixel
[i
] = color
.pixel
;
177 else if (i
>= NB_RESERVED_COLORS
-8)
178 COLOR_mapEGAPixel
[i
- (NB_RESERVED_COLORS
-16)] = color
.pixel
;
181 palPtr
= malloc( sizeof(LOGPALETTE
) + (NB_RESERVED_COLORS
-1)*sizeof(PALETTEENTRY
) );
182 if (!palPtr
) return FALSE
;
183 palPtr
->palVersion
= 0x300;
184 palPtr
->palNumEntries
= NB_RESERVED_COLORS
;
185 memcpy( palPtr
->palPalEntry
, COLOR_sysPaletteEntries
,
186 sizeof(COLOR_sysPaletteEntries
) );
187 hpalette
= CreatePalette( palPtr
);
193 COLOR_Computeshifts(unsigned long maskbits
, int *shift
, int *max
)
203 for(i
=0;!(maskbits
&1);i
++)
210 /***********************************************************************
213 * Initialize color map and system palette.
215 HPALETTE
COLOR_Init(void)
217 Visual
* visual
= DefaultVisual( display
, DefaultScreen(display
) );
219 switch(visual
->class)
225 if (Options
.usePrivateMap
)
227 COLOR_WinColormap
= XCreateColormap( display
, rootWindow
,
229 if (COLOR_WinColormap
)
231 COLOR_BuildMap( COLOR_WinColormap
, screenDepth
,
232 visual
->map_entries
);
233 if (rootWindow
!= DefaultRootWindow(display
))
235 XSetWindowAttributes win_attr
;
236 win_attr
.colormap
= COLOR_WinColormap
;
237 XChangeWindowAttributes( display
, rootWindow
,
238 CWColormap
, &win_attr
);
243 COLOR_WinColormap
= DefaultColormapOfScreen( screen
);
246 COLOR_WinColormap
= DefaultColormapOfScreen( screen
);
248 COLOR_Graymax
= (1<<screenDepth
)-1;
252 COLOR_WinColormap
= DefaultColormapOfScreen( screen
);
254 COLOR_Computeshifts(visual
->red_mask
, &COLOR_Redshift
, &COLOR_Redmax
);
255 COLOR_Computeshifts(visual
->green_mask
, &COLOR_Greenshift
, &COLOR_Greenmax
);
256 COLOR_Computeshifts(visual
->blue_mask
, &COLOR_Blueshift
, &COLOR_Bluemax
);
259 return COLOR_InitPalette();
263 /***********************************************************************
266 * Check whether 'color' can be represented with a solid color.
268 BOOL
COLOR_IsSolid( COLORREF color
)
271 PALETTEENTRY
*pEntry
= COLOR_sysPaletteEntries
;
273 if (color
& 0xff000000) return TRUE
;
274 if (!color
|| (color
== 0xffffff)) return TRUE
;
275 for (i
= NB_RESERVED_COLORS
; i
> 0; i
--, pEntry
++)
277 if ((GetRValue(color
) == pEntry
->peRed
) &&
278 (GetGValue(color
) == pEntry
->peGreen
) &&
279 (GetBValue(color
) == pEntry
->peBlue
)) return TRUE
;
285 /***********************************************************************
288 * Return the physical color closest to 'color'.
290 * ESW: This still needs a lot of work; in particular, what happens when
291 * we have really large (> 8 bit) DirectColor boards?
292 * But it should work better in 16 and 24 bit modes now.
293 * (At least it pays attention to the X server's description
294 * in TrueColor mode, instead of blindly passing through the
295 * color spec and swapping red to blue or losing blue and part of the
296 * green entirely, depending on what mode one is in!)
299 int COLOR_ToPhysical( DC
*dc
, COLORREF color
)
304 if (dc
&& (dc
->w
.bitsPerPixel
== 1) && ((color
>> 24) == 0))
307 if (((color
>> 16) & 0xff) +
308 ((color
>> 8) & 0xff) + (color
& 0xff) > 255*3/2)
309 return 1; /* white */
310 else return 0; /* black */
315 /* there is no colormap possible; we are going to have to compute
316 the pixel value from the visual information stored earlier */
318 unsigned long red
, green
, blue
;
325 case 2: /* PALETTERGB -- needs some work, but why bother; we've got a REALLY LARGE number of colors...? */
327 red
= GetRValue(color
);
328 green
= GetGValue(color
);
329 blue
= GetBValue(color
);
332 case 1: /* PALETTEIDX -- hmm, get the real color from the stock palette */
333 palPtr
= (PALETTEOBJ
*) GDI_GetObjPtr( STOCK_DEFAULT_PALETTE
, PALETTE_MAGIC
);
334 idx
= color
& 0xffff;
335 if (idx
>= palPtr
->logpalette
.palNumEntries
)
338 red
= green
= blue
= 0;
342 red
= palPtr
->logpalette
.palPalEntry
[idx
].peRed
;
343 green
= palPtr
->logpalette
.palPalEntry
[idx
].peGreen
;
344 blue
= palPtr
->logpalette
.palPalEntry
[idx
].peBlue
;
350 /* grayscale only; return scaled value */
351 return ( (red
* 30 + green
* 69 + blue
* 11) * COLOR_Graymax
) / 25500;
355 /* scale each individually and construct the TrueColor pixel value */
356 if (COLOR_Redmax
!= 255) red
= (red
* COLOR_Redmax
) / 255;
357 if (COLOR_Greenmax
!= 255) green
= (green
* COLOR_Greenmax
) / 255;
358 if (COLOR_Bluemax
!= 255) blue
= (blue
* COLOR_Bluemax
) / 255;
360 return (red
<< COLOR_Redshift
) | (green
<< COLOR_Greenshift
) | (blue
<< COLOR_Blueshift
);
363 else switch(color
>> 24)
366 index
= GetNearestPaletteIndex( STOCK_DEFAULT_PALETTE
, color
);
368 case 1: /* PALETTEINDEX */
369 index
= color
& 0xffff;
371 case 2: /* PALETTERGB */
372 if (dc
) index
= GetNearestPaletteIndex( dc
->w
.hPalette
, color
);
376 if (dc
&&dc
->u
.x
.pal
.mappingSize
)
378 if (index
>= dc
->u
.x
.pal
.mappingSize
) return 0;
379 mapping
= (WORD
*) GDI_HEAP_LIN_ADDR( dc
->u
.x
.pal
.hMapping
);
383 if (index
>= NB_RESERVED_COLORS
) return 0;
384 mapping
= (WORD
*) GDI_HEAP_LIN_ADDR( hSysColorTranslation
);
386 if (mapping
) return mapping
[index
];
387 else return index
; /* Identity mapping */
391 /***********************************************************************
394 * Set the color-mapping table in a DC.
396 void COLOR_SetMapping( DC
*dc
, HANDLE map
, HANDLE revMap
, WORD size
)
398 WORD
*pmap
, *pnewmap
;
401 if (dc
->u
.x
.pal
.hMapping
&& (dc
->u
.x
.pal
.hMapping
!= hSysColorTranslation
))
402 GDI_HEAP_FREE( dc
->u
.x
.pal
.hMapping
);
403 if (dc
->u
.x
.pal
.hRevMapping
&&
404 (dc
->u
.x
.pal
.hRevMapping
!= hRevSysColorTranslation
))
405 GDI_HEAP_FREE( dc
->u
.x
.pal
.hRevMapping
);
406 if (map
&& (map
!= hSysColorTranslation
))
408 /* Copy mapping table */
409 dc
->u
.x
.pal
.hMapping
= GDI_HEAP_ALLOC( sizeof(WORD
) * size
);
410 pmap
= (WORD
*) GDI_HEAP_LIN_ADDR( map
);
411 pnewmap
= (WORD
*) GDI_HEAP_LIN_ADDR( dc
->u
.x
.pal
.hMapping
);
412 memcpy( pnewmap
, pmap
, sizeof(WORD
)*size
);
413 /* Build reverse table */
414 dc
->u
.x
.pal
.hRevMapping
= GDI_HEAP_ALLOC(sizeof(WORD
)*COLOR_ColormapSize
);
415 pmap
= (WORD
*) GDI_HEAP_LIN_ADDR( dc
->u
.x
.pal
.hRevMapping
);
416 for (i
= 0; i
< size
; i
++) pmap
[pnewmap
[i
]] = i
;
420 dc
->u
.x
.pal
.hMapping
= map
;
421 dc
->u
.x
.pal
.hRevMapping
= map
? hRevSysColorTranslation
: 0;
423 dc
->u
.x
.pal
.mappingSize
= size
;
427 /***********************************************************************
428 * GetNearestColor (GDI.154)
430 COLORREF
GetNearestColor( HDC hdc
, COLORREF color
)
433 DC
*dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
435 if (screenDepth
> 8) return color
; /* FIXME */
436 index
= (WORD
)(COLOR_ToPhysical( dc
, color
& 0xffffff ) & 0xffff);
437 return PALETTEINDEX( index
);
441 /***********************************************************************
442 * RealizeDefaultPalette (GDI.365)
444 WORD
RealizeDefaultPalette( HDC hdc
)
447 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return 0;
448 dc
->w
.hPalette
= STOCK_DEFAULT_PALETTE
;
449 COLOR_SetMapping( dc
, hSysColorTranslation
,
450 hRevSysColorTranslation
, NB_RESERVED_COLORS
);
451 return NB_RESERVED_COLORS
;