1 // FIXME: Use PXLATEOBJ logicalToSystem instead of int *mapping
3 #undef WIN32_LEAN_AND_MEAN
6 #include <ddk/winddi.h>
8 #include <win32k/color.h>
9 #include <include/eng.h>
10 #include "../eng/handle.h"
13 #include <win32k/debug1.h>
15 int COLOR_gapStart
= 256;
16 int COLOR_gapEnd
= -1;
17 int COLOR_gapFilled
= 0;
20 static HPALETTE hPrimaryPalette
= 0; // used for WM_PALETTECHANGED
21 static HPALETTE hLastRealizedPalette
= 0; // UnrealizeObject() needs it
23 const PALETTEENTRY COLOR_sysPalTemplate
[NO_RESERVED_COLORS
] =
25 // first 10 entries in the system palette
26 // red green blue flags
27 { 0x00, 0x00, 0x00, PC_SYS_USED
},
28 { 0x80, 0x00, 0x00, PC_SYS_USED
},
29 { 0x00, 0x80, 0x00, PC_SYS_USED
},
30 { 0x80, 0x80, 0x00, PC_SYS_USED
},
31 { 0x00, 0x00, 0x80, PC_SYS_USED
},
32 { 0x80, 0x00, 0x80, PC_SYS_USED
},
33 { 0x00, 0x80, 0x80, PC_SYS_USED
},
34 { 0xc0, 0xc0, 0xc0, PC_SYS_USED
},
35 { 0xc0, 0xdc, 0xc0, PC_SYS_USED
},
36 { 0xa6, 0xca, 0xf0, PC_SYS_USED
},
38 // ... c_min/2 dynamic colorcells
39 // ... gap (for sparse palettes)
40 // ... c_min/2 dynamic colorcells
42 { 0xff, 0xfb, 0xf0, PC_SYS_USED
},
43 { 0xa0, 0xa0, 0xa4, PC_SYS_USED
},
44 { 0x80, 0x80, 0x80, PC_SYS_USED
},
45 { 0xff, 0x00, 0x00, PC_SYS_USED
},
46 { 0x00, 0xff, 0x00, PC_SYS_USED
},
47 { 0xff, 0xff, 0x00, PC_SYS_USED
},
48 { 0x00, 0x00, 0xff, PC_SYS_USED
},
49 { 0xff, 0x00, 0xff, PC_SYS_USED
},
50 { 0x00, 0xff, 0xff, PC_SYS_USED
},
51 { 0xff, 0xff, 0xff, PC_SYS_USED
} // last 10
54 //forward declarations
55 COLORREF
COLOR_LookupNearestColor( PALETTEENTRY
* palPalEntry
, int size
, COLORREF color
);
58 const PALETTEENTRY
* COLOR_GetSystemPaletteTemplate(void)
60 return (const PALETTEENTRY
*)&COLOR_sysPalTemplate
;
63 BOOL STDCALL
W32kAnimatePalette(HPALETTE hpal
,
66 CONST PPALETTEENTRY ppe
)
69 if( hPal != W32kGetStockObject(DEFAULT_PALETTE) )
71 PALETTEOBJ* palPtr = (PALETTEOBJ *)GDI_GetObjPtr(hPal, PALETTE_MAGIC);
72 if (!palPtr) return FALSE;
74 if( (StartIndex + NumEntries) <= palPtr->logpalette.palNumEntries )
77 for( u = 0; u < NumEntries; u++ )
78 palPtr->logpalette.palPalEntry[u + StartIndex] = PaletteColors[u];
79 PALETTE_Driver->pSetMapping(palPtr, StartIndex, NumEntries, hPal != hPrimaryPalette );
90 HPALETTE STDCALL
W32kCreateHalftonePalette(HDC hDC
)
96 PALETTEENTRY aEntries
[256];
99 Palette
.Version
= 0x300;
100 Palette
.NumberOfEntries
= 256;
101 W32kGetSystemPaletteEntries(hDC
, 0, 256, Palette
.aEntries
);
103 for (r
= 0; r
< 6; r
++) {
104 for (g
= 0; g
< 6; g
++) {
105 for (b
= 0; b
< 6; b
++) {
106 i
= r
+ g
*6 + b
*36 + 10;
107 Palette
.aEntries
[i
].peRed
= r
* 51;
108 Palette
.aEntries
[i
].peGreen
= g
* 51;
109 Palette
.aEntries
[i
].peBlue
= b
* 51;
114 for (i
= 216; i
< 246; i
++) {
115 int v
= (i
- 216) * 8;
116 Palette
.aEntries
[i
].peRed
= v
;
117 Palette
.aEntries
[i
].peGreen
= v
;
118 Palette
.aEntries
[i
].peBlue
= v
;
121 return W32kCreatePalette((LOGPALETTE
*)&Palette
);
124 HPALETTE STDCALL
W32kCreatePalette(CONST PLOGPALETTE palette
)
126 // FIXME: PALOBJ is not correct - reimplement
129 HPALETTE NewPalette
= (HPALETTE
)EngCreatePalette(PAL_INDEXED
, palette
->palNumEntries
, (PULONG
*) palette
->palPalEntry
, 0, 0, 0);
132 PalObj
= (ROS_PALOBJ
*)AccessUserObject(NewPalette
);
134 size
= sizeof(LOGPALETTE
) + (palette
->palNumEntries
* sizeof(PALETTEENTRY
));
135 PalObj
->logpalette
= ExAllocatePool(NonPagedPool
, size
);
136 memcpy(PalObj
->logpalette
, palette
, size
);
137 PALETTE_ValidateFlags(PalObj
->logpalette
->palPalEntry
, PalObj
->logpalette
->palNumEntries
);
138 PalObj
->logicalToSystem
= NULL
;
143 BOOL STDCALL
W32kGetColorAdjustment(HDC hDC
,
144 LPCOLORADJUSTMENT ca
)
149 COLORREF STDCALL
W32kGetNearestColor(HDC hDC
,
152 COLORREF nearest
= CLR_INVALID
;
156 if( (dc
= DC_HandleToPtr(hDC
) ) )
158 HPALETTE hpal
= (dc
->w
.hPalette
)? dc
->w
.hPalette
: W32kGetStockObject(DEFAULT_PALETTE
);
159 palObj
= (ROS_PALOBJ
*)AccessUserObject(hpal
);
161 // GDI_ReleaseObj(hdc);
165 nearest
= COLOR_LookupNearestColor(palObj
->logpalette
->palPalEntry
,
166 palObj
->logpalette
->palNumEntries
, Color
);
167 // FIXME: release hpal!!
168 // GDI_ReleaseObj( hpal );
169 DC_ReleasePtr( hDC
);
175 UINT STDCALL
W32kGetNearestPaletteIndex(HPALETTE hpal
,
178 ROS_PALOBJ
* palObj
= (ROS_PALOBJ
*)AccessUserObject(hpal
);
183 // Return closest match for the given RGB color
184 index
= COLOR_PaletteLookupPixel(palObj
->logpalette
->palPalEntry
, palObj
->logpalette
->palNumEntries
, NULL
, Color
, FALSE
);
185 // GDI_ReleaseObj( hpalette );
191 UINT STDCALL
W32kGetPaletteEntries(HPALETTE hpal
,
199 palPtr
= (ROS_PALOBJ
*)AccessUserObject(hpal
);
200 if (!palPtr
) return 0;
202 numEntries
= palPtr
->logpalette
->palNumEntries
;
203 if (StartIndex
+ Entries
> numEntries
) Entries
= numEntries
- StartIndex
;
206 if (StartIndex
>= numEntries
)
208 // GDI_ReleaseObj( hpalette );
211 memcpy(pe
, &palPtr
->logpalette
->palPalEntry
[StartIndex
], Entries
* sizeof(PALETTEENTRY
));
212 for(numEntries
= 0; numEntries
< Entries
; numEntries
++)
213 if (pe
[numEntries
].peFlags
& 0xF0)
214 pe
[numEntries
].peFlags
= 0;
217 // GDI_ReleaseObj( hpalette );
221 UINT STDCALL
W32kGetSystemPaletteEntries(HDC hDC
,
229 if (!(dc = AccessUserObject(hdc))) return 0;
233 Entries = dc->devCaps->sizePalette;
237 if (StartIndex >= dc->devCaps->sizePalette)
243 if (StartIndex + Entries >= dc->devCaps->sizePalette) Entries = dc->devCaps->sizePalette - StartIndex;
245 for (i = 0; i < Entries; i++)
247 *(COLORREF*)(entries + i) = COLOR_GetSystemPaletteEntry(StartIndex + i);
251 // GDI_ReleaseObj(hdc);
255 UINT STDCALL
W32kGetSystemPaletteUse(HDC hDC
)
260 UINT STDCALL
W32kRealizePalette(HDC hDC
)
262 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.
264 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.
266 1= IF DRAWING TO A DEVICE
267 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
269 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the system palette.
271 2= IF DRAWING TO A MEMORY DC\BITMAP
272 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
274 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the dc palette.
277 ROS_PALOBJ
*palPtr
, *sysPtr
;
278 PPALGDI palGDI
, sysGDI
;
280 PDC dc
= (PDC
)AccessUserObject(hDC
);
281 HPALETTE systemPalette
;
287 palPtr
= (ROS_PALOBJ
*)AccessUserObject(dc
->w
.hPalette
);
288 SurfGDI
= (PSURFGDI
)AccessInternalObjectFromUserObject(dc
->Surface
);
289 systemPalette
= W32kGetStockObject(STOCK_DEFAULT_PALETTE
);
290 sysPtr
= (ROS_PALOBJ
*)AccessInternalObject(systemPalette
);
291 palGDI
= (PPALGDI
)AccessInternalObject(dc
->w
.hPalette
);
292 sysGDI
= (PPALGDI
)AccessInternalObject(systemPalette
);
294 // Step 1: Create mapping of system palette\DC palette
295 realized
= PALETTE_SetMapping(palPtr
, 0, palPtr
->logpalette
->palNumEntries
,
296 (dc
->w
.hPalette
!= hPrimaryPalette
) ||
297 (dc
->w
.hPalette
== W32kGetStockObject(DEFAULT_PALETTE
)));
300 // The RealizePalette function modifies the palette for the device associated with the specified device context. If the
301 // device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device
302 // context is a display DC, the physical palette for that device is modified.
303 if(dc
->w
.flags
== DC_MEMORY
)
306 DbgPrint("win32k: realizepalette unimplemented step 2 for DC_MEMORY");
308 if(SurfGDI
->SetPalette
)
310 success
= SurfGDI
->SetPalette(dc
->PDev
, sysPtr
, 0, 0, sysPtr
->logpalette
->palNumEntries
);
314 // Step 3: Create the XLATEOBJ for device managed DCs
315 if(dc
->w
.flags
!= DC_MEMORY
)
318 palPtr
->logicalToSystem
= EngCreateXlate(sysGDI
->Mode
, palGDI
->Mode
, systemPalette
, dc
->w
.hPalette
);
321 // GDI_ReleaseObj(dc->w.hPalette);
322 // GDI_ReleaseObj(hdc);
327 BOOL STDCALL
W32kResizePalette(HPALETTE hpal
,
330 /* PALOBJ* palPtr = (PALOBJ*)AccessUserObject(hPal);
331 UINT cPrevEnt, prevVer;
332 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
333 PXLATEOBJ XlateObj = NULL;
335 if(!palPtr) return FALSE;
336 cPrevEnt = palPtr->logpalette->palNumEntries;
337 prevVer = palPtr->logpalette->palVersion;
338 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
339 size += sizeof(int*) + sizeof(GDIOBJHDR);
340 XlateObj = palPtr->logicalToSystem;
342 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
346 PXLATEOBJ NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
347 if(NewXlateObj == NULL)
349 ERR("Can not resize logicalToSystem -- out of memory!");
350 GDI_ReleaseObj( hPal );
353 palPtr->logicalToSystem = NewXlateObj;
356 if(cEntries > cPrevEnt)
358 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
359 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
360 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
362 palPtr->logpalette->palNumEntries = cEntries;
363 palPtr->logpalette->palVersion = prevVer;
364 // GDI_ReleaseObj( hPal );
370 HPALETTE STDCALL
W32kSelectPalette(HDC hDC
,
372 BOOL ForceBackground
)
374 PDC dc
= (PDC
)AccessUserObject(hDC
);
377 oldPal
= dc
->w
.hPalette
;
378 dc
->w
.hPalette
= hpal
;
380 // FIXME: mark the palette as a [fore\back]ground pal
385 BOOL STDCALL
W32kSetColorAdjustment(HDC hDC
,
386 CONST LPCOLORADJUSTMENT ca
)
391 UINT STDCALL
W32kSetPaletteEntries(HPALETTE hpal
,
394 CONST LPPALETTEENTRY pe
)
399 palPtr
= (ROS_PALOBJ
*)AccessUserObject(hpal
);
400 if (!palPtr
) return 0;
402 numEntries
= palPtr
->logpalette
->palNumEntries
;
403 if (Start
>= numEntries
)
405 // GDI_ReleaseObj( hpalette );
408 if (Start
+ Entries
> numEntries
) Entries
= numEntries
- Start
;
409 memcpy(&palPtr
->logpalette
->palPalEntry
[Start
], pe
, Entries
* sizeof(PALETTEENTRY
));
410 PALETTE_ValidateFlags(palPtr
->logpalette
->palPalEntry
, palPtr
->logpalette
->palNumEntries
);
411 ExFreePool(palPtr
->logicalToSystem
);
412 palPtr
->logicalToSystem
= NULL
;
413 // GDI_ReleaseObj( hpalette );
417 UINT STDCALL
W32kSetSystemPaletteUse(HDC hDC
,
423 BOOL STDCALL
W32kUnrealizeObject(HGDIOBJ hgdiobj
)
428 BOOL STDCALL
W32kUpdateColors(HDC hDC
)
434 if (!(dc = AccessUserObject(hDC))) return 0;
435 size = dc->devCaps->sizePalette;
436 // GDI_ReleaseObj( hDC );
438 if (Callout.WindowFromDC)
440 hWnd = Callout.WindowFromDC( hDC );
442 // Docs say that we have to remap current drawable pixel by pixel
443 // but it would take forever given the speed of XGet/PutPixel.
444 if (hWnd && size) Callout.RedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE );
449 int COLOR_PaletteLookupPixel(PALETTEENTRY
*palPalEntry
, int size
,
450 XLATEOBJ
*XlateObj
, COLORREF col
, BOOL skipReserved
)
452 int i
, best
= 0, diff
= 0x7fffffff;
455 for( i
= 0; i
< size
&& diff
; i
++ )
457 if(!(palPalEntry
[i
].peFlags
& PC_SYS_USED
) || (skipReserved
&& palPalEntry
[i
].peFlags
& PC_SYS_RESERVED
))
460 r
= palPalEntry
[i
].peRed
- GetRValue(col
);
461 g
= palPalEntry
[i
].peGreen
- GetGValue(col
);
462 b
= palPalEntry
[i
].peBlue
- GetBValue(col
);
466 if( r
< diff
) { best
= i
; diff
= r
; }
468 return (XlateObj
->pulXlate
) ? XlateObj
->pulXlate
[best
] : best
;
471 COLORREF
COLOR_LookupNearestColor( PALETTEENTRY
* palPalEntry
, int size
, COLORREF color
)
473 unsigned char spec_type
= color
>> 24;
475 PALETTEENTRY
*COLOR_sysPal
= (PALETTEENTRY
*)ReturnSystemPalette();
477 // we need logical palette for PALETTERGB and PALETTEINDEX colorrefs
479 if( spec_type
== 2 ) /* PALETTERGB */
480 color
= *(COLORREF
*)(palPalEntry
+ COLOR_PaletteLookupPixel(palPalEntry
,size
,NULL
,color
,FALSE
));
482 else if( spec_type
== 1 ) /* PALETTEINDEX */
484 if( (i
= color
& 0x0000ffff) >= size
)
486 DbgPrint("RGB(%lx) : idx %d is out of bounds, assuming NULL\n", color
, i
);
487 color
= *(COLORREF
*)palPalEntry
;
489 else color
= *(COLORREF
*)(palPalEntry
+ i
);
493 return (0x00ffffff & *(COLORREF
*)(COLOR_sysPal
+ COLOR_PaletteLookupPixel(COLOR_sysPal
, 256, NULL
, color
, FALSE
)));
496 int COLOR_PaletteLookupExactIndex( PALETTEENTRY
* palPalEntry
, int size
,
500 BYTE r
= GetRValue(col
), g
= GetGValue(col
), b
= GetBValue(col
);
501 for( i
= 0; i
< size
; i
++ )
503 if( palPalEntry
[i
].peFlags
& PC_SYS_USED
) /* skips gap */
504 if(palPalEntry
[i
].peRed
== r
&& palPalEntry
[i
].peGreen
== g
&& palPalEntry
[i
].peBlue
== b
) return i
;