Release 951124
[wine/multimedia.git] / objects / color.c
blob03cefa9a85c09526ff99261762d34839cf311d38
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"
15 #include "xmalloc.h"
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 /***********************************************************************
70 * COLOR_BuildMap
72 * Fill the private colormap.
74 static BOOL COLOR_BuildMap( Colormap map, int depth, int size )
76 XColor color;
77 int r, g, b, red_incr, green_incr, blue_incr;
78 int index = 0;
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++;
92 color.red = r;
93 color.green = g;
94 color.blue = b;
95 XStoreColor( display, map, &color );
98 return TRUE;
102 /***********************************************************************
103 * COLOR_InitPalette
105 * Create the system palette.
107 static HPALETTE COLOR_InitPalette(void)
109 int i, size, pixel;
110 XColor color;
111 HPALETTE hpalette;
112 LOGPALETTE * palPtr;
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 )))
120 return FALSE;
121 if (!(hRevSysColorTranslation = GDI_HEAP_ALLOC( sizeof(WORD)*size )))
122 return FALSE;
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 */
146 pixel = i;
147 if (pixel >= size/2) continue;
149 else
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))
157 color.pixel = pixel;
158 XStoreColor( display, COLOR_WinColormap, &color );
160 else
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 */
176 if (i < 8)
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 );
189 free( palPtr );
190 return hpalette;
193 void
194 COLOR_Computeshifts(unsigned long maskbits, int *shift, int *max)
196 int i;
198 if(maskbits==0) {
199 *shift=0;
200 *max=0;
201 return;
204 for(i=0;!(maskbits&1);i++)
205 maskbits >>= 1;
207 *shift = i;
208 *max = maskbits;
211 /***********************************************************************
212 * COLOR_Init
214 * Initialize color map and system palette.
216 HPALETTE COLOR_Init(void)
218 Visual * visual = DefaultVisual( display, DefaultScreen(display) );
220 switch(visual->class)
222 case GrayScale:
223 case PseudoColor:
224 case DirectColor:
225 COLOR_FixedMap = 0;
226 if (Options.usePrivateMap)
228 COLOR_WinColormap = XCreateColormap( display, rootWindow,
229 visual, AllocAll );
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 );
241 break;
244 COLOR_WinColormap = DefaultColormapOfScreen( screen );
245 break;
246 case StaticGray:
247 COLOR_WinColormap = DefaultColormapOfScreen( screen );
248 COLOR_FixedMap = 1;
249 COLOR_Graymax = (1<<screenDepth)-1;
250 break;
251 case StaticColor:
252 case TrueColor:
253 COLOR_WinColormap = DefaultColormapOfScreen( screen );
254 COLOR_FixedMap = 1;
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);
258 break;
260 return COLOR_InitPalette();
264 /***********************************************************************
265 * COLOR_IsSolid
267 * Check whether 'color' can be represented with a solid color.
269 BOOL COLOR_IsSolid( COLORREF color )
271 int i;
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;
282 return FALSE;
286 /***********************************************************************
287 * COLOR_ToPhysical
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 )
302 WORD index = 0;
303 WORD *mapping;
305 if (dc && (dc->w.bitsPerPixel == 1) && ((color >> 24) == 0))
307 /* monochrome */
308 if (((color >> 16) & 0xff) +
309 ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2)
310 return 1; /* white */
311 else return 0; /* black */
314 if (COLOR_FixedMap)
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;
320 unsigned idx;
321 PALETTEOBJ * palPtr;
323 switch(color >> 24)
325 case 0: /* RGB */
326 case 2: /* PALETTERGB -- needs some work, but why bother; we've got a REALLY LARGE number of colors...? */
327 default:
328 red = GetRValue(color);
329 green = GetGValue(color);
330 blue = GetBValue(color);
331 break;
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);
339 /* out of bounds */
340 red = green = blue = 0;
342 else
344 red = palPtr->logpalette.palPalEntry[idx].peRed;
345 green = palPtr->logpalette.palPalEntry[idx].peGreen;
346 blue = palPtr->logpalette.palPalEntry[idx].peBlue;
350 if (COLOR_Graymax)
352 /* grayscale only; return scaled value */
353 return ( (red * 30 + green * 69 + blue * 11) * COLOR_Graymax) / 25500;
355 else
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)
367 case 0: /* RGB */
368 index = GetNearestPaletteIndex( STOCK_DEFAULT_PALETTE, color );
369 break;
370 case 1: /* PALETTEINDEX */
371 index = color & 0xffff;
372 break;
373 case 2: /* PALETTERGB */
374 if (dc) index = GetNearestPaletteIndex( dc->w.hPalette, color );
375 else index = 0;
376 break;
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);
383 return 0;
385 mapping = (WORD *) GDI_HEAP_LIN_ADDR( dc->u.x.pal.hMapping );
387 else
389 if (index >= NB_RESERVED_COLORS)
391 fprintf(stderr, "COLOR_ToPhysical(%lx) : idx %d is >= NB_RESERVED_COLORS, assuming pixel 0\n", color, index);
392 return 0;
394 mapping = (WORD *) GDI_HEAP_LIN_ADDR( hSysColorTranslation );
396 if (mapping) return mapping[index];
397 else return index; /* Identity mapping */
401 /***********************************************************************
402 * COLOR_SetMapping
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;
409 WORD i;
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;
428 else
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 )
442 DC *dc;
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;