Release 951003
[wine/multimedia.git] / objects / color.c
blob5941340a61bf5c73cca1fe0d0355c57f65ac8e39
1 /*
2 * Color functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <X11/Xlib.h>
9 #include <stdio.h>
10 #include "windows.h"
11 #include "options.h"
12 #include "gdi.h"
13 #include "color.h"
14 #include "palette.h"
16 Colormap COLOR_WinColormap = 0;
17 int COLOR_FixedMap = 0;
19 int COLOR_Redshift = 0;
20 int COLOR_Redmax = 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 /***********************************************************************
69 * COLOR_BuildMap
71 * Fill the private colormap.
73 static BOOL COLOR_BuildMap( Colormap map, int depth, int size )
75 XColor color;
76 int r, g, b, red_incr, green_incr, blue_incr;
77 int index = 0;
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++;
91 color.red = r;
92 color.green = g;
93 color.blue = b;
94 XStoreColor( display, map, &color );
97 return TRUE;
101 /***********************************************************************
102 * COLOR_InitPalette
104 * Create the system palette.
106 static HPALETTE COLOR_InitPalette(void)
108 int i, size, pixel;
109 XColor color;
110 HPALETTE hpalette;
111 LOGPALETTE * palPtr;
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 )))
119 return FALSE;
120 if (!(hRevSysColorTranslation = GDI_HEAP_ALLOC( sizeof(WORD)*size )))
121 return FALSE;
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 */
145 pixel = i;
146 if (pixel >= size/2) continue;
148 else
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))
156 color.pixel = pixel;
157 XStoreColor( display, COLOR_WinColormap, &color );
159 else
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 */
175 if (i < 8)
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 );
188 free( palPtr );
189 return hpalette;
192 void
193 COLOR_Computeshifts(unsigned long maskbits, int *shift, int *max)
195 int i;
197 if(maskbits==0) {
198 *shift=0;
199 *max=0;
200 return;
203 for(i=0;!(maskbits&1);i++)
204 maskbits >>= 1;
206 *shift = i;
207 *max = maskbits;
210 /***********************************************************************
211 * COLOR_Init
213 * Initialize color map and system palette.
215 HPALETTE COLOR_Init(void)
217 Visual * visual = DefaultVisual( display, DefaultScreen(display) );
219 switch(visual->class)
221 case GrayScale:
222 case PseudoColor:
223 case DirectColor:
224 COLOR_FixedMap = 0;
225 if (Options.usePrivateMap)
227 COLOR_WinColormap = XCreateColormap( display, rootWindow,
228 visual, AllocAll );
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 );
240 break;
243 COLOR_WinColormap = DefaultColormapOfScreen( screen );
244 break;
245 case StaticGray:
246 COLOR_WinColormap = DefaultColormapOfScreen( screen );
247 COLOR_FixedMap = 1;
248 COLOR_Graymax = (1<<screenDepth)-1;
249 break;
250 case StaticColor:
251 case TrueColor:
252 COLOR_WinColormap = DefaultColormapOfScreen( screen );
253 COLOR_FixedMap = 1;
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);
257 break;
259 return COLOR_InitPalette();
263 /***********************************************************************
264 * COLOR_IsSolid
266 * Check whether 'color' can be represented with a solid color.
268 BOOL COLOR_IsSolid( COLORREF color )
270 int i;
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;
281 return FALSE;
285 /***********************************************************************
286 * COLOR_ToPhysical
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 )
301 WORD index = 0;
302 WORD *mapping;
304 if (dc && (dc->w.bitsPerPixel == 1) && ((color >> 24) == 0))
306 /* monochrome */
307 if (((color >> 16) & 0xff) +
308 ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2)
309 return 1; /* white */
310 else return 0; /* black */
313 if (COLOR_FixedMap)
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;
319 unsigned idx;
320 PALETTEOBJ * palPtr;
322 switch(color >> 24)
324 case 0: /* RGB */
325 case 2: /* PALETTERGB -- needs some work, but why bother; we've got a REALLY LARGE number of colors...? */
326 default:
327 red = GetRValue(color);
328 green = GetGValue(color);
329 blue = GetBValue(color);
330 break;
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)
337 /* out of bounds */
338 red = green = blue = 0;
340 else
342 red = palPtr->logpalette.palPalEntry[idx].peRed;
343 green = palPtr->logpalette.palPalEntry[idx].peGreen;
344 blue = palPtr->logpalette.palPalEntry[idx].peBlue;
348 if (COLOR_Graymax)
350 /* grayscale only; return scaled value */
351 return ( (red * 30 + green * 69 + blue * 11) * COLOR_Graymax) / 25500;
353 else
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)
365 case 0: /* RGB */
366 index = GetNearestPaletteIndex( STOCK_DEFAULT_PALETTE, color );
367 break;
368 case 1: /* PALETTEINDEX */
369 index = color & 0xffff;
370 break;
371 case 2: /* PALETTERGB */
372 if (dc) index = GetNearestPaletteIndex( dc->w.hPalette, color );
373 else index = 0;
374 break;
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 );
381 else
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 /***********************************************************************
392 * COLOR_SetMapping
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;
399 WORD i;
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;
418 else
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 )
432 WORD index;
433 DC *dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
434 if (!dc) return 0;
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 )
446 DC *dc;
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;