Release 960611
[wine/multimedia.git] / objects / color.c
blob6868a22e4e2c13ef114bc7eb03d6b8810ef7aad3
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 "stddebug.h"
16 #include "debug.h"
17 #include "xmalloc.h"
19 Colormap COLOR_WinColormap = 0;
20 static int COLOR_FixedMap = 0;
22 static int COLOR_Redshift = 0;
23 static int COLOR_Redmax = 0;
24 static int COLOR_Greenshift = 0;
25 static int COLOR_Greenmax = 0;
26 static int COLOR_Blueshift = 0;
27 static int COLOR_Bluemax = 0;
28 static int COLOR_Graymax = 0;
30 /* System palette static colors */
32 #define NB_RESERVED_COLORS 20
34 /* The first and last eight colors are EGA colors */
35 static const PALETTEENTRY COLOR_sysPaletteEntries[NB_RESERVED_COLORS] =
37 /* red green blue flags */
38 { 0x00, 0x00, 0x00, 0 },
39 { 0x80, 0x00, 0x00, 0 },
40 { 0x00, 0x80, 0x00, 0 },
41 { 0x80, 0x80, 0x00, 0 },
42 { 0x00, 0x00, 0x80, 0 },
43 { 0x80, 0x00, 0x80, 0 },
44 { 0x00, 0x80, 0x80, 0 },
45 { 0xc0, 0xc0, 0xc0, 0 },
46 { 0xc0, 0xdc, 0xc0, 0 },
47 { 0xa6, 0xca, 0xf0, 0 },
49 { 0xff, 0xfb, 0xf0, 0 },
50 { 0xa0, 0xa0, 0xa4, 0 },
51 { 0x80, 0x80, 0x80, 0 },
52 { 0xff, 0x00, 0x00, 0 },
53 { 0x00, 0xff, 0x00, 0 },
54 { 0xff, 0xff, 0x00, 0 },
55 { 0x00, 0x00, 0xff, 0 },
56 { 0xff, 0x00, 0xff, 0 },
57 { 0x00, 0xff, 0xff, 0 },
58 { 0xff, 0xff, 0xff, 0 }
61 static HANDLE hSysColorTranslation = 0;
62 static HANDLE hRevSysColorTranslation = 0;
64 /* Map an EGA index (0..15) to a pixel value. Used for dithering. */
65 int COLOR_mapEGAPixel[16];
67 int* COLOR_PaletteToPixel = NULL;
68 int* COLOR_PixelToPalette = NULL;
69 int COLOR_ColormapSize = 0;
71 /***********************************************************************
72 * COLOR_BuildMap
74 * Fill the private colormap.
76 static BOOL COLOR_BuildMap( Colormap map, int depth, int size )
78 XColor color;
79 int r, g, b, red_incr, green_incr, blue_incr;
80 int index = 0;
82 /* Fill the whole map with a range of colors */
84 blue_incr = 0x10000 >> (depth / 3);
85 red_incr = 0x10000 >> ((depth + 1) / 3);
86 green_incr = 0x10000 >> ((depth + 2) / 3);
88 for (r = red_incr - 1; r < 0x10000; r += red_incr)
89 for (g = green_incr - 1; g < 0x10000; g += green_incr)
90 for (b = blue_incr - 1; b < 0x10000; b += blue_incr)
92 if (index >= size) break;
93 color.pixel = index++;
94 color.red = r;
95 color.green = g;
96 color.blue = b;
97 XStoreColor( display, map, &color );
100 return TRUE;
104 /***********************************************************************
105 * COLOR_InitPalette
107 * Create the system palette.
109 static HPALETTE16 COLOR_InitPalette(void)
111 int i, size, pixel;
112 XColor color;
113 HPALETTE16 hpalette;
114 LOGPALETTE * palPtr;
115 WORD *colorTranslation, *revTranslation;
117 size = DefaultVisual( display, DefaultScreen(display) )->map_entries;
118 COLOR_ColormapSize = size;
119 if (screenDepth <= 8)
121 if (!(hSysColorTranslation = GDI_HEAP_ALLOC(sizeof(WORD)*NB_RESERVED_COLORS )))
122 return FALSE;
123 if (!(hRevSysColorTranslation = GDI_HEAP_ALLOC( sizeof(WORD)*size )))
124 return FALSE;
125 colorTranslation = (WORD *) GDI_HEAP_LIN_ADDR( hSysColorTranslation );
126 revTranslation = (WORD *) GDI_HEAP_LIN_ADDR( hRevSysColorTranslation );
128 else colorTranslation = revTranslation = NULL;
130 if ((COLOR_WinColormap == DefaultColormapOfScreen(screen)) && (screenDepth <= 8))
132 COLOR_PaletteToPixel = (int *)xmalloc( sizeof(int) * size );
133 COLOR_PixelToPalette = (int *)xmalloc( sizeof(int) * size );
134 for (i = 0; i < size; i++) /* Set the default mapping */
135 COLOR_PaletteToPixel[i] = COLOR_PixelToPalette[i] = i;
138 for (i = 0; i < NB_RESERVED_COLORS; i++)
140 color.red = COLOR_sysPaletteEntries[i].peRed * 65535 / 255;
141 color.green = COLOR_sysPaletteEntries[i].peGreen * 65535 / 255;
142 color.blue = COLOR_sysPaletteEntries[i].peBlue * 65535 / 255;
143 color.flags = DoRed | DoGreen | DoBlue;
145 if (i < NB_RESERVED_COLORS/2)
147 /* Bottom half of the colormap */
148 pixel = i;
149 if (pixel >= size/2) continue;
151 else
153 /* Top half of the colormap */
154 pixel = size - NB_RESERVED_COLORS + i;
155 if (pixel < size/2) continue;
157 if (COLOR_WinColormap != DefaultColormapOfScreen(screen))
159 color.pixel = pixel;
160 XStoreColor( display, COLOR_WinColormap, &color );
162 else
164 if (!XAllocColor( display, COLOR_WinColormap, &color ))
166 fprintf(stderr, "Warning: Not enough free colors. Try using the -privatemap option.\n" );
167 color.pixel = color.red = color.green = color.blue = 0;
169 else if (COLOR_PaletteToPixel)
171 COLOR_PaletteToPixel[pixel] = color.pixel;
172 COLOR_PixelToPalette[color.pixel] = pixel;
175 if (colorTranslation) colorTranslation[i] = color.pixel;
176 if (revTranslation) revTranslation[color.pixel] = i;
177 /* Set EGA mapping if color in the first or last eight */
178 if (i < 8)
179 COLOR_mapEGAPixel[i] = color.pixel;
180 else if (i >= NB_RESERVED_COLORS-8)
181 COLOR_mapEGAPixel[i - (NB_RESERVED_COLORS-16)] = color.pixel;
184 palPtr = malloc( sizeof(LOGPALETTE) + (NB_RESERVED_COLORS-1)*sizeof(PALETTEENTRY) );
185 if (!palPtr) return FALSE;
186 palPtr->palVersion = 0x300;
187 palPtr->palNumEntries = NB_RESERVED_COLORS;
188 memcpy( palPtr->palPalEntry, COLOR_sysPaletteEntries,
189 sizeof(COLOR_sysPaletteEntries) );
190 hpalette = CreatePalette( palPtr );
191 free( palPtr );
192 return hpalette;
195 void
196 COLOR_Computeshifts(unsigned long maskbits, int *shift, int *max)
198 int i;
200 if(maskbits==0) {
201 *shift=0;
202 *max=0;
203 return;
206 for(i=0;!(maskbits&1);i++)
207 maskbits >>= 1;
209 *shift = i;
210 *max = maskbits;
213 /***********************************************************************
214 * COLOR_Init
216 * Initialize color map and system palette.
218 HPALETTE16 COLOR_Init(void)
220 Visual * visual = DefaultVisual( display, DefaultScreen(display) );
222 switch(visual->class)
224 case GrayScale:
225 case PseudoColor:
226 case DirectColor:
227 COLOR_FixedMap = 0;
228 if (Options.usePrivateMap)
230 COLOR_WinColormap = XCreateColormap( display, rootWindow,
231 visual, AllocAll );
232 if (COLOR_WinColormap)
234 COLOR_BuildMap( COLOR_WinColormap, screenDepth,
235 visual->map_entries );
236 if (rootWindow != DefaultRootWindow(display))
238 XSetWindowAttributes win_attr;
239 win_attr.colormap = COLOR_WinColormap;
240 XChangeWindowAttributes( display, rootWindow,
241 CWColormap, &win_attr );
243 break;
246 COLOR_WinColormap = DefaultColormapOfScreen( screen );
247 break;
248 case StaticGray:
249 COLOR_WinColormap = DefaultColormapOfScreen( screen );
250 COLOR_FixedMap = 1;
251 COLOR_Graymax = (1<<screenDepth)-1;
252 break;
253 case StaticColor:
254 case TrueColor:
255 COLOR_WinColormap = DefaultColormapOfScreen( screen );
256 COLOR_FixedMap = 1;
257 COLOR_Computeshifts(visual->red_mask, &COLOR_Redshift, &COLOR_Redmax);
258 COLOR_Computeshifts(visual->green_mask, &COLOR_Greenshift, &COLOR_Greenmax);
259 COLOR_Computeshifts(visual->blue_mask, &COLOR_Blueshift, &COLOR_Bluemax);
260 break;
262 return COLOR_InitPalette();
266 /***********************************************************************
267 * COLOR_IsSolid
269 * Check whether 'color' can be represented with a solid color.
271 BOOL COLOR_IsSolid( COLORREF color )
273 int i;
274 const PALETTEENTRY *pEntry = COLOR_sysPaletteEntries;
276 if (color & 0xff000000) return TRUE;
277 if (!color || (color == 0xffffff)) return TRUE;
278 for (i = NB_RESERVED_COLORS; i > 0; i--, pEntry++)
280 if ((GetRValue(color) == pEntry->peRed) &&
281 (GetGValue(color) == pEntry->peGreen) &&
282 (GetBValue(color) == pEntry->peBlue)) return TRUE;
284 return FALSE;
288 /***********************************************************************
289 * COLOR_ToPhysical
291 * Return the physical color closest to 'color'.
293 * ESW: This still needs a lot of work; in particular, what happens when
294 * we have really large (> 8 bit) DirectColor boards?
295 * But it should work better in 16 and 24 bit modes now.
296 * (At least it pays attention to the X server's description
297 * in TrueColor mode, instead of blindly passing through the
298 * color spec and swapping red to blue or losing blue and part of the
299 * green entirely, depending on what mode one is in!)
302 int COLOR_ToPhysical( DC *dc, COLORREF color )
304 WORD index = 0;
305 WORD *mapping;
306 unsigned char spec_type;
308 spec_type = color >> 24;
309 if (spec_type == 0xff)
311 spec_type = 0; /* 'write' seems to need that for 'Page 1' text */
312 color &= 0xffffff;
314 if (spec_type > 2)
315 fprintf(stderr, "COLOR_ToPhysical : color >> 24 not in {-1,0,1,2} : %08lx\n",
316 color);
317 if (dc && (dc->w.bitsPerPixel == 1) && (spec_type == 0))
319 /* monochrome */
320 if (((color >> 16) & 0xff) +
321 ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2)
322 return 1; /* white */
323 else return 0; /* black */
326 if (COLOR_FixedMap)
328 /* there is no colormap possible; we are going to have to compute
329 the pixel value from the visual information stored earlier */
331 unsigned long red, green, blue;
332 unsigned idx;
333 PALETTEOBJ * palPtr;
335 switch(spec_type)
337 case 0: /* RGB */
338 case 2: /* PALETTERGB -- needs some work, but why bother; we've got a REALLY LARGE number of colors...? */
339 default:
340 red = GetRValue(color);
341 green = GetGValue(color);
342 blue = GetBValue(color);
343 break;
345 case 1: /* PALETTEIDX -- hmm, get the real color from the stock palette */
346 palPtr = (PALETTEOBJ *) GDI_GetObjPtr( STOCK_DEFAULT_PALETTE, PALETTE_MAGIC);
347 idx = color & 0xffff;
348 if (idx >= palPtr->logpalette.palNumEntries)
350 fprintf(stderr, "COLOR_ToPhysical(%lx) : idx %d is out of bounds, assuming black\n", color, idx);
351 /* out of bounds */
352 red = green = blue = 0;
354 else
356 red = palPtr->logpalette.palPalEntry[idx].peRed;
357 green = palPtr->logpalette.palPalEntry[idx].peGreen;
358 blue = palPtr->logpalette.palPalEntry[idx].peBlue;
362 if (COLOR_Graymax)
364 /* grayscale only; return scaled value */
365 return ( (red * 30 + green * 69 + blue * 11) * COLOR_Graymax) / 25500;
367 else
369 /* scale each individually and construct the TrueColor pixel value */
370 if (COLOR_Redmax != 255) red = (red * COLOR_Redmax) / 255;
371 if (COLOR_Greenmax != 255) green = (green * COLOR_Greenmax) / 255;
372 if (COLOR_Bluemax != 255) blue = (blue * COLOR_Bluemax) / 255;
374 return (red << COLOR_Redshift) | (green << COLOR_Greenshift) | (blue << COLOR_Blueshift);
377 else switch(spec_type)
379 default:
380 case 0: /* RGB */
381 index = GetNearestPaletteIndex( STOCK_DEFAULT_PALETTE, color );
382 break;
383 case 1: /* PALETTEINDEX */
384 index = color & 0xffff;
385 break;
386 case 2: /* PALETTERGB */
387 if (dc) index = GetNearestPaletteIndex( dc->w.hPalette, color );
388 else index = 0;
389 break;
391 if (dc&&dc->u.x.pal.mappingSize)
393 if (index >= dc->u.x.pal.mappingSize)
395 fprintf(stderr, "COLOR_ToPhysical(%lx) : idx %d is >= dc->u.x.pal.mappingSize, assuming pixel 0\n", color, index);
396 return 0;
398 mapping = (WORD *) GDI_HEAP_LIN_ADDR( dc->u.x.pal.hMapping );
400 else
402 if (index >= NB_RESERVED_COLORS)
404 fprintf(stderr, "COLOR_ToPhysical(%lx) : idx %d is >= NB_RESERVED_COLORS, assuming pixel 0\n", color, index);
405 return 0;
407 mapping = (WORD *) GDI_HEAP_LIN_ADDR( hSysColorTranslation );
409 if (mapping) return mapping[index];
410 else return index; /* Identity mapping */
414 /***********************************************************************
415 * COLOR_SetMapping
417 * Set the color-mapping table in a DC.
419 void COLOR_SetMapping( DC *dc, HANDLE map, HANDLE revMap, WORD size )
421 WORD *pmap, *pnewmap;
422 WORD i;
424 if (dc->u.x.pal.hMapping && (dc->u.x.pal.hMapping != hSysColorTranslation))
425 GDI_HEAP_FREE( dc->u.x.pal.hMapping );
426 if (dc->u.x.pal.hRevMapping &&
427 (dc->u.x.pal.hRevMapping != hRevSysColorTranslation))
428 GDI_HEAP_FREE( dc->u.x.pal.hRevMapping );
429 if (map && (map != hSysColorTranslation))
431 /* Copy mapping table */
432 dc->u.x.pal.hMapping = GDI_HEAP_ALLOC( sizeof(WORD) * size );
433 pmap = (WORD *) GDI_HEAP_LIN_ADDR( map );
434 pnewmap = (WORD *) GDI_HEAP_LIN_ADDR( dc->u.x.pal.hMapping );
435 memcpy( pnewmap, pmap, sizeof(WORD)*size );
436 /* Build reverse table */
437 dc->u.x.pal.hRevMapping = GDI_HEAP_ALLOC(sizeof(WORD)*COLOR_ColormapSize);
438 pmap = (WORD *) GDI_HEAP_LIN_ADDR( dc->u.x.pal.hRevMapping );
439 for (i = 0; i < size; i++) pmap[pnewmap[i]] = i;
441 else
443 dc->u.x.pal.hMapping = map;
444 dc->u.x.pal.hRevMapping = map ? hRevSysColorTranslation : 0;
446 dc->u.x.pal.mappingSize = size;
450 /***********************************************************************
451 * RealizeDefaultPalette (GDI.365)
453 WORD RealizeDefaultPalette( HDC hdc )
455 DC *dc;
456 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
457 dc->w.hPalette = STOCK_DEFAULT_PALETTE;
458 COLOR_SetMapping( dc, hSysColorTranslation,
459 hRevSysColorTranslation, NB_RESERVED_COLORS );
460 return NB_RESERVED_COLORS;