In CreateDIBSection function, if hdc is NULL it now uses the desktop DC
[wine] / objects / color.c
1 /*
2  * Color functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  * Copyright 1996 Alex Korobka
6  */
7
8 #include "color.h"
9 #include "debugtools.h"
10 #include "palette.h"
11 #include "windef.h"
12
13 DEFAULT_DEBUG_CHANNEL(palette)
14
15
16 /***********************************************************************
17  * System color space. 
18  *
19  * First 10 and last 10 colors in COLOR_sysPalette are
20  * "guarded". RealizePalette changes only the rest of colorcells. For
21  * currently inactive window it changes only DC palette mappings.
22  */
23
24 PALETTEENTRY *COLOR_sysPal = NULL; /* current system palette */
25
26 int COLOR_gapStart = 256;
27 int COLOR_gapEnd = -1;
28 int COLOR_gapFilled = 0;
29 int COLOR_max = 256;
30
31 const PALETTEENTRY COLOR_sysPalTemplate[NB_RESERVED_COLORS] = 
32 {
33     /* first 10 entries in the system palette */
34     /* red  green blue  flags */
35     { 0x00, 0x00, 0x00, PC_SYS_USED },
36     { 0x80, 0x00, 0x00, PC_SYS_USED },
37     { 0x00, 0x80, 0x00, PC_SYS_USED },
38     { 0x80, 0x80, 0x00, PC_SYS_USED },
39     { 0x00, 0x00, 0x80, PC_SYS_USED },
40     { 0x80, 0x00, 0x80, PC_SYS_USED },
41     { 0x00, 0x80, 0x80, PC_SYS_USED },
42     { 0xc0, 0xc0, 0xc0, PC_SYS_USED },
43     { 0xc0, 0xdc, 0xc0, PC_SYS_USED },
44     { 0xa6, 0xca, 0xf0, PC_SYS_USED },
45
46     /* ... c_min/2 dynamic colorcells */
47
48     /* ... gap (for sparse palettes) */
49
50     /* ... c_min/2 dynamic colorcells */
51
52     { 0xff, 0xfb, 0xf0, PC_SYS_USED },
53     { 0xa0, 0xa0, 0xa4, PC_SYS_USED },
54     { 0x80, 0x80, 0x80, PC_SYS_USED },
55     { 0xff, 0x00, 0x00, PC_SYS_USED },
56     { 0x00, 0xff, 0x00, PC_SYS_USED },
57     { 0xff, 0xff, 0x00, PC_SYS_USED },
58     { 0x00, 0x00, 0xff, PC_SYS_USED },
59     { 0xff, 0x00, 0xff, PC_SYS_USED },
60     { 0x00, 0xff, 0xff, PC_SYS_USED },
61     { 0xff, 0xff, 0xff, PC_SYS_USED }     /* last 10 */
62 };
63
64 /***********************************************************************
65  *           COLOR_GetSystemPaletteTemplate
66  */
67 const PALETTEENTRY* COLOR_GetSystemPaletteTemplate(void)
68 {
69     return COLOR_sysPalTemplate;
70 }
71
72 /***********************************************************************
73  *           COLOR_GetSystemPaletteEntry
74  */
75
76 COLORREF COLOR_GetSystemPaletteEntry(UINT i)
77 {
78     return *(COLORREF*)(COLOR_sysPal + i) & 0x00ffffff;
79 }
80
81 /***********************************************************************
82  *           COLOR_IsSolid
83  *
84  * Check whether 'color' can be represented with a solid color.
85  */
86 BOOL COLOR_IsSolid( COLORREF color )
87 {
88     int i;
89     const PALETTEENTRY *pEntry = COLOR_sysPal;
90
91     if (color & 0xff000000) return TRUE;                /* indexed color */
92
93     if (!color || (color == 0xffffff)) return TRUE;     /* black or white */
94
95     for (i = 0; i < 256 ; i++, pEntry++)
96     {
97       if( i < COLOR_gapStart || i > COLOR_gapEnd )
98         if ((GetRValue(color) == pEntry->peRed) &&
99             (GetGValue(color) == pEntry->peGreen) &&
100             (GetBValue(color) == pEntry->peBlue)) return TRUE;
101     }
102     return FALSE;
103 }
104
105 /***********************************************************************
106  *           COLOR_PaletteLookupPixel
107  */
108 int COLOR_PaletteLookupPixel( PALETTEENTRY* palPalEntry, int size,
109                               int* mapping, COLORREF col, BOOL skipReserved )
110 {
111     int i, best = 0, diff = 0x7fffffff;
112     int r,g,b;
113
114     for( i = 0; i < size && diff ; i++ )
115     {
116         if( !(palPalEntry[i].peFlags & PC_SYS_USED) ||
117             (skipReserved && palPalEntry[i].peFlags  & PC_SYS_RESERVED) )
118             continue;
119
120         r = palPalEntry[i].peRed - GetRValue(col);
121         g = palPalEntry[i].peGreen - GetGValue(col);
122         b = palPalEntry[i].peBlue - GetBValue(col);
123
124         r = r*r + g*g + b*b;
125
126         if( r < diff ) { best = i; diff = r; }
127     }
128     return (mapping) ? mapping[best] : best;
129 }
130
131 /***********************************************************************
132  *           COLOR_PaletteLookupExactIndex
133  */
134 int COLOR_PaletteLookupExactIndex( PALETTEENTRY* palPalEntry, int size,
135                                    COLORREF col )
136 {
137     int i;
138     BYTE r = GetRValue(col), g = GetGValue(col), b = GetBValue(col);
139     for( i = 0; i < size; i++ )
140     {
141         if( palPalEntry[i].peFlags & PC_SYS_USED )      /* skips gap */
142             if( palPalEntry[i].peRed == r &&
143                 palPalEntry[i].peGreen == g &&
144                 palPalEntry[i].peBlue == b )
145                 return i;
146     }
147     return -1;
148 }
149
150 /***********************************************************************
151  *           COLOR_LookupNearestColor
152  */
153 COLORREF COLOR_LookupNearestColor( PALETTEENTRY* palPalEntry, int size, COLORREF color )
154 {
155   unsigned char         spec_type = color >> 24;
156   int                   i;
157
158   /* we need logical palette for PALETTERGB and PALETTEINDEX colorrefs */
159
160   if( spec_type == 2 ) /* PALETTERGB */
161     color = *(COLORREF*)
162              (palPalEntry + COLOR_PaletteLookupPixel(palPalEntry,size,NULL,color,FALSE));
163
164   else if( spec_type == 1 ) /* PALETTEINDEX */
165   {
166     if( (i = color & 0x0000ffff) >= size ) 
167       {
168         WARN("RGB(%lx) : idx %d is out of bounds, assuming NULL\n", color, i);
169         color = *(COLORREF*)palPalEntry;
170       }
171     else color = *(COLORREF*)(palPalEntry + i);
172   }
173
174   color &= 0x00ffffff;
175   return (0x00ffffff & *(COLORREF*)
176          (COLOR_sysPal + COLOR_PaletteLookupPixel(COLOR_sysPal, 256, NULL, color, FALSE)));
177 }