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