Release 940405
[wine] / objects / color.c
1 /*
2  * Color functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  */
6
7 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
8
9 #include <stdlib.h>
10 #include <X11/Xlib.h>
11
12 #include "windows.h"
13 #include "options.h"
14 #include "gdi.h"
15
16
17 Colormap COLOR_WinColormap = 0;
18
19   /* System palette static colors */
20
21 #define NB_RESERVED_COLORS  20
22
23   /* The first and last eight colors are EGA colors */
24 static PALETTEENTRY COLOR_sysPaletteEntries[NB_RESERVED_COLORS] =
25 {
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 },
37
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 }
48 };
49
50 static HANDLE hSysColorTranslation = 0;
51
52    /* Map an EGA index (0..15) to a pixel value. Used for dithering. */
53 int COLOR_mapEGAPixel[16];
54
55
56 /***********************************************************************
57  *           COLOR_BuildMap
58  *
59  * Fill the private colormap.
60  */
61 static BOOL COLOR_BuildMap( Colormap map, int depth, int size )
62 {
63     XColor color;
64     int r, g, b, red_incr, green_incr, blue_incr;
65     int index = 0;
66
67       /* Fill the whole map with a range of colors */
68
69     blue_incr  = 0x10000 >> (depth / 3);
70     red_incr   = 0x10000 >> ((depth + 1) / 3);
71     green_incr = 0x10000 >> ((depth + 2) / 3);
72
73     for (r = red_incr - 1; r < 0x10000; r += red_incr)
74         for (g = green_incr - 1; g < 0x10000; g += green_incr)
75             for (b = blue_incr - 1; b < 0x10000; b += blue_incr)
76             {
77                 if (index >= size) break;
78                 color.pixel = index++;
79                 color.red   = r;
80                 color.green = g;
81                 color.blue  = b;
82                 XStoreColor( display, map, &color );
83             }
84
85     return TRUE;
86 }
87
88
89 /***********************************************************************
90  *           COLOR_InitPalette
91  *
92  * Create the system palette.
93  */
94 static HPALETTE COLOR_InitPalette()
95 {
96     int i, size;
97     XColor color;
98     HPALETTE hpalette;
99     LOGPALETTE * palPtr;
100     WORD *colorTranslation;
101
102     if (!(hSysColorTranslation = GDI_HEAP_ALLOC( GMEM_MOVEABLE,
103                                    sizeof(WORD)*NB_RESERVED_COLORS ))) return FALSE;
104     colorTranslation = (WORD *) GDI_HEAP_ADDR( hSysColorTranslation );
105     size = DefaultVisual( display, DefaultScreen(display) )->map_entries;
106     for (i = 0; i < NB_RESERVED_COLORS; i++)
107     {
108         color.red   = COLOR_sysPaletteEntries[i].peRed * 65535 / 255;
109         color.green = COLOR_sysPaletteEntries[i].peGreen * 65535 / 255;
110         color.blue  = COLOR_sysPaletteEntries[i].peBlue * 65535 / 255;
111         color.flags = DoRed | DoGreen | DoBlue;
112
113         if (COLOR_WinColormap != DefaultColormapOfScreen(screen))
114         {
115             if (i < NB_RESERVED_COLORS/2)
116             {
117                   /* Bottom half of the colormap */
118                 color.pixel = i;
119                 if (color.pixel >= size/2) continue;
120             }
121             else
122             {
123                   /* Top half of the colormap */
124                 color.pixel = size - NB_RESERVED_COLORS + i;
125                 if (color.pixel < size/2) continue;
126             }
127             XStoreColor( display, COLOR_WinColormap, &color );
128         }
129         else if (!XAllocColor( display, COLOR_WinColormap, &color ))
130         {
131             printf( "Warning: Not enough free colors. Try using the -privatemap option.\n" );
132             color.pixel = color.red = color.green = color.blue = 0;
133         }
134         colorTranslation[i] = color.pixel;
135 #if 0
136           /* Put the allocated colors back in the list */
137         COLOR_sysPaletteEntries[i].peRed   = color.red >> 8;
138         COLOR_sysPaletteEntries[i].peGreen = color.green >> 8;
139         COLOR_sysPaletteEntries[i].peBlue  = color.blue >> 8;
140 #endif
141           /* Set EGA mapping if color in the first or last eight */
142         if (i < 8)
143             COLOR_mapEGAPixel[i] = color.pixel;
144         else if (i >= NB_RESERVED_COLORS-8)
145             COLOR_mapEGAPixel[i - (NB_RESERVED_COLORS-16)] = color.pixel;
146     }
147
148     palPtr = malloc( sizeof(LOGPALETTE) + (NB_RESERVED_COLORS-1)*sizeof(PALETTEENTRY) );
149     if (!palPtr) return FALSE;
150     palPtr->palVersion = 0x300;
151     palPtr->palNumEntries = NB_RESERVED_COLORS;
152     memcpy( palPtr->palPalEntry, COLOR_sysPaletteEntries,
153             sizeof(COLOR_sysPaletteEntries) );
154     hpalette = CreatePalette( palPtr );
155     free( palPtr );
156     return hpalette;
157 }
158
159
160 /***********************************************************************
161  *           COLOR_Init
162  *
163  * Initialize color map and system palette.
164  */
165 HPALETTE COLOR_Init()
166 {
167     Visual * visual = DefaultVisual( display, DefaultScreen(display) );
168     
169     switch(visual->class)
170     {
171     case GrayScale:
172     case PseudoColor:
173     case DirectColor:
174         if (Options.usePrivateMap)
175         {
176             COLOR_WinColormap = XCreateColormap( display, rootWindow,
177                                                  visual, AllocAll );
178             if (COLOR_WinColormap)
179             {
180                 COLOR_BuildMap( COLOR_WinColormap, screenDepth,
181                                 visual->map_entries );
182                 if (rootWindow != DefaultRootWindow(display))
183                 {
184                     XSetWindowAttributes win_attr;
185                     win_attr.colormap = COLOR_WinColormap;
186                     XChangeWindowAttributes( display, rootWindow,
187                                              CWColormap, &win_attr );
188                 }
189                 break;
190             }
191         }
192         /* Fall through */
193     case StaticGray:
194     case StaticColor:
195     case TrueColor:
196         COLOR_WinColormap = DefaultColormapOfScreen( screen );
197         break;  
198     }
199     return COLOR_InitPalette();
200 }
201
202
203 /***********************************************************************
204  *           COLOR_IsSolid
205  *
206  * Check whether 'color' can be represented with a solid color.
207  */
208 BOOL COLOR_IsSolid( COLORREF color )
209 {
210     int i;
211     PALETTEENTRY *pEntry = COLOR_sysPaletteEntries;
212
213     if (color & 0xff000000) return TRUE;
214     if (!color || (color == 0xffffff)) return TRUE;
215     for (i = NB_RESERVED_COLORS; i > 0; i--, pEntry++)
216     {
217         if ((GetRValue(color) == pEntry->peRed) &&
218             (GetGValue(color) == pEntry->peGreen) &&
219             (GetBValue(color) == pEntry->peBlue)) return TRUE;
220     }
221     return FALSE;
222 }
223
224
225 /***********************************************************************
226  *           COLOR_ToPhysical
227  *
228  * Return the physical color closest to 'color'.
229  */
230 WORD COLOR_ToPhysical( DC *dc, COLORREF color )
231 {
232     WORD index = 0;
233     WORD *mapping;
234
235     if (!dc->u.x.pal.hMapping) return 0;
236     switch(color & 0xff000000)
237     {
238     case 0:  /* RGB */
239         index = GetNearestPaletteIndex( STOCK_DEFAULT_PALETTE, color );
240         break;
241     case 1:  /* PALETTEINDEX */
242         index = color & 0xffff;
243         break;
244     case 2:  /* PALETTERGB */
245         index = GetNearestPaletteIndex( dc->w.hPalette, color );
246         break;
247     }
248     if (index >= dc->u.x.pal.mappingSize) return 0;
249     mapping = (WORD *) GDI_HEAP_ADDR( dc->u.x.pal.hMapping );
250     return mapping[index];
251 }
252
253
254 /***********************************************************************
255  *           COLOR_SetMapping
256  *
257  * Set the color-mapping table in a DC.
258  */
259 void COLOR_SetMapping( DC *dc, HANDLE map, WORD size )
260 {
261     WORD *pmap, *pnewmap;
262
263     if (dc->u.x.pal.hMapping && (dc->u.x.pal.hMapping != hSysColorTranslation))
264         GDI_HEAP_FREE( dc->u.x.pal.hMapping );
265     if (map && (map != hSysColorTranslation))
266     {
267           /* Copy mapping table */
268         dc->u.x.pal.hMapping = GDI_HEAP_ALLOC(GMEM_MOVEABLE,sizeof(WORD)*size);
269         pmap = (WORD *) GDI_HEAP_ADDR( map );
270         pnewmap = (WORD *) GDI_HEAP_ADDR( dc->u.x.pal.hMapping );
271         memcpy( pnewmap, pmap, sizeof(WORD)*size );
272     }
273     else dc->u.x.pal.hMapping = map;
274     dc->u.x.pal.mappingSize = size;
275 }
276
277
278 /***********************************************************************
279  *           GetNearestColor    (GDI.154)
280  */
281 COLORREF GetNearestColor( HDC hdc, COLORREF color )
282 {
283     WORD index;
284     DC *dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
285     if (!dc) return 0;
286     index = COLOR_ToPhysical( dc, color & 0xffffff );
287     return PALETTEINDEX( index );
288 }
289
290
291 /***********************************************************************
292  *           RealizeDefaultPalette    (GDI.365)
293  */
294 WORD RealizeDefaultPalette( HDC hdc )
295 {
296     DC *dc;
297     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
298     dc->w.hPalette = STOCK_DEFAULT_PALETTE;
299     COLOR_SetMapping( dc, hSysColorTranslation, NB_RESERVED_COLORS );
300     return NB_RESERVED_COLORS;
301 }