1 // FIXME: Use PXLATEOBJ logicalToSystem instead of int *mapping
3 #undef WIN32_LEAN_AND_MEAN
6 #include <ddk/winddi.h>
7 #include <win32k/brush.h>
9 #include <win32k/color.h>
10 #include <win32k/pen.h>
11 #include "../eng/handle.h"
12 #include <include/inteng.h>
15 #include <win32k/debug1.h>
17 int COLOR_gapStart = 256;
18 int COLOR_gapEnd = -1;
19 int COLOR_gapFilled = 0;
22 static HPALETTE hPrimaryPalette = 0; // used for WM_PALETTECHANGED
23 static HPALETTE hLastRealizedPalette = 0; // UnrealizeObject() needs it
25 const PALETTEENTRY COLOR_sysPalTemplate[NB_RESERVED_COLORS] =
27 // first 10 entries in the system palette
28 // red green blue flags
29 { 0x00, 0x00, 0x00, PC_SYS_USED },
30 { 0x80, 0x00, 0x00, PC_SYS_USED },
31 { 0x00, 0x80, 0x00, PC_SYS_USED },
32 { 0x80, 0x80, 0x00, PC_SYS_USED },
33 { 0x00, 0x00, 0x80, PC_SYS_USED },
34 { 0x80, 0x00, 0x80, PC_SYS_USED },
35 { 0x00, 0x80, 0x80, PC_SYS_USED },
36 { 0xc0, 0xc0, 0xc0, PC_SYS_USED },
37 { 0xc0, 0xdc, 0xc0, PC_SYS_USED },
38 { 0xa6, 0xca, 0xf0, PC_SYS_USED },
40 // ... c_min/2 dynamic colorcells
41 // ... gap (for sparse palettes)
42 // ... c_min/2 dynamic colorcells
44 { 0xff, 0xfb, 0xf0, PC_SYS_USED },
45 { 0xa0, 0xa0, 0xa4, PC_SYS_USED },
46 { 0x80, 0x80, 0x80, PC_SYS_USED },
47 { 0xff, 0x00, 0x00, PC_SYS_USED },
48 { 0x00, 0xff, 0x00, PC_SYS_USED },
49 { 0xff, 0xff, 0x00, PC_SYS_USED },
50 { 0x00, 0x00, 0xff, PC_SYS_USED },
51 { 0xff, 0x00, 0xff, PC_SYS_USED },
52 { 0x00, 0xff, 0xff, PC_SYS_USED },
53 { 0xff, 0xff, 0xff, PC_SYS_USED } // last 10
56 ULONG W32kGetSysColor(int nIndex)
58 PALETTEENTRY *p = COLOR_sysPalTemplate + (nIndex * sizeof(PALETTEENTRY));
59 return RGB(p->peRed, p->peGreen, p->peBlue);
62 HPEN STDCALL W32kGetSysColorPen(int nIndex)
65 memcpy(&Col, COLOR_sysPalTemplate + nIndex, sizeof(COLORREF));
66 return(W32kCreatePen(PS_SOLID, 1, Col));
69 HBRUSH STDCALL W32kGetSysColorBrush(int nIndex)
72 memcpy(&Col, COLOR_sysPalTemplate + nIndex, sizeof(COLORREF));
73 return(W32kCreateSolidBrush(Col));
76 //forward declarations
77 COLORREF COLOR_LookupNearestColor( PALETTEENTRY* palPalEntry, int size, COLORREF color );
80 const PALETTEENTRY* COLOR_GetSystemPaletteTemplate(void)
82 return (const PALETTEENTRY*)&COLOR_sysPalTemplate;
85 BOOL STDCALL W32kAnimatePalette(HPALETTE hpal,
88 CONST PPALETTEENTRY ppe)
91 if( hPal != W32kGetStockObject(DEFAULT_PALETTE) )
93 PALETTEOBJ* palPtr = (PALETTEOBJ *)GDI_GetObjPtr(hPal, PALETTE_MAGIC);
94 if (!palPtr) return FALSE;
96 if( (StartIndex + NumEntries) <= palPtr->logpalette.palNumEntries )
99 for( u = 0; u < NumEntries; u++ )
100 palPtr->logpalette.palPalEntry[u + StartIndex] = PaletteColors[u];
101 PALETTE_Driver->pSetMapping(palPtr, StartIndex, NumEntries, hPal != hPrimaryPalette );
102 GDI_ReleaseObj(hPal);
105 GDI_ReleaseObj(hPal);
112 HPALETTE STDCALL W32kCreateHalftonePalette(HDC hDC)
117 WORD NumberOfEntries;
118 PALETTEENTRY aEntries[256];
121 Palette.Version = 0x300;
122 Palette.NumberOfEntries = 256;
123 W32kGetSystemPaletteEntries(hDC, 0, 256, Palette.aEntries);
125 for (r = 0; r < 6; r++) {
126 for (g = 0; g < 6; g++) {
127 for (b = 0; b < 6; b++) {
128 i = r + g*6 + b*36 + 10;
129 Palette.aEntries[i].peRed = r * 51;
130 Palette.aEntries[i].peGreen = g * 51;
131 Palette.aEntries[i].peBlue = b * 51;
136 for (i = 216; i < 246; i++) {
137 int v = (i - 216) * 8;
138 Palette.aEntries[i].peRed = v;
139 Palette.aEntries[i].peGreen = v;
140 Palette.aEntries[i].peBlue = v;
143 return W32kCreatePalette((LOGPALETTE *)&Palette);
146 HPALETTE STDCALL W32kCreatePalette(CONST PLOGPALETTE palette)
150 HPALETTE NewPalette = (HPALETTE)EngCreatePalette(PAL_INDEXED, palette->palNumEntries, (PULONG*) palette->palPalEntry, 0, 0, 0);
153 PalObj = (PPALOBJ)AccessUserObject(NewPalette);
155 size = sizeof(LOGPALETTE) + (palette->palNumEntries * sizeof(PALETTEENTRY));
156 PalObj->logpalette = ExAllocatePool(NonPagedPool, size);
157 memcpy(PalObj->logpalette, palette, size);
158 PALETTE_ValidateFlags(PalObj->logpalette->palPalEntry, PalObj->logpalette->palNumEntries);
159 PalObj->logicalToSystem = NULL;
164 BOOL STDCALL W32kGetColorAdjustment(HDC hDC,
165 LPCOLORADJUSTMENT ca)
170 COLORREF STDCALL W32kGetNearestColor(HDC hDC,
173 COLORREF nearest = CLR_INVALID;
177 if( (dc = DC_HandleToPtr(hDC) ) )
179 HPALETTE hpal = (dc->w.hPalette)? dc->w.hPalette : W32kGetStockObject(DEFAULT_PALETTE);
180 palObj = (PPALOBJ)AccessUserObject(hpal);
182 // GDI_ReleaseObj(hdc);
186 nearest = COLOR_LookupNearestColor(palObj->logpalette->palPalEntry,
187 palObj->logpalette->palNumEntries, Color);
188 // FIXME: release hpal!!
189 // GDI_ReleaseObj( hpal );
190 DC_ReleasePtr( hDC );
196 UINT STDCALL W32kGetNearestPaletteIndex(HPALETTE hpal,
199 PPALOBJ palObj = (PPALOBJ)AccessUserObject(hpal);
204 // Return closest match for the given RGB color
205 index = COLOR_PaletteLookupPixel(palObj->logpalette->palPalEntry, palObj->logpalette->palNumEntries, NULL, Color, FALSE);
206 // GDI_ReleaseObj( hpalette );
212 UINT STDCALL W32kGetPaletteEntries(HPALETTE hpal,
220 palPtr = (PPALOBJ)AccessUserObject(hpal);
221 if (!palPtr) return 0;
223 numEntries = palPtr->logpalette->palNumEntries;
224 if (StartIndex + Entries > numEntries) Entries = numEntries - StartIndex;
227 if (StartIndex >= numEntries)
229 // GDI_ReleaseObj( hpalette );
232 memcpy(pe, &palPtr->logpalette->palPalEntry[StartIndex], Entries * sizeof(PALETTEENTRY));
233 for(numEntries = 0; numEntries < Entries ; numEntries++)
234 if (pe[numEntries].peFlags & 0xF0)
235 pe[numEntries].peFlags = 0;
238 // GDI_ReleaseObj( hpalette );
242 UINT STDCALL W32kGetSystemPaletteEntries(HDC hDC,
250 if (!(dc = AccessUserObject(hdc))) return 0;
254 Entries = dc->devCaps->sizePalette;
258 if (StartIndex >= dc->devCaps->sizePalette)
264 if (StartIndex + Entries >= dc->devCaps->sizePalette) Entries = dc->devCaps->sizePalette - StartIndex;
266 for (i = 0; i < Entries; i++)
268 *(COLORREF*)(entries + i) = COLOR_GetSystemPaletteEntry(StartIndex + i);
272 // GDI_ReleaseObj(hdc);
276 UINT STDCALL W32kGetSystemPaletteUse(HDC hDC)
282 The RealizePalette function modifies the palette for the device associated with the specified device context. If the device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device context is a display DC, the physical palette for that device is modified.
284 A logical palette is a buffer between color-intensive applications and the system, allowing these applications to use as many colors as needed without interfering with colors displayed by other windows.
286 1= IF DRAWING TO A DEVICE
287 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
289 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the system palette.
291 2= IF DRAWING TO A MEMORY DC\BITMAP
292 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
294 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the dc palette.
296 UINT STDCALL W32kRealizePalette(HDC hDC)
298 PPALOBJ palPtr, sysPtr;
299 PPALGDI palGDI, sysGDI;
302 HPALETTE systemPalette;
306 dc = DC_HandleToPtr(hDC);
310 palPtr = (PPALOBJ)AccessUserObject(dc->w.hPalette);
311 SurfGDI = (PSURFGDI)AccessInternalObjectFromUserObject(dc->Surface);
312 systemPalette = W32kGetStockObject(STOCK_DEFAULT_PALETTE);
313 sysPtr = (PPALOBJ)AccessInternalObject(systemPalette);
314 palGDI = (PPALGDI)AccessInternalObject(dc->w.hPalette);
315 sysGDI = (PPALGDI)AccessInternalObject(systemPalette);
317 // Step 1: Create mapping of system palette\DC palette
318 realized = PALETTE_SetMapping(palPtr, 0, palPtr->logpalette->palNumEntries,
319 (dc->w.hPalette != hPrimaryPalette) ||
320 (dc->w.hPalette == W32kGetStockObject(DEFAULT_PALETTE)));
323 // The RealizePalette function modifies the palette for the device associated with the specified device context. If the
324 // device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device
325 // context is a display DC, the physical palette for that device is modified.
326 if(dc->w.flags == DC_MEMORY)
329 DbgPrint("win32k: realizepalette unimplemented step 2 for DC_MEMORY");
331 if(SurfGDI->SetPalette)
333 success = SurfGDI->SetPalette(dc->PDev, sysPtr, 0, 0, sysPtr->logpalette->palNumEntries);
337 // Step 3: Create the XLATEOBJ for device managed DCs
338 if(dc->w.flags != DC_MEMORY)
341 palPtr->logicalToSystem = IntEngCreateXlate(sysGDI->Mode, palGDI->Mode, systemPalette, dc->w.hPalette);
344 // GDI_ReleaseObj(dc->w.hPalette);
345 // GDI_ReleaseObj(hdc);
350 BOOL STDCALL W32kResizePalette(HPALETTE hpal,
353 /* PPALOBJ palPtr = (PPALOBJ)AccessUserObject(hPal);
354 UINT cPrevEnt, prevVer;
355 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
356 PXLATEOBJ XlateObj = NULL;
358 if(!palPtr) return FALSE;
359 cPrevEnt = palPtr->logpalette->palNumEntries;
360 prevVer = palPtr->logpalette->palVersion;
361 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
362 size += sizeof(int*) + sizeof(GDIOBJHDR);
363 XlateObj = palPtr->logicalToSystem;
365 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
369 PXLATEOBJ NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
370 if(NewXlateObj == NULL)
372 ERR("Can not resize logicalToSystem -- out of memory!");
373 GDI_ReleaseObj( hPal );
376 palPtr->logicalToSystem = NewXlateObj;
379 if(cEntries > cPrevEnt)
381 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
382 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
383 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
385 palPtr->logpalette->palNumEntries = cEntries;
386 palPtr->logpalette->palVersion = prevVer;
387 // GDI_ReleaseObj( hPal );
394 * Select logical palette into device context.
395 * \param hDC handle to the device context
396 * \param hpal handle to the palette
397 * \param ForceBackground If this value is FALSE the logical palette will be copied to the device palette only when the applicatioon
398 * is in the foreground. If this value is TRUE then map the colors in the logical palette to the device
399 * palette colors in the best way.
400 * \return old palette
402 * \todo implement ForceBackground == TRUE
404 HPALETTE STDCALL W32kSelectPalette(HDC hDC,
406 BOOL ForceBackground)
411 // FIXME: mark the palette as a [fore\back]ground pal
412 dc = DC_HandleToPtr(hDC);
414 oldPal = dc->w.hPalette;
415 dc->w.hPalette = hpal;
416 DC_ReleasePtr( hDC );
422 BOOL STDCALL W32kSetColorAdjustment(HDC hDC,
423 CONST LPCOLORADJUSTMENT ca)
428 UINT STDCALL W32kSetPaletteEntries(HPALETTE hpal,
431 CONST LPPALETTEENTRY pe)
436 palPtr = (PPALOBJ)AccessUserObject(hpal);
437 if (!palPtr) return 0;
439 numEntries = palPtr->logpalette->palNumEntries;
440 if (Start >= numEntries)
442 // GDI_ReleaseObj( hpalette );
445 if (Start + Entries > numEntries) Entries = numEntries - Start;
446 memcpy(&palPtr->logpalette->palPalEntry[Start], pe, Entries * sizeof(PALETTEENTRY));
447 PALETTE_ValidateFlags(palPtr->logpalette->palPalEntry, palPtr->logpalette->palNumEntries);
448 ExFreePool(palPtr->logicalToSystem);
449 palPtr->logicalToSystem = NULL;
450 // GDI_ReleaseObj( hpalette );
454 UINT STDCALL W32kSetSystemPaletteUse(HDC hDC,
460 BOOL STDCALL W32kUnrealizeObject(HGDIOBJ hgdiobj)
465 BOOL STDCALL W32kUpdateColors(HDC hDC)
471 if (!(dc = AccessUserObject(hDC))) return 0;
472 size = dc->devCaps->sizePalette;
473 // GDI_ReleaseObj( hDC );
475 if (Callout.WindowFromDC)
477 hWnd = Callout.WindowFromDC( hDC );
479 // Docs say that we have to remap current drawable pixel by pixel
480 // but it would take forever given the speed of XGet/PutPixel.
481 if (hWnd && size) Callout.RedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE );
486 int COLOR_PaletteLookupPixel(PALETTEENTRY *palPalEntry, int size,
487 PXLATEOBJ XlateObj, COLORREF col, BOOL skipReserved)
489 int i, best = 0, diff = 0x7fffffff;
492 for( i = 0; i < size && diff ; i++ )
494 if(!(palPalEntry[i].peFlags & PC_SYS_USED) || (skipReserved && palPalEntry[i].peFlags & PC_SYS_RESERVED))
497 r = palPalEntry[i].peRed - GetRValue(col);
498 g = palPalEntry[i].peGreen - GetGValue(col);
499 b = palPalEntry[i].peBlue - GetBValue(col);
503 if( r < diff ) { best = i; diff = r; }
505 return (XlateObj->pulXlate) ? XlateObj->pulXlate[best] : best;
508 COLORREF COLOR_LookupNearestColor( PALETTEENTRY* palPalEntry, int size, COLORREF color )
510 unsigned char spec_type = color >> 24;
512 PALETTEENTRY *COLOR_sysPal = (PALETTEENTRY*)ReturnSystemPalette();
514 // we need logical palette for PALETTERGB and PALETTEINDEX colorrefs
516 if( spec_type == 2 ) /* PALETTERGB */
517 color = *(COLORREF*)(palPalEntry + COLOR_PaletteLookupPixel(palPalEntry,size,NULL,color,FALSE));
519 else if( spec_type == 1 ) /* PALETTEINDEX */
521 if( (i = color & 0x0000ffff) >= size )
523 DbgPrint("RGB(%lx) : idx %d is out of bounds, assuming NULL\n", color, i);
524 color = *(COLORREF*)palPalEntry;
526 else color = *(COLORREF*)(palPalEntry + i);
530 return (0x00ffffff & *(COLORREF*)(COLOR_sysPal + COLOR_PaletteLookupPixel(COLOR_sysPal, 256, NULL, color, FALSE)));
533 int COLOR_PaletteLookupExactIndex( PALETTEENTRY* palPalEntry, int size,
537 BYTE r = GetRValue(col), g = GetGValue(col), b = GetBValue(col);
538 for( i = 0; i < size; i++ )
540 if( palPalEntry[i].peFlags & PC_SYS_USED ) /* skips gap */
541 if(palPalEntry[i].peRed == r && palPalEntry[i].peGreen == g && palPalEntry[i].peBlue == b) return i;