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.
19 /* $Id: color.c,v 1.17 2003/05/18 17:16:17 ea Exp $ */
21 // FIXME: Use PXLATEOBJ logicalToSystem instead of int *mapping
23 #undef WIN32_LEAN_AND_MEAN
25 #include <ddk/ntddk.h>
26 #include <ddk/winddi.h>
27 #include <win32k/brush.h>
28 #include <win32k/dc.h>
29 #include <win32k/color.h>
30 #include <win32k/pen.h>
31 #include "../eng/handle.h"
32 #include <include/inteng.h>
33 #include <include/color.h>
34 #include <include/palette.h>
37 #include <win32k/debug1.h>
39 int COLOR_gapStart
= 256;
40 int COLOR_gapEnd
= -1;
41 int COLOR_gapFilled
= 0;
44 static HPALETTE hPrimaryPalette
= 0; // used for WM_PALETTECHANGED
45 static HPALETTE hLastRealizedPalette
= 0; // UnrealizeObject() needs it
47 const PALETTEENTRY COLOR_sysPalTemplate
[NB_RESERVED_COLORS
] =
49 // first 10 entries in the system palette
50 // red green blue flags
51 { 0x00, 0x00, 0x00, PC_SYS_USED
},
52 { 0x80, 0x00, 0x00, PC_SYS_USED
},
53 { 0x00, 0x80, 0x00, PC_SYS_USED
},
54 { 0x80, 0x80, 0x00, PC_SYS_USED
},
55 { 0x00, 0x00, 0x80, PC_SYS_USED
},
56 { 0x80, 0x00, 0x80, PC_SYS_USED
},
57 { 0x00, 0x80, 0x80, PC_SYS_USED
},
58 { 0xc0, 0xc0, 0xc0, PC_SYS_USED
},
59 { 0xc0, 0xdc, 0xc0, PC_SYS_USED
},
60 { 0xa6, 0xca, 0xf0, PC_SYS_USED
},
62 // ... c_min/2 dynamic colorcells
63 // ... gap (for sparse palettes)
64 // ... c_min/2 dynamic colorcells
66 { 0xff, 0xfb, 0xf0, PC_SYS_USED
},
67 { 0xa0, 0xa0, 0xa4, PC_SYS_USED
},
68 { 0x80, 0x80, 0x80, PC_SYS_USED
},
69 { 0xff, 0x00, 0x00, PC_SYS_USED
},
70 { 0x00, 0xff, 0x00, PC_SYS_USED
},
71 { 0xff, 0xff, 0x00, PC_SYS_USED
},
72 { 0x00, 0x00, 0xff, PC_SYS_USED
},
73 { 0xff, 0x00, 0xff, PC_SYS_USED
},
74 { 0x00, 0xff, 0xff, PC_SYS_USED
},
75 { 0xff, 0xff, 0xff, PC_SYS_USED
} // last 10
78 ULONG FASTCALL
W32kGetSysColor(int nIndex
)
80 PALETTEENTRY
*p
= COLOR_sysPalTemplate
+ (nIndex
* sizeof(PALETTEENTRY
));
81 return RGB(p
->peRed
, p
->peGreen
, p
->peBlue
);
84 HPEN STDCALL
W32kGetSysColorPen(int nIndex
)
87 memcpy(&Col
, COLOR_sysPalTemplate
+ nIndex
, sizeof(COLORREF
));
88 return(W32kCreatePen(PS_SOLID
, 1, Col
));
91 HBRUSH STDCALL
W32kGetSysColorBrush(int nIndex
)
94 memcpy(&Col
, COLOR_sysPalTemplate
+ nIndex
, sizeof(COLORREF
));
95 return(W32kCreateSolidBrush(Col
));
100 const PALETTEENTRY
* FASTCALL
COLOR_GetSystemPaletteTemplate(void)
102 return (const PALETTEENTRY
*)&COLOR_sysPalTemplate
;
105 BOOL STDCALL
W32kAnimatePalette(HPALETTE hpal
,
108 CONST PPALETTEENTRY ppe
)
111 if( hPal != W32kGetStockObject(DEFAULT_PALETTE) )
113 PALETTEOBJ* palPtr = (PALETTEOBJ *)GDI_GetObjPtr(hPal, PALETTE_MAGIC);
114 if (!palPtr) return FALSE;
116 if( (StartIndex + NumEntries) <= palPtr->logpalette.palNumEntries )
119 for( u = 0; u < NumEntries; u++ )
120 palPtr->logpalette.palPalEntry[u + StartIndex] = PaletteColors[u];
121 PALETTE_Driver->pSetMapping(palPtr, StartIndex, NumEntries, hPal != hPrimaryPalette );
122 GDI_ReleaseObj(hPal);
125 GDI_ReleaseObj(hPal);
132 HPALETTE STDCALL
W32kCreateHalftonePalette(HDC hDC
)
137 WORD NumberOfEntries
;
138 PALETTEENTRY aEntries
[256];
141 Palette
.Version
= 0x300;
142 Palette
.NumberOfEntries
= 256;
143 W32kGetSystemPaletteEntries(hDC
, 0, 256, Palette
.aEntries
);
145 for (r
= 0; r
< 6; r
++) {
146 for (g
= 0; g
< 6; g
++) {
147 for (b
= 0; b
< 6; b
++) {
148 i
= r
+ g
*6 + b
*36 + 10;
149 Palette
.aEntries
[i
].peRed
= r
* 51;
150 Palette
.aEntries
[i
].peGreen
= g
* 51;
151 Palette
.aEntries
[i
].peBlue
= b
* 51;
156 for (i
= 216; i
< 246; i
++) {
157 int v
= (i
- 216) * 8;
158 Palette
.aEntries
[i
].peRed
= v
;
159 Palette
.aEntries
[i
].peGreen
= v
;
160 Palette
.aEntries
[i
].peBlue
= v
;
163 return W32kCreatePalette((LOGPALETTE
*)&Palette
);
166 HPALETTE STDCALL
W32kCreatePalette(CONST PLOGPALETTE palette
)
170 HPALETTE NewPalette
= (HPALETTE
)EngCreatePalette(PAL_INDEXED
, palette
->palNumEntries
, (PULONG
*) palette
->palPalEntry
, 0, 0, 0);
173 PalObj
= (PPALOBJ
)AccessUserObject(NewPalette
);
175 size
= sizeof(LOGPALETTE
) + (palette
->palNumEntries
* sizeof(PALETTEENTRY
));
176 PalObj
->logpalette
= ExAllocatePool(NonPagedPool
, size
);
177 memcpy(PalObj
->logpalette
, palette
, size
);
178 PALETTE_ValidateFlags(PalObj
->logpalette
->palPalEntry
, PalObj
->logpalette
->palNumEntries
);
179 PalObj
->logicalToSystem
= NULL
;
184 BOOL STDCALL
W32kGetColorAdjustment(HDC hDC
,
185 LPCOLORADJUSTMENT ca
)
190 COLORREF STDCALL
W32kGetNearestColor(HDC hDC
,
193 COLORREF nearest
= CLR_INVALID
;
197 if( (dc
= DC_HandleToPtr(hDC
) ) )
199 HPALETTE hpal
= (dc
->w
.hPalette
)? dc
->w
.hPalette
: W32kGetStockObject(DEFAULT_PALETTE
);
200 palObj
= (PPALOBJ
)AccessUserObject(hpal
);
202 // GDI_ReleaseObj(hdc);
206 nearest
= COLOR_LookupNearestColor(palObj
->logpalette
->palPalEntry
,
207 palObj
->logpalette
->palNumEntries
, Color
);
208 // FIXME: release hpal!!
209 // GDI_ReleaseObj( hpal );
210 DC_ReleasePtr( hDC
);
216 UINT STDCALL
W32kGetNearestPaletteIndex(HPALETTE hpal
,
219 PPALOBJ palObj
= (PPALOBJ
)AccessUserObject(hpal
);
224 // Return closest match for the given RGB color
225 index
= COLOR_PaletteLookupPixel(palObj
->logpalette
->palPalEntry
, palObj
->logpalette
->palNumEntries
, NULL
, Color
, FALSE
);
226 // GDI_ReleaseObj( hpalette );
232 UINT STDCALL
W32kGetPaletteEntries(HPALETTE hpal
,
240 palPtr
= (PPALOBJ
)AccessUserObject(hpal
);
241 if (!palPtr
) return 0;
243 numEntries
= palPtr
->logpalette
->palNumEntries
;
244 if (StartIndex
+ Entries
> numEntries
) Entries
= numEntries
- StartIndex
;
247 if (StartIndex
>= numEntries
)
249 // GDI_ReleaseObj( hpalette );
252 memcpy(pe
, &palPtr
->logpalette
->palPalEntry
[StartIndex
], Entries
* sizeof(PALETTEENTRY
));
253 for(numEntries
= 0; numEntries
< Entries
; numEntries
++)
254 if (pe
[numEntries
].peFlags
& 0xF0)
255 pe
[numEntries
].peFlags
= 0;
258 // GDI_ReleaseObj( hpalette );
262 UINT STDCALL
W32kGetSystemPaletteEntries(HDC hDC
,
270 if (!(dc = AccessUserObject(hdc))) return 0;
274 Entries = dc->GDIInfo->ulNumPalReg;
278 if (StartIndex >= dc->GDIInfo->ulNumPalReg)
284 if (StartIndex + Entries >= dc->GDIInfo->ulNumPalReg) Entries = dc->GDIInfo->ulNumPalReg - StartIndex;
286 for (i = 0; i < Entries; i++)
288 *(COLORREF*)(entries + i) = COLOR_GetSystemPaletteEntry(StartIndex + i);
292 // GDI_ReleaseObj(hdc);
296 UINT STDCALL
W32kGetSystemPaletteUse(HDC hDC
)
302 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.
304 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.
306 1= IF DRAWING TO A DEVICE
307 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
309 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the system palette.
311 2= IF DRAWING TO A MEMORY DC\BITMAP
312 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
314 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the dc palette.
316 UINT STDCALL
W32kRealizePalette(HDC hDC
)
318 PPALOBJ palPtr
, sysPtr
;
319 PPALGDI palGDI
, sysGDI
;
322 HPALETTE systemPalette
;
326 dc
= DC_HandleToPtr(hDC
);
330 palPtr
= (PPALOBJ
)AccessUserObject(dc
->w
.hPalette
);
331 SurfGDI
= (PSURFGDI
)AccessInternalObjectFromUserObject(dc
->Surface
);
332 systemPalette
= W32kGetStockObject(STOCK_DEFAULT_PALETTE
);
333 sysPtr
= (PPALOBJ
)AccessInternalObject(systemPalette
);
334 palGDI
= (PPALGDI
)AccessInternalObject(dc
->w
.hPalette
);
335 sysGDI
= (PPALGDI
)AccessInternalObject(systemPalette
);
337 // Step 1: Create mapping of system palette\DC palette
338 realized
= PALETTE_SetMapping(palPtr
, 0, palPtr
->logpalette
->palNumEntries
,
339 (dc
->w
.hPalette
!= hPrimaryPalette
) ||
340 (dc
->w
.hPalette
== W32kGetStockObject(DEFAULT_PALETTE
)));
343 // The RealizePalette function modifies the palette for the device associated with the specified device context. If the
344 // device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device
345 // context is a display DC, the physical palette for that device is modified.
346 if(dc
->w
.flags
== DC_MEMORY
)
349 DbgPrint("win32k: realizepalette unimplemented step 2 for DC_MEMORY");
351 if(SurfGDI
->SetPalette
)
353 success
= SurfGDI
->SetPalette(dc
->PDev
, sysPtr
, 0, 0, sysPtr
->logpalette
->palNumEntries
);
357 // Step 3: Create the XLATEOBJ for device managed DCs
358 if(dc
->w
.flags
!= DC_MEMORY
)
361 palPtr
->logicalToSystem
= IntEngCreateXlate(sysGDI
->Mode
, palGDI
->Mode
, systemPalette
, dc
->w
.hPalette
);
364 // GDI_ReleaseObj(dc->w.hPalette);
365 // GDI_ReleaseObj(hdc);
370 BOOL STDCALL
W32kResizePalette(HPALETTE hpal
,
373 /* PPALOBJ palPtr = (PPALOBJ)AccessUserObject(hPal);
374 UINT cPrevEnt, prevVer;
375 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
376 PXLATEOBJ XlateObj = NULL;
378 if(!palPtr) return FALSE;
379 cPrevEnt = palPtr->logpalette->palNumEntries;
380 prevVer = palPtr->logpalette->palVersion;
381 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
382 size += sizeof(int*) + sizeof(GDIOBJHDR);
383 XlateObj = palPtr->logicalToSystem;
385 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
389 PXLATEOBJ NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
390 if(NewXlateObj == NULL)
392 ERR("Can not resize logicalToSystem -- out of memory!");
393 GDI_ReleaseObj( hPal );
396 palPtr->logicalToSystem = NewXlateObj;
399 if(cEntries > cPrevEnt)
401 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
402 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
403 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
405 palPtr->logpalette->palNumEntries = cEntries;
406 palPtr->logpalette->palVersion = prevVer;
407 // GDI_ReleaseObj( hPal );
414 * Select logical palette into device context.
415 * \param hDC handle to the device context
416 * \param hpal handle to the palette
417 * \param ForceBackground If this value is FALSE the logical palette will be copied to the device palette only when the applicatioon
418 * is in the foreground. If this value is TRUE then map the colors in the logical palette to the device
419 * palette colors in the best way.
420 * \return old palette
422 * \todo implement ForceBackground == TRUE
424 HPALETTE STDCALL
W32kSelectPalette(HDC hDC
,
426 BOOL ForceBackground
)
431 // FIXME: mark the palette as a [fore\back]ground pal
432 dc
= DC_HandleToPtr(hDC
);
434 oldPal
= dc
->w
.hPalette
;
435 dc
->w
.hPalette
= hpal
;
436 DC_ReleasePtr( hDC
);
442 BOOL STDCALL
W32kSetColorAdjustment(HDC hDC
,
443 CONST LPCOLORADJUSTMENT ca
)
448 UINT STDCALL
W32kSetPaletteEntries(HPALETTE hpal
,
451 CONST LPPALETTEENTRY pe
)
456 palPtr
= (PPALOBJ
)AccessUserObject(hpal
);
457 if (!palPtr
) return 0;
459 numEntries
= palPtr
->logpalette
->palNumEntries
;
460 if (Start
>= numEntries
)
462 // GDI_ReleaseObj( hpalette );
465 if (Start
+ Entries
> numEntries
) Entries
= numEntries
- Start
;
466 memcpy(&palPtr
->logpalette
->palPalEntry
[Start
], pe
, Entries
* sizeof(PALETTEENTRY
));
467 PALETTE_ValidateFlags(palPtr
->logpalette
->palPalEntry
, palPtr
->logpalette
->palNumEntries
);
468 ExFreePool(palPtr
->logicalToSystem
);
469 palPtr
->logicalToSystem
= NULL
;
470 // GDI_ReleaseObj( hpalette );
474 UINT STDCALL
W32kSetSystemPaletteUse(HDC hDC
,
480 BOOL STDCALL
W32kUnrealizeObject(HGDIOBJ hgdiobj
)
485 BOOL STDCALL
W32kUpdateColors(HDC hDC
)
491 if (!(dc = AccessUserObject(hDC))) return 0;
492 size = dc->GDIInfo->ulNumPalReg;
493 // GDI_ReleaseObj( hDC );
495 if (Callout.WindowFromDC)
497 hWnd = Callout.WindowFromDC( hDC );
499 // Docs say that we have to remap current drawable pixel by pixel
500 // but it would take forever given the speed of XGet/PutPixel.
501 if (hWnd && size) Callout.RedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE );
506 INT STDCALL
COLOR_PaletteLookupPixel(PALETTEENTRY
*palPalEntry
, INT size
,
507 PXLATEOBJ XlateObj
, COLORREF col
, BOOL skipReserved
)
509 int i
, best
= 0, diff
= 0x7fffffff;
512 for( i
= 0; i
< size
&& diff
; i
++ )
514 if(!(palPalEntry
[i
].peFlags
& PC_SYS_USED
) || (skipReserved
&& palPalEntry
[i
].peFlags
& PC_SYS_RESERVED
))
517 r
= palPalEntry
[i
].peRed
- GetRValue(col
);
518 g
= palPalEntry
[i
].peGreen
- GetGValue(col
);
519 b
= palPalEntry
[i
].peBlue
- GetBValue(col
);
523 if( r
< diff
) { best
= i
; diff
= r
; }
525 return (XlateObj
->pulXlate
) ? XlateObj
->pulXlate
[best
] : best
;
528 COLORREF STDCALL
COLOR_LookupNearestColor( PALETTEENTRY
* palPalEntry
, int size
, COLORREF color
)
530 unsigned char spec_type
= color
>> 24;
532 PALETTEENTRY
*COLOR_sysPal
= (PALETTEENTRY
*)ReturnSystemPalette();
534 // we need logical palette for PALETTERGB and PALETTEINDEX colorrefs
536 if( spec_type
== 2 ) /* PALETTERGB */
537 color
= *(COLORREF
*)(palPalEntry
+ COLOR_PaletteLookupPixel(palPalEntry
,size
,NULL
,color
,FALSE
));
539 else if( spec_type
== 1 ) /* PALETTEINDEX */
541 if( (i
= color
& 0x0000ffff) >= size
)
543 DbgPrint("RGB(%lx) : idx %d is out of bounds, assuming NULL\n", color
, i
);
544 color
= *(COLORREF
*)palPalEntry
;
546 else color
= *(COLORREF
*)(palPalEntry
+ i
);
550 return (0x00ffffff & *(COLORREF
*)(COLOR_sysPal
+ COLOR_PaletteLookupPixel(COLOR_sysPal
, 256, NULL
, color
, FALSE
)));
553 int STDCALL
COLOR_PaletteLookupExactIndex( PALETTEENTRY
* palPalEntry
, int size
,
557 BYTE r
= GetRValue(col
), g
= GetGValue(col
), b
= GetBValue(col
);
558 for( i
= 0; i
< size
; i
++ )
560 if( palPalEntry
[i
].peFlags
& PC_SYS_USED
) /* skips gap */
561 if(palPalEntry
[i
].peRed
== r
&& palPalEntry
[i
].peGreen
== g
&& palPalEntry
[i
].peBlue
== b
) return i
;