2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
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.
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.
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.
26 static int PALETTE_firstFree
= 0;
27 static unsigned char PALETTE_freeList
[256];
30 int PALETTE_PaletteFlags
= 0;
31 PALETTEENTRY
*COLOR_sysPal
= NULL
;
37 PPALETTEENTRY FASTCALL
ReturnSystemPalette (VOID
)
43 PALETTE_Cleanup(PVOID ObjectBody
)
45 PPALGDI pPal
= (PPALGDI
)ObjectBody
;
46 if (NULL
!= pPal
->IndexedColors
)
48 ExFreePool(pPal
->IndexedColors
);
56 PALETTE_AllocPalette(ULONG Mode
,
66 PalGDI
= (PPALGDI
)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_PALETTE
);
72 NewPalette
= PalGDI
->BaseObject
.hHmgr
;
74 PalGDI
->Self
= NewPalette
;
79 PalGDI
->IndexedColors
= ExAllocatePoolWithTag(PagedPool
, sizeof(PALETTEENTRY
) * NumColors
, TAG_PALETTE
);
80 if (NULL
== PalGDI
->IndexedColors
)
82 PALETTE_UnlockPalette(PalGDI
);
83 PALETTE_FreePaletteByHandle(NewPalette
);
86 RtlCopyMemory(PalGDI
->IndexedColors
, Colors
, sizeof(PALETTEENTRY
) * NumColors
);
89 if (PAL_INDEXED
== Mode
)
91 PalGDI
->NumColors
= NumColors
;
93 else if (PAL_BITFIELDS
== Mode
)
95 PalGDI
->RedMask
= Red
;
96 PalGDI
->GreenMask
= Green
;
97 PalGDI
->BlueMask
= Blue
;
100 PALETTE_UnlockPalette(PalGDI
);
107 PALETTE_AllocPaletteIndexedRGB(ULONG NumColors
,
108 CONST RGBQUAD
*Colors
)
114 PalGDI
= (PPALGDI
)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_PALETTE
);
120 NewPalette
= PalGDI
->BaseObject
.hHmgr
;
122 PalGDI
->Self
= NewPalette
;
123 PalGDI
->Mode
= PAL_INDEXED
;
125 PalGDI
->IndexedColors
= ExAllocatePoolWithTag(PagedPool
, sizeof(PALETTEENTRY
) * NumColors
, TAG_PALETTE
);
126 if (NULL
== PalGDI
->IndexedColors
)
128 PALETTE_UnlockPalette(PalGDI
);
129 PALETTE_FreePaletteByHandle(NewPalette
);
132 for (i
= 0; i
< NumColors
; i
++)
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;
140 PalGDI
->NumColors
= NumColors
;
142 PALETTE_UnlockPalette(PalGDI
);
147 // Create the system palette
148 HPALETTE FASTCALL
PALETTE_Init(VOID
)
156 const PALETTEENTRY
* __sysPalTemplate
= (const PALETTEENTRY
*)COLOR_GetSystemPaletteTemplate();
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
;
162 palPtr
->palVersion
= 0x300;
163 palPtr
->palNumEntries
= NB_RESERVED_COLORS
;
164 for(i
=0; i
<NB_RESERVED_COLORS
; i
++)
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;
172 hpalette
= NtGdiCreatePaletteInternal(palPtr
,NB_RESERVED_COLORS
);
173 ExFreePoolWithTag(palPtr
, TAG_PALETTE
);
176 palObj
= (PALOBJ
*)PALETTE_LockPalette(hpalette
);
179 if (!(palObj
->mapping
= ExAllocatePool(PagedPool
, sizeof(int) * 20)))
181 DbgPrint("Win32k: Can not create palette mapping -- out of memory!");
184 PALETTE_UnlockPalette(palObj
);
188 /* palette_size = visual->map_entries; */
194 static void FASTCALL
PALETTE_FormatSystemPalette(void)
196 // Build free list so we'd have an easy way to find
197 // out if there are any available colorcells.
199 int i
, j
= PALETTE_firstFree
= NB_RESERVED_COLORS
/2;
201 COLOR_sysPal
[j
].peFlags
= 0;
202 for(i
= (NB_RESERVED_COLORS
>>1) + 1 ; i
< 256 - (NB_RESERVED_COLORS
>>1) ; i
++)
204 if( i
< COLOR_gapStart
|| i
> COLOR_gapEnd
)
206 COLOR_sysPal
[i
].peFlags
= 0; // unused tag
207 PALETTE_freeList
[j
] = i
; // next
211 PALETTE_freeList
[j
] = 0;
215 VOID FASTCALL
PALETTE_ValidateFlags(PALETTEENTRY
* lpPalE
, INT size
)
218 for( ; i
<size
; i
++ )
219 lpPalE
[i
].peFlags
= PC_SYS_USED
| (lpPalE
[i
].peFlags
& 0x07);
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
)
228 int prevMapping
= (palPtr
->mapping
) ? 1 : 0;
229 int index
, iRemapped
= 0;
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!!!!!!! */
236 COLOR_sysPal
= pSysPal
->IndexedColors
;
237 PALETTE_UnlockPalette(pSysPal
); // FIXME: Is this a right way to obtain pointer to the system palette?
240 // reset dynamic system palette entries
242 if( !mapOnly
&& PALETTE_firstFree
!= -1) PALETTE_FormatSystemPalette();
244 // initialize palette mapping table
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
);
253 DPRINT1("Failed allocating memory for palette mapping!\n");
257 palPtr
->mapping
= mapping
;
259 for(uNum
+= uStart
; uStart
< uNum
; uStart
++)
264 switch( palGDI
->IndexedColors
[uStart
].peFlags
& 0x07 )
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
))
271 DbgPrint("Win32k: PC_EXPLICIT: idx %d out of system palette, assuming black.\n", index
);
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
;
281 default: // try to collapse identical colors
282 index
= COLOR_PaletteLookupExactIndex(COLOR_sysPal
, 256,
283 *(COLORREF
*)(palGDI
->IndexedColors
+ uStart
));
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
291 DbgPrint("Win32k: WARNING: PC_NOCOLLAPSE is not yet working properly\n");
295 if(PALETTE_firstFree
> 0 /* && !(PALETTE_PaletteFlags & PALETTE_FIXED) FIXME */ )
297 DbgPrint("Win32k: Unimplemented Palette Operation: PC_NOCOLLAPSE [objects/palette.c]\n");
299 index = PALETTE_firstFree; // ought to be available
300 PALETTE_firstFree = PALETTE_freeList[index];
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);
309 COLOR_sysPal[index] = palPtr->logpalette->palPalEntry[uStart];
310 COLOR_sysPal[index].peFlags = flag;
311 PALETTE_freeList[index] = 0;
313 if(PALETTE_PaletteToXPixel) index = PALETTE_PaletteToXPixel[index]; */
316 /* else if (PALETTE_PaletteFlags & PALETTE_VIRTUAL)
318 index = PALETTE_ToPhysical(NULL, 0x00ffffff &
319 *(COLORREF*)(palPtr->logpalette->palPalEntry + uStart));
323 // we have to map to existing entry in the system palette
325 index
= COLOR_PaletteLookupPixel(COLOR_sysPal
, 256, NULL
,
326 *(COLORREF
*)(palGDI
->IndexedColors
+ uStart
), TRUE
);
328 palGDI
->IndexedColors
[uStart
].peFlags
|= PC_SYS_USED
;
330 /* if(PALETTE_PaletteToXPixel) index = PALETTE_PaletteToXPixel[index]; FIXME */
334 if( !prevMapping
|| palPtr
->mapping
[uStart
] != index
) iRemapped
++;
335 palPtr
->mapping
[uStart
] = index
;
342 PALETTE_GetObject(PPALGDI pGdiObject
, INT cbCount
, LPLOGBRUSH lpBuffer
)
348 if ((UINT
)cbCount
< sizeof(WORD
)) return 0;
349 *((WORD
*)lpBuffer
) = (WORD
)pGdiObject
->NumColors
;