4ae9d9902b4a484929d6f64f6019bbdfd88cfc24
[reactos.git] / reactos / subsys / win32k / objects / palette.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$ */
20
21 #include <w32k.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26 #ifndef NO_MAPPING
27 static int PALETTE_firstFree = 0;
28 static unsigned char PALETTE_freeList[256];
29 #endif
30
31 int PALETTE_PaletteFlags = 0;
32 PALETTEENTRY *COLOR_sysPal = NULL;
33 int COLOR_gapStart;
34 int COLOR_gapEnd;
35 int COLOR_gapFilled;
36 int COLOR_max;
37
38 PPALETTEENTRY FASTCALL ReturnSystemPalette (VOID)
39 {
40 return COLOR_sysPal;
41 }
42
43 BOOL INTERNAL_CALL
44 PALETTE_Cleanup(PVOID ObjectBody)
45 {
46 PPALGDI pPal = (PPALGDI)ObjectBody;
47 if (NULL != pPal->IndexedColors)
48 {
49 ExFreePool(pPal->IndexedColors);
50 }
51
52 return TRUE;
53 }
54
55 HPALETTE FASTCALL
56 PALETTE_AllocPalette(ULONG Mode,
57 ULONG NumColors,
58 ULONG *Colors,
59 ULONG Red,
60 ULONG Green,
61 ULONG Blue)
62 {
63 HPALETTE NewPalette;
64 PPALGDI PalGDI;
65
66 NewPalette = (HPALETTE) GDIOBJ_AllocObj(GDI_OBJECT_TYPE_PALETTE);
67 if (NULL == NewPalette)
68 {
69 return NULL;
70 }
71
72 PalGDI = PALETTE_LockPalette(NewPalette);
73 /* FIXME - PalGDI can be NULL!!! Don't assert here! */
74 ASSERT( PalGDI );
75
76 PalGDI->Self = NewPalette;
77 PalGDI->Mode = Mode;
78
79 if (NULL != Colors)
80 {
81 PalGDI->IndexedColors = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * NumColors, TAG_PALETTE);
82 if (NULL == PalGDI->IndexedColors)
83 {
84 PALETTE_UnlockPalette(PalGDI);
85 PALETTE_FreePalette(NewPalette);
86 return NULL;
87 }
88 RtlCopyMemory(PalGDI->IndexedColors, Colors, sizeof(PALETTEENTRY) * NumColors);
89 }
90
91 if (PAL_INDEXED == Mode)
92 {
93 PalGDI->NumColors = NumColors;
94 }
95 else if (PAL_BITFIELDS == Mode)
96 {
97 PalGDI->RedMask = Red;
98 PalGDI->GreenMask = Green;
99 PalGDI->BlueMask = Blue;
100 }
101
102 PALETTE_UnlockPalette(PalGDI);
103
104 return NewPalette;
105 }
106
107 HPALETTE FASTCALL
108 PALETTE_AllocPaletteIndexedRGB(ULONG NumColors,
109 CONST RGBQUAD *Colors)
110 {
111 HPALETTE NewPalette;
112 PPALGDI PalGDI;
113 unsigned i;
114
115 NewPalette = (HPALETTE) GDIOBJ_AllocObj(GDI_OBJECT_TYPE_PALETTE);
116 if (NULL == NewPalette)
117 {
118 return NULL;
119 }
120
121 PalGDI = PALETTE_LockPalette(NewPalette);
122 /* FIXME - PalGDI can be NULL!!! Don't assert here! */
123 ASSERT( PalGDI );
124
125 PalGDI->Self = NewPalette;
126 PalGDI->Mode = PAL_INDEXED;
127
128 PalGDI->IndexedColors = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * NumColors, TAG_PALETTE);
129 if (NULL == PalGDI->IndexedColors)
130 {
131 PALETTE_UnlockPalette(PalGDI);
132 PALETTE_FreePalette(NewPalette);
133 return NULL;
134 }
135 for (i = 0; i < NumColors; i++)
136 {
137 PalGDI->IndexedColors[i].peRed = Colors[i].rgbRed;
138 PalGDI->IndexedColors[i].peGreen = Colors[i].rgbGreen;
139 PalGDI->IndexedColors[i].peBlue = Colors[i].rgbBlue;
140 PalGDI->IndexedColors[i].peFlags = 0;
141 }
142
143 PalGDI->NumColors = NumColors;
144
145 PALETTE_UnlockPalette(PalGDI);
146
147 return NewPalette;
148 }
149
150 // Create the system palette
151 HPALETTE FASTCALL PALETTE_Init(VOID)
152 {
153 int i;
154 HPALETTE hpalette;
155 PLOGPALETTE palPtr;
156 #ifndef NO_MAPPING
157 PALOBJ *palObj;
158 #endif
159 const PALETTEENTRY* __sysPalTemplate = (const PALETTEENTRY*)COLOR_GetSystemPaletteTemplate();
160
161 // create default palette (20 system colors)
162 palPtr = ExAllocatePoolWithTag(PagedPool, sizeof(LOGPALETTE) + (NB_RESERVED_COLORS * sizeof(PALETTEENTRY)), TAG_PALETTE);
163 if (!palPtr) return FALSE;
164
165 palPtr->palVersion = 0x300;
166 palPtr->palNumEntries = NB_RESERVED_COLORS;
167 for(i=0; i<NB_RESERVED_COLORS; i++)
168 {
169 palPtr->palPalEntry[i].peRed = __sysPalTemplate[i].peRed;
170 palPtr->palPalEntry[i].peGreen = __sysPalTemplate[i].peGreen;
171 palPtr->palPalEntry[i].peBlue = __sysPalTemplate[i].peBlue;
172 palPtr->palPalEntry[i].peFlags = 0;
173 }
174
175 hpalette = NtGdiCreatePalette(palPtr);
176 ExFreePool(palPtr);
177
178 #ifndef NO_MAPPING
179 palObj = (PALOBJ*)PALETTE_LockPalette(hpalette);
180 if (palObj)
181 {
182 if (!(palObj->mapping = ExAllocatePool(PagedPool, sizeof(int) * 20)))
183 {
184 DbgPrint("Win32k: Can not create palette mapping -- out of memory!");
185 return FALSE;
186 }
187 PALETTE_UnlockPalette(palObj);
188 }
189 #endif
190
191 /* palette_size = visual->map_entries; */
192
193 return hpalette;
194 }
195
196 #ifndef NO_MAPPING
197 static void FASTCALL PALETTE_FormatSystemPalette(void)
198 {
199 // Build free list so we'd have an easy way to find
200 // out if there are any available colorcells.
201
202 int i, j = PALETTE_firstFree = NB_RESERVED_COLORS/2;
203
204 COLOR_sysPal[j].peFlags = 0;
205 for(i = (NB_RESERVED_COLORS>>1) + 1 ; i < 256 - (NB_RESERVED_COLORS>>1) ; i++)
206 {
207 if( i < COLOR_gapStart || i > COLOR_gapEnd )
208 {
209 COLOR_sysPal[i].peFlags = 0; // unused tag
210 PALETTE_freeList[j] = i; // next
211 j = i;
212 }
213 }
214 PALETTE_freeList[j] = 0;
215 }
216 #endif
217
218 VOID FASTCALL PALETTE_ValidateFlags(PALETTEENTRY* lpPalE, INT size)
219 {
220 int i = 0;
221 for( ; i<size ; i++ )
222 lpPalE[i].peFlags = PC_SYS_USED | (lpPalE[i].peFlags & 0x07);
223 }
224
225 #ifndef NO_MAPPING
226 // Set the color-mapping table for selected palette.
227 // Return number of entries which mapping has changed.
228 INT STDCALL PALETTE_SetMapping(PALOBJ *palPtr, UINT uStart, UINT uNum, BOOL mapOnly)
229 {
230 char flag;
231 int prevMapping = (palPtr->mapping) ? 1 : 0;
232 int index, iRemapped = 0;
233 int *mapping;
234 HPALETTE hSysPal = NtGdiGetStockObject(DEFAULT_PALETTE);
235 PPALGDI pSysPal = PALETTE_LockPalette(hSysPal);
236 PPALGDI palGDI = (PPALGDI) palPtr;
237 /* FIXME - handle pSysPal == NULL!!!!!!! */
238
239 COLOR_sysPal = pSysPal->IndexedColors;
240 PALETTE_UnlockPalette(pSysPal); // FIXME: Is this a right way to obtain pointer to the system palette?
241
242
243 // reset dynamic system palette entries
244
245 if( !mapOnly && PALETTE_firstFree != -1) PALETTE_FormatSystemPalette();
246
247 // initialize palette mapping table
248
249 //mapping = HeapReAlloc( GetProcessHeap(), 0, palPtr->mapping,
250 // sizeof(int)*palPtr->logpalette->palNumEntries);
251 ExFreePool(palPtr->mapping);
252 mapping = ExAllocatePoolWithTag(PagedPool, sizeof(int)*palGDI->NumColors, TAG_PALETTEMAP);
253
254 palPtr->mapping = mapping;
255
256 for(uNum += uStart; uStart < uNum; uStart++)
257 {
258 index = -1;
259 flag = PC_SYS_USED;
260
261 switch( palGDI->IndexedColors[uStart].peFlags & 0x07 )
262 {
263 case PC_EXPLICIT: // palette entries are indices into system palette
264 // The PC_EXPLICIT flag is used to copy an entry from the system palette into the logical palette
265 index = *(WORD*)(palGDI->IndexedColors + uStart);
266 if(index > 255 || (index >= COLOR_gapStart && index <= COLOR_gapEnd))
267 {
268 DbgPrint("Win32k: PC_EXPLICIT: idx %d out of system palette, assuming black.\n", index);
269 index = 0;
270 }
271 break;
272
273 case PC_RESERVED: // forbid future mappings to this entry
274 // For palette animation, the entries in the logical palette need the PC_RESERVED flag
275 flag |= PC_SYS_RESERVED;
276
277 // fall through
278 default: // try to collapse identical colors
279 index = COLOR_PaletteLookupExactIndex(COLOR_sysPal, 256,
280 *(COLORREF*)(palGDI->IndexedColors + uStart));
281 // fall through
282
283 case PC_NOCOLLAPSE:
284 // If an entry in the logical palette is marked with the PC_NOCOLLAPSE flag, the palette
285 // manager allocates a free entry in the system palette if one is available and only uses the
286 // closest colour match if there are no (more) free entries in the system palette
287
288 DbgPrint("Win32k: WARNING: PC_NOCOLLAPSE is not yet working properly\n");
289
290 if( index < 0 )
291 {
292 if(PALETTE_firstFree > 0 /* && !(PALETTE_PaletteFlags & PALETTE_FIXED) FIXME */ )
293 {
294 DbgPrint("Win32k: Unimplemented Palette Operation: PC_NOCOLLAPSE [objects/palette.c]\n");
295 /* XColor color;
296 index = PALETTE_firstFree; // ought to be available
297 PALETTE_firstFree = PALETTE_freeList[index];
298
299 color.pixel = (PALETTE_PaletteToXPixel) ? PALETTE_PaletteToXPixel[index] : index;
300 color.red = palPtr->logpalette->palPalEntry[uStart].peRed << 8;
301 color.green = palPtr->logpalette->palPalEntry[uStart].peGreen << 8;
302 color.blue = palPtr->logpalette->palPalEntry[uStart].peBlue << 8;
303 color.flags = DoRed | DoGreen | DoBlue;
304 TSXStoreColor(display, PALETTE_PaletteXColormap, &color);
305
306 COLOR_sysPal[index] = palPtr->logpalette->palPalEntry[uStart];
307 COLOR_sysPal[index].peFlags = flag;
308 PALETTE_freeList[index] = 0;
309
310 if(PALETTE_PaletteToXPixel) index = PALETTE_PaletteToXPixel[index]; */
311 break;
312 }
313 /* else if (PALETTE_PaletteFlags & PALETTE_VIRTUAL)
314 {
315 index = PALETTE_ToPhysical(NULL, 0x00ffffff &
316 *(COLORREF*)(palPtr->logpalette->palPalEntry + uStart));
317 break;
318 } FIXME */
319
320 // we have to map to existing entry in the system palette
321
322 index = COLOR_PaletteLookupPixel(COLOR_sysPal, 256, NULL,
323 *(COLORREF*)(palGDI->IndexedColors + uStart), TRUE);
324 }
325 palGDI->IndexedColors[uStart].peFlags |= PC_SYS_USED;
326
327 /* if(PALETTE_PaletteToXPixel) index = PALETTE_PaletteToXPixel[index]; FIXME */
328 break;
329 }
330
331 if( !prevMapping || palPtr->mapping[uStart] != index ) iRemapped++;
332 palPtr->mapping[uStart] = index;
333
334 }
335 return iRemapped;
336 }
337 #endif
338
339 /* EOF */