- Less STDCALL, more WINAPI/NTAPI/APIENTRY
[reactos.git] / reactos / subsystems / win32 / win32k / objects / palobj.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
20 #include <w32k.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25 #ifndef NO_MAPPING
26 static int PALETTE_firstFree = 0;
27 static unsigned char PALETTE_freeList[256];
28 #endif
29
30 int PALETTE_PaletteFlags = 0;
31 PALETTEENTRY *COLOR_sysPal = NULL;
32 int COLOR_gapStart;
33 int COLOR_gapEnd;
34 int COLOR_gapFilled;
35 int COLOR_max;
36
37 PPALETTEENTRY FASTCALL ReturnSystemPalette (VOID)
38 {
39 return COLOR_sysPal;
40 }
41
42 BOOL INTERNAL_CALL
43 PALETTE_Cleanup(PVOID ObjectBody)
44 {
45 PPALGDI pPal = (PPALGDI)ObjectBody;
46 if (NULL != pPal->IndexedColors)
47 {
48 ExFreePool(pPal->IndexedColors);
49 }
50
51 return TRUE;
52 }
53
54 HPALETTE
55 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 PalGDI = (PPALGDI)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_PALETTE);
67 if (!PalGDI)
68 {
69 return NULL;
70 }
71
72 NewPalette = PalGDI->BaseObject.hHmgr;
73
74 PalGDI->Self = NewPalette;
75 PalGDI->Mode = Mode;
76
77 if (NULL != Colors)
78 {
79 PalGDI->IndexedColors = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * NumColors, TAG_PALETTE);
80 if (NULL == PalGDI->IndexedColors)
81 {
82 PALETTE_UnlockPalette(PalGDI);
83 PALETTE_FreePaletteByHandle(NewPalette);
84 return NULL;
85 }
86 RtlCopyMemory(PalGDI->IndexedColors, Colors, sizeof(PALETTEENTRY) * NumColors);
87 }
88
89 if (PAL_INDEXED == Mode)
90 {
91 PalGDI->NumColors = NumColors;
92 }
93 else if (PAL_BITFIELDS == Mode)
94 {
95 PalGDI->RedMask = Red;
96 PalGDI->GreenMask = Green;
97 PalGDI->BlueMask = Blue;
98 }
99
100 PALETTE_UnlockPalette(PalGDI);
101
102 return NewPalette;
103 }
104
105 HPALETTE
106 FASTCALL
107 PALETTE_AllocPaletteIndexedRGB(ULONG NumColors,
108 CONST RGBQUAD *Colors)
109 {
110 HPALETTE NewPalette;
111 PPALGDI PalGDI;
112 UINT i;
113
114 PalGDI = (PPALGDI)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_PALETTE);
115 if (!PalGDI)
116 {
117 return NULL;
118 }
119
120 NewPalette = PalGDI->BaseObject.hHmgr;
121
122 PalGDI->Self = NewPalette;
123 PalGDI->Mode = PAL_INDEXED;
124
125 PalGDI->IndexedColors = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * NumColors, TAG_PALETTE);
126 if (NULL == PalGDI->IndexedColors)
127 {
128 PALETTE_UnlockPalette(PalGDI);
129 PALETTE_FreePaletteByHandle(NewPalette);
130 return NULL;
131 }
132 for (i = 0; i < NumColors; i++)
133 {
134 PalGDI->IndexedColors[i].peRed = Colors[i].rgbRed;
135 PalGDI->IndexedColors[i].peGreen = Colors[i].rgbGreen;
136 PalGDI->IndexedColors[i].peBlue = Colors[i].rgbBlue;
137 PalGDI->IndexedColors[i].peFlags = 0;
138 }
139
140 PalGDI->NumColors = NumColors;
141
142 PALETTE_UnlockPalette(PalGDI);
143
144 return NewPalette;
145 }
146
147 // Create the system palette
148 HPALETTE FASTCALL PALETTE_Init(VOID)
149 {
150 int i;
151 HPALETTE hpalette;
152 PLOGPALETTE palPtr;
153 #ifndef NO_MAPPING
154 PALOBJ *palObj;
155 #endif
156 const PALETTEENTRY* __sysPalTemplate = (const PALETTEENTRY*)COLOR_GetSystemPaletteTemplate();
157
158 // create default palette (20 system colors)
159 palPtr = ExAllocatePoolWithTag(PagedPool, sizeof(LOGPALETTE) + (NB_RESERVED_COLORS * sizeof(PALETTEENTRY)), TAG_PALETTE);
160 if (!palPtr) return FALSE;
161
162 palPtr->palVersion = 0x300;
163 palPtr->palNumEntries = NB_RESERVED_COLORS;
164 for(i=0; i<NB_RESERVED_COLORS; i++)
165 {
166 palPtr->palPalEntry[i].peRed = __sysPalTemplate[i].peRed;
167 palPtr->palPalEntry[i].peGreen = __sysPalTemplate[i].peGreen;
168 palPtr->palPalEntry[i].peBlue = __sysPalTemplate[i].peBlue;
169 palPtr->palPalEntry[i].peFlags = 0;
170 }
171
172 hpalette = NtGdiCreatePaletteInternal(palPtr,NB_RESERVED_COLORS);
173 ExFreePoolWithTag(palPtr, TAG_PALETTE);
174
175 #ifndef NO_MAPPING
176 palObj = (PALOBJ*)PALETTE_LockPalette(hpalette);
177 if (palObj)
178 {
179 if (!(palObj->mapping = ExAllocatePool(PagedPool, sizeof(int) * 20)))
180 {
181 DbgPrint("Win32k: Can not create palette mapping -- out of memory!");
182 return FALSE;
183 }
184 PALETTE_UnlockPalette(palObj);
185 }
186 #endif
187
188 /* palette_size = visual->map_entries; */
189
190 return hpalette;
191 }
192
193 #ifndef NO_MAPPING
194 static void FASTCALL PALETTE_FormatSystemPalette(void)
195 {
196 // Build free list so we'd have an easy way to find
197 // out if there are any available colorcells.
198
199 int i, j = PALETTE_firstFree = NB_RESERVED_COLORS/2;
200
201 COLOR_sysPal[j].peFlags = 0;
202 for(i = (NB_RESERVED_COLORS>>1) + 1 ; i < 256 - (NB_RESERVED_COLORS>>1) ; i++)
203 {
204 if( i < COLOR_gapStart || i > COLOR_gapEnd )
205 {
206 COLOR_sysPal[i].peFlags = 0; // unused tag
207 PALETTE_freeList[j] = i; // next
208 j = i;
209 }
210 }
211 PALETTE_freeList[j] = 0;
212 }
213 #endif
214
215 VOID FASTCALL PALETTE_ValidateFlags(PALETTEENTRY* lpPalE, INT size)
216 {
217 int i = 0;
218 for( ; i<size ; i++ )
219 lpPalE[i].peFlags = PC_SYS_USED | (lpPalE[i].peFlags & 0x07);
220 }
221
222 #ifndef NO_MAPPING
223 // Set the color-mapping table for selected palette.
224 // Return number of entries which mapping has changed.
225 INT APIENTRY PALETTE_SetMapping(PALOBJ *palPtr, UINT uStart, UINT uNum, BOOL mapOnly)
226 {
227 char flag;
228 int prevMapping = (palPtr->mapping) ? 1 : 0;
229 int index, iRemapped = 0;
230 int *mapping;
231 HPALETTE hSysPal = NtGdiGetStockObject(DEFAULT_PALETTE);
232 PPALGDI pSysPal = PALETTE_LockPalette(hSysPal);
233 PPALGDI palGDI = CONTAINING_RECORD(palPtr,PALGDI,PalObj);
234 /* FIXME - handle pSysPal == NULL!!!!!!! */
235
236 COLOR_sysPal = pSysPal->IndexedColors;
237 PALETTE_UnlockPalette(pSysPal); // FIXME: Is this a right way to obtain pointer to the system palette?
238
239
240 // reset dynamic system palette entries
241
242 if( !mapOnly && PALETTE_firstFree != -1) PALETTE_FormatSystemPalette();
243
244 // initialize palette mapping table
245
246 //mapping = HeapReAlloc( GetProcessHeap(), 0, palPtr->mapping,
247 // sizeof(int)*palPtr->logpalette->palNumEntries);
248 ExFreePool(palPtr->mapping);
249 mapping = ExAllocatePoolWithTag(PagedPool, sizeof(int)*palGDI->NumColors, TAG_PALETTEMAP);
250
251 if (!mapping)
252 {
253 DPRINT1("Failed allocating memory for palette mapping!\n");
254 return 0;
255 }
256
257 palPtr->mapping = mapping;
258
259 for(uNum += uStart; uStart < uNum; uStart++)
260 {
261 index = -1;
262 flag = PC_SYS_USED;
263
264 switch( palGDI->IndexedColors[uStart].peFlags & 0x07 )
265 {
266 case PC_EXPLICIT: // palette entries are indices into system palette
267 // The PC_EXPLICIT flag is used to copy an entry from the system palette into the logical palette
268 index = *(WORD*)(palGDI->IndexedColors + uStart);
269 if(index > 255 || (index >= COLOR_gapStart && index <= COLOR_gapEnd))
270 {
271 DbgPrint("Win32k: PC_EXPLICIT: idx %d out of system palette, assuming black.\n", index);
272 index = 0;
273 }
274 break;
275
276 case PC_RESERVED: // forbid future mappings to this entry
277 // For palette animation, the entries in the logical palette need the PC_RESERVED flag
278 flag |= PC_SYS_RESERVED;
279
280 // fall through
281 default: // try to collapse identical colors
282 index = COLOR_PaletteLookupExactIndex(COLOR_sysPal, 256,
283 *(COLORREF*)(palGDI->IndexedColors + uStart));
284 // fall through
285
286 case PC_NOCOLLAPSE:
287 // If an entry in the logical palette is marked with the PC_NOCOLLAPSE flag, the palette
288 // manager allocates a free entry in the system palette if one is available and only uses the
289 // closest colour match if there are no (more) free entries in the system palette
290
291 DbgPrint("Win32k: WARNING: PC_NOCOLLAPSE is not yet working properly\n");
292
293 if( index < 0 )
294 {
295 if(PALETTE_firstFree > 0 /* && !(PALETTE_PaletteFlags & PALETTE_FIXED) FIXME */ )
296 {
297 DbgPrint("Win32k: Unimplemented Palette Operation: PC_NOCOLLAPSE [objects/palette.c]\n");
298 /* XColor color;
299 index = PALETTE_firstFree; // ought to be available
300 PALETTE_firstFree = PALETTE_freeList[index];
301
302 color.pixel = (PALETTE_PaletteToXPixel) ? PALETTE_PaletteToXPixel[index] : index;
303 color.red = palPtr->logpalette->palPalEntry[uStart].peRed << 8;
304 color.green = palPtr->logpalette->palPalEntry[uStart].peGreen << 8;
305 color.blue = palPtr->logpalette->palPalEntry[uStart].peBlue << 8;
306 color.flags = DoRed | DoGreen | DoBlue;
307 TSXStoreColor(display, PALETTE_PaletteXColormap, &color);
308
309 COLOR_sysPal[index] = palPtr->logpalette->palPalEntry[uStart];
310 COLOR_sysPal[index].peFlags = flag;
311 PALETTE_freeList[index] = 0;
312
313 if(PALETTE_PaletteToXPixel) index = PALETTE_PaletteToXPixel[index]; */
314 break;
315 }
316 /* else if (PALETTE_PaletteFlags & PALETTE_VIRTUAL)
317 {
318 index = PALETTE_ToPhysical(NULL, 0x00ffffff &
319 *(COLORREF*)(palPtr->logpalette->palPalEntry + uStart));
320 break;
321 } FIXME */
322
323 // we have to map to existing entry in the system palette
324
325 index = COLOR_PaletteLookupPixel(COLOR_sysPal, 256, NULL,
326 *(COLORREF*)(palGDI->IndexedColors + uStart), TRUE);
327 }
328 palGDI->IndexedColors[uStart].peFlags |= PC_SYS_USED;
329
330 /* if(PALETTE_PaletteToXPixel) index = PALETTE_PaletteToXPixel[index]; FIXME */
331 break;
332 }
333
334 if( !prevMapping || palPtr->mapping[uStart] != index ) iRemapped++;
335 palPtr->mapping[uStart] = index;
336 }
337 return iRemapped;
338 }
339 #endif
340
341 INT FASTCALL
342 PALETTE_GetObject(PPALGDI pGdiObject, INT cbCount, LPLOGBRUSH lpBuffer)
343 {
344 if (!lpBuffer)
345 {
346 return sizeof(WORD);
347 }
348 if ((UINT)cbCount < sizeof(WORD)) return 0;
349 *((WORD*)lpBuffer) = (WORD)pGdiObject->NumColors;
350 return sizeof(WORD);
351 }
352
353 /* EOF */