Release 941227
[wine/multimedia.git] / objects / color.c
blob35238808d6cc2f629194a2c1155997770c53bdbc
1 /*
2 * Color functions
4 * Copyright 1993 Alexandre Julliard
6 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
7 */
8 #include <stdlib.h>
9 #include <X11/Xlib.h>
10 #include <stdio.h>
11 #include "windows.h"
12 #include "options.h"
13 #include "gdi.h"
14 #include "color.h"
17 Colormap COLOR_WinColormap = 0;
19 /* System palette static colors */
21 #define NB_RESERVED_COLORS 20
23 /* The first and last eight colors are EGA colors */
24 static PALETTEENTRY COLOR_sysPaletteEntries[NB_RESERVED_COLORS] =
26 /* red green blue flags */
27 { 0x00, 0x00, 0x00, 0 },
28 { 0x80, 0x00, 0x00, 0 },
29 { 0x00, 0x80, 0x00, 0 },
30 { 0x80, 0x80, 0x00, 0 },
31 { 0x00, 0x00, 0x80, 0 },
32 { 0x80, 0x00, 0x80, 0 },
33 { 0x00, 0x80, 0x80, 0 },
34 { 0xc0, 0xc0, 0xc0, 0 },
35 { 0xc0, 0xdc, 0xc0, 0 },
36 { 0xa6, 0xca, 0xf0, 0 },
38 { 0xff, 0xfb, 0xf0, 0 },
39 { 0xa0, 0xa0, 0xa4, 0 },
40 { 0x80, 0x80, 0x80, 0 },
41 { 0xff, 0x00, 0x00, 0 },
42 { 0x00, 0xff, 0x00, 0 },
43 { 0xff, 0xff, 0x00, 0 },
44 { 0x00, 0x00, 0xff, 0 },
45 { 0xff, 0x00, 0xff, 0 },
46 { 0x00, 0xff, 0xff, 0 },
47 { 0xff, 0xff, 0xff, 0 }
50 static HANDLE hSysColorTranslation = 0;
51 static HANDLE hRevSysColorTranslation = 0;
53 /* Map an EGA index (0..15) to a pixel value. Used for dithering. */
54 int COLOR_mapEGAPixel[16];
56 int* COLOR_PaletteToPixel = NULL;
57 int* COLOR_PixelToPalette = NULL;
58 int COLOR_ColormapSize = 0;
60 /***********************************************************************
61 * COLOR_BuildMap
63 * Fill the private colormap.
65 static BOOL COLOR_BuildMap( Colormap map, int depth, int size )
67 XColor color;
68 int r, g, b, red_incr, green_incr, blue_incr;
69 int index = 0;
71 /* Fill the whole map with a range of colors */
73 blue_incr = 0x10000 >> (depth / 3);
74 red_incr = 0x10000 >> ((depth + 1) / 3);
75 green_incr = 0x10000 >> ((depth + 2) / 3);
77 for (r = red_incr - 1; r < 0x10000; r += red_incr)
78 for (g = green_incr - 1; g < 0x10000; g += green_incr)
79 for (b = blue_incr - 1; b < 0x10000; b += blue_incr)
81 if (index >= size) break;
82 color.pixel = index++;
83 color.red = r;
84 color.green = g;
85 color.blue = b;
86 XStoreColor( display, map, &color );
89 return TRUE;
93 /***********************************************************************
94 * COLOR_InitPalette
96 * Create the system palette.
98 static HPALETTE COLOR_InitPalette(void)
100 int i, size, pixel;
101 XColor color;
102 HPALETTE hpalette;
103 LOGPALETTE * palPtr;
104 WORD *colorTranslation, *revTranslation;
106 size = DefaultVisual( display, DefaultScreen(display) )->map_entries;
107 COLOR_ColormapSize = size;
108 if (!(hSysColorTranslation = GDI_HEAP_ALLOC( GMEM_MOVEABLE,
109 sizeof(WORD)*NB_RESERVED_COLORS )))
110 return FALSE;
111 if (!(hRevSysColorTranslation = GDI_HEAP_ALLOC( GMEM_MOVEABLE,
112 sizeof(WORD)*size )))
113 return FALSE;
114 colorTranslation = (WORD *) GDI_HEAP_ADDR( hSysColorTranslation );
115 revTranslation = (WORD *) GDI_HEAP_ADDR( hRevSysColorTranslation );
117 if (COLOR_WinColormap == DefaultColormapOfScreen(screen))
119 COLOR_PaletteToPixel = (int *)malloc( sizeof(int) * size );
120 COLOR_PixelToPalette = (int *)malloc( sizeof(int) * size );
123 for (i = 0; i < NB_RESERVED_COLORS; i++)
125 color.red = COLOR_sysPaletteEntries[i].peRed * 65535 / 255;
126 color.green = COLOR_sysPaletteEntries[i].peGreen * 65535 / 255;
127 color.blue = COLOR_sysPaletteEntries[i].peBlue * 65535 / 255;
128 color.flags = DoRed | DoGreen | DoBlue;
130 if (i < NB_RESERVED_COLORS/2)
132 /* Bottom half of the colormap */
133 pixel = i;
134 if (pixel >= size/2) continue;
136 else
138 /* Top half of the colormap */
139 pixel = size - NB_RESERVED_COLORS + i;
140 if (pixel < size/2) continue;
142 if (COLOR_WinColormap != DefaultColormapOfScreen(screen))
144 color.pixel = pixel;
145 XStoreColor( display, COLOR_WinColormap, &color );
147 else
149 if (!XAllocColor( display, COLOR_WinColormap, &color ))
151 fprintf(stderr, "Warning: Not enough free colors. Try using the -privatemap option.\n" );
152 color.pixel = color.red = color.green = color.blue = 0;
154 else
156 COLOR_PaletteToPixel[pixel] = color.pixel;
157 COLOR_PixelToPalette[color.pixel] = pixel;
160 colorTranslation[i] = color.pixel;
161 revTranslation[color.pixel] = i;
162 /* Set EGA mapping if color in the first or last eight */
163 if (i < 8)
164 COLOR_mapEGAPixel[i] = color.pixel;
165 else if (i >= NB_RESERVED_COLORS-8)
166 COLOR_mapEGAPixel[i - (NB_RESERVED_COLORS-16)] = color.pixel;
169 palPtr = malloc( sizeof(LOGPALETTE) + (NB_RESERVED_COLORS-1)*sizeof(PALETTEENTRY) );
170 if (!palPtr) return FALSE;
171 palPtr->palVersion = 0x300;
172 palPtr->palNumEntries = NB_RESERVED_COLORS;
173 memcpy( palPtr->palPalEntry, COLOR_sysPaletteEntries,
174 sizeof(COLOR_sysPaletteEntries) );
175 hpalette = CreatePalette( palPtr );
176 free( palPtr );
177 return hpalette;
181 /***********************************************************************
182 * COLOR_Init
184 * Initialize color map and system palette.
186 HPALETTE COLOR_Init(void)
188 Visual * visual = DefaultVisual( display, DefaultScreen(display) );
190 switch(visual->class)
192 case GrayScale:
193 case PseudoColor:
194 case DirectColor:
195 if (Options.usePrivateMap)
197 COLOR_WinColormap = XCreateColormap( display, rootWindow,
198 visual, AllocAll );
199 if (COLOR_WinColormap)
201 COLOR_BuildMap( COLOR_WinColormap, screenDepth,
202 visual->map_entries );
203 if (rootWindow != DefaultRootWindow(display))
205 XSetWindowAttributes win_attr;
206 win_attr.colormap = COLOR_WinColormap;
207 XChangeWindowAttributes( display, rootWindow,
208 CWColormap, &win_attr );
210 break;
213 /* Fall through */
214 case StaticGray:
215 case StaticColor:
216 case TrueColor:
217 COLOR_WinColormap = DefaultColormapOfScreen( screen );
218 break;
220 return COLOR_InitPalette();
224 /***********************************************************************
225 * COLOR_IsSolid
227 * Check whether 'color' can be represented with a solid color.
229 BOOL COLOR_IsSolid( COLORREF color )
231 int i;
232 PALETTEENTRY *pEntry = COLOR_sysPaletteEntries;
234 if (color & 0xff000000) return TRUE;
235 if (!color || (color == 0xffffff)) return TRUE;
236 for (i = NB_RESERVED_COLORS; i > 0; i--, pEntry++)
238 if ((GetRValue(color) == pEntry->peRed) &&
239 (GetGValue(color) == pEntry->peGreen) &&
240 (GetBValue(color) == pEntry->peBlue)) return TRUE;
242 return FALSE;
246 /***********************************************************************
247 * COLOR_ToPhysical
249 * Return the physical color closest to 'color'.
251 int COLOR_ToPhysical( DC *dc, COLORREF color )
253 WORD index = 0;
254 WORD *mapping;
256 if (screenDepth > 8) return color;
257 switch(color >> 24)
259 case 0: /* RGB */
260 index = GetNearestPaletteIndex( STOCK_DEFAULT_PALETTE, color );
261 break;
262 case 1: /* PALETTEINDEX */
263 index = color & 0xffff;
264 break;
265 case 2: /* PALETTERGB */
266 if (dc) index = GetNearestPaletteIndex( dc->w.hPalette, color );
267 else index = 0;
268 break;
270 if (dc)
272 if (index >= dc->u.x.pal.mappingSize) return 0;
273 mapping = (WORD *) GDI_HEAP_ADDR( dc->u.x.pal.hMapping );
275 else
277 if (index >= NB_RESERVED_COLORS) return 0;
278 mapping = (WORD *) GDI_HEAP_ADDR( hSysColorTranslation );
280 if (mapping) return mapping[index];
281 else return index; /* Identity mapping */
285 /***********************************************************************
286 * COLOR_SetMapping
288 * Set the color-mapping table in a DC.
290 void COLOR_SetMapping( DC *dc, HANDLE map, HANDLE revMap, WORD size )
292 WORD *pmap, *pnewmap;
293 WORD i;
295 if (dc->u.x.pal.hMapping && (dc->u.x.pal.hMapping != hSysColorTranslation))
296 GDI_HEAP_FREE( dc->u.x.pal.hMapping );
297 if (dc->u.x.pal.hRevMapping &&
298 (dc->u.x.pal.hRevMapping != hRevSysColorTranslation))
299 GDI_HEAP_FREE( dc->u.x.pal.hRevMapping );
300 if (map && (map != hSysColorTranslation))
302 /* Copy mapping table */
303 dc->u.x.pal.hMapping = GDI_HEAP_ALLOC(GMEM_MOVEABLE,sizeof(WORD)*size);
304 pmap = (WORD *) GDI_HEAP_ADDR( map );
305 pnewmap = (WORD *) GDI_HEAP_ADDR( dc->u.x.pal.hMapping );
306 memcpy( pnewmap, pmap, sizeof(WORD)*size );
307 /* Build reverse table */
308 dc->u.x.pal.hRevMapping = GDI_HEAP_ALLOC( GMEM_MOVEABLE,
309 sizeof(WORD)*COLOR_ColormapSize );
310 pmap = (WORD *) GDI_HEAP_ADDR( dc->u.x.pal.hRevMapping );
311 for (i = 0; i < size; i++) pmap[pnewmap[i]] = i;
313 else
315 dc->u.x.pal.hMapping = map;
316 dc->u.x.pal.hRevMapping = map ? hRevSysColorTranslation : 0;
318 dc->u.x.pal.mappingSize = size;
322 /***********************************************************************
323 * GetNearestColor (GDI.154)
325 COLORREF GetNearestColor( HDC hdc, COLORREF color )
327 WORD index;
328 DC *dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
329 if (!dc) return 0;
330 if (screenDepth > 8) return color;
331 index = (WORD)(COLOR_ToPhysical( dc, color & 0xffffff ) & 0xffff);
332 return PALETTEINDEX( index );
336 /***********************************************************************
337 * RealizeDefaultPalette (GDI.365)
339 WORD RealizeDefaultPalette( HDC hdc )
341 DC *dc;
342 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
343 dc->w.hPalette = STOCK_DEFAULT_PALETTE;
344 COLOR_SetMapping( dc, hSysColorTranslation,
345 hRevSysColorTranslation, NB_RESERVED_COLORS );
346 return NB_RESERVED_COLORS;