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.37 2004/04/28 18:38:07 navaraf 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 <win32k/ntuser.h>
32 #include "../eng/handle.h"
33 #include <include/inteng.h>
34 #include <include/eng.h>
35 #include <include/color.h>
36 #include <include/palette.h>
37 #include <include/error.h>
38 #include <include/dce.h>
41 #include <win32k/debug1.h>
43 int COLOR_gapStart
= 256;
44 int COLOR_gapEnd
= -1;
45 int COLOR_gapFilled
= 0;
49 static HPALETTE hPrimaryPalette
= 0; // used for WM_PALETTECHANGED
51 //static HPALETTE hLastRealizedPalette = 0; // UnrealizeObject() needs it
53 const PALETTEENTRY COLOR_sysPalTemplate
[NB_RESERVED_COLORS
] =
55 // first 10 entries in the system palette
56 // red green blue flags
57 { 0x00, 0x00, 0x00, PC_SYS_USED
},
58 { 0x80, 0x00, 0x00, PC_SYS_USED
},
59 { 0x00, 0x80, 0x00, PC_SYS_USED
},
60 { 0x80, 0x80, 0x00, PC_SYS_USED
},
61 { 0x00, 0x00, 0x80, PC_SYS_USED
},
62 { 0x80, 0x00, 0x80, PC_SYS_USED
},
63 { 0x00, 0x80, 0x80, PC_SYS_USED
},
64 { 0xc0, 0xc0, 0xc0, PC_SYS_USED
},
65 { 0xc0, 0xdc, 0xc0, PC_SYS_USED
},
66 { 0xa6, 0xca, 0xf0, PC_SYS_USED
},
68 // ... c_min/2 dynamic colorcells
69 // ... gap (for sparse palettes)
70 // ... c_min/2 dynamic colorcells
72 { 0xff, 0xfb, 0xf0, PC_SYS_USED
},
73 { 0xa0, 0xa0, 0xa4, PC_SYS_USED
},
74 { 0x80, 0x80, 0x80, PC_SYS_USED
},
75 { 0xff, 0x00, 0x00, PC_SYS_USED
},
76 { 0x00, 0xff, 0x00, PC_SYS_USED
},
77 { 0xff, 0xff, 0x00, PC_SYS_USED
},
78 { 0x00, 0x00, 0xff, PC_SYS_USED
},
79 { 0xff, 0x00, 0xff, PC_SYS_USED
},
80 { 0x00, 0xff, 0xff, PC_SYS_USED
},
81 { 0xff, 0xff, 0xff, PC_SYS_USED
} // last 10
84 const PALETTEENTRY
* FASTCALL
COLOR_GetSystemPaletteTemplate(void)
86 return (const PALETTEENTRY
*)&COLOR_sysPalTemplate
;
89 BOOL STDCALL
NtGdiAnimatePalette(HPALETTE hPalette
, UINT uStartIndex
,
90 UINT uEntries
, CONST PPALETTEENTRY ppe
)
93 SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED
);
97 HPALETTE STDCALL
NtGdiCreateHalftonePalette(HDC hDC
)
102 WORD NumberOfEntries
;
103 PALETTEENTRY aEntries
[256];
106 Palette
.Version
= 0x300;
107 Palette
.NumberOfEntries
= 256;
108 if (NtGdiGetSystemPaletteEntries(hDC
, 0, 256, Palette
.aEntries
) == 0)
113 for (r
= 0; r
< 6; r
++)
114 for (g
= 0; g
< 6; g
++)
115 for (b
= 0; b
< 6; b
++)
117 i
= r
+ g
*6 + b
*36 + 10;
118 Palette
.aEntries
[i
].peRed
= r
* 51;
119 Palette
.aEntries
[i
].peGreen
= g
* 51;
120 Palette
.aEntries
[i
].peBlue
= b
* 51;
123 for (i
= 216; i
< 246; i
++)
125 int v
= (i
- 216) << 3;
126 Palette
.aEntries
[i
].peRed
= v
;
127 Palette
.aEntries
[i
].peGreen
= v
;
128 Palette
.aEntries
[i
].peBlue
= v
;
131 return NtGdiCreatePalette((LOGPALETTE
*)&Palette
);
134 HPALETTE STDCALL
NtGdiCreatePalette(CONST PLOGPALETTE palette
)
138 HPALETTE NewPalette
= PALETTE_AllocPalette(
140 palette
->palNumEntries
,
141 (PULONG
)palette
->palPalEntry
,
144 PalGDI
= (PPALGDI
) PALETTE_LockPalette(NewPalette
);
146 PALETTE_ValidateFlags(PalGDI
->IndexedColors
, PalGDI
->NumColors
);
147 PalGDI
->logicalToSystem
= NULL
;
149 PALETTE_UnlockPalette(NewPalette
);
154 BOOL STDCALL
NtGdiGetColorAdjustment(HDC hDC
,
155 LPCOLORADJUSTMENT ca
)
160 COLORREF STDCALL
NtGdiGetNearestColor(HDC hDC
,
163 COLORREF nearest
= CLR_INVALID
;
170 HPALETTE hpal
= dc
->w
.hPalette
;
171 palGDI
= (PPALGDI
) PALETTE_LockPalette(hpal
);
178 nearest
= COLOR_LookupNearestColor(palGDI
->IndexedColors
,
179 palGDI
->NumColors
, Color
);
180 PALETTE_UnlockPalette(hpal
);
187 UINT STDCALL
NtGdiGetNearestPaletteIndex(HPALETTE hpal
,
190 PPALGDI palGDI
= (PPALGDI
) PALETTE_LockPalette(hpal
);
195 /* Return closest match for the given RGB color */
196 index
= COLOR_PaletteLookupPixel((LPPALETTEENTRY
)palGDI
->IndexedColors
, palGDI
->NumColors
, NULL
, Color
, FALSE
);
197 PALETTE_UnlockPalette(hpal
);
203 UINT STDCALL
NtGdiGetPaletteEntries(HPALETTE hpal
,
211 palGDI
= (PPALGDI
) PALETTE_LockPalette(hpal
);
217 numEntries
= palGDI
->NumColors
;
218 if (numEntries
< StartIndex
+ Entries
)
220 Entries
= numEntries
- StartIndex
;
224 if (numEntries
<= StartIndex
)
226 PALETTE_UnlockPalette(hpal
);
229 memcpy(pe
, &palGDI
->IndexedColors
[StartIndex
], Entries
* sizeof(PALETTEENTRY
));
230 for (numEntries
= 0; numEntries
< Entries
; numEntries
++)
232 if (pe
[numEntries
].peFlags
& 0xF0)
234 pe
[numEntries
].peFlags
= 0;
239 PALETTE_UnlockPalette(hpal
);
243 UINT STDCALL
NtGdiGetSystemPaletteEntries(HDC hDC
,
251 if (!(dc = AccessUserObject(hdc))) return 0;
255 Entries = dc->GDIInfo->ulNumPalReg;
259 if (StartIndex >= dc->GDIInfo->ulNumPalReg)
265 if (StartIndex + Entries >= dc->GDIInfo->ulNumPalReg) Entries = dc->GDIInfo->ulNumPalReg - StartIndex;
267 for (i = 0; i < Entries; i++)
269 *(COLORREF*)(entries + i) = COLOR_GetSystemPaletteEntry(StartIndex + i);
273 // GDI_ReleaseObj(hdc);
275 // FIXME UNIMPLEMENTED;
279 UINT STDCALL
NtGdiGetSystemPaletteUse(HDC hDC
)
286 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.
288 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.
290 1= IF DRAWING TO A DEVICE
291 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
293 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the system palette.
295 2= IF DRAWING TO A MEMORY DC\BITMAP
296 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
298 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the dc palette.
300 UINT STDCALL
NtGdiRealizePalette(HDC hDC
)
302 PALOBJ
*palPtr
, *sysPtr
;
303 PPALGDI palGDI
, sysGDI
;
306 HPALETTE systemPalette
;
309 USHORT sysMode
, palMode
;
315 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
)dc
->Surface
);
316 systemPalette
= NtGdiGetStockObject((INT
)DEFAULT_PALETTE
);
317 palGDI
= PALETTE_LockPalette(dc
->w
.hPalette
);
318 palPtr
= (PALOBJ
*) palGDI
;
320 // Step 1: Create mapping of system palette\DC palette
322 realized
= PALETTE_SetMapping(palPtr
, 0, palGDI
->NumColors
,
323 (dc
->w
.hPalette
!= hPrimaryPalette
) ||
324 (dc
->w
.hPalette
== NtGdiGetStockObject(DEFAULT_PALETTE
)));
329 sysGDI
= PALETTE_LockPalette(systemPalette
);
330 sysPtr
= (PALOBJ
*) sysGDI
;
333 // The RealizePalette function modifies the palette for the device associated with the specified device context. If the
334 // device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device
335 // context is a display DC, the physical palette for that device is modified.
336 if(dc
->w
.flags
== DC_MEMORY
)
339 DbgPrint("win32k: realizepalette unimplemented step 2 for DC_MEMORY");
341 if(SurfGDI
->SetPalette
)
343 IntLockGDIDriver(SurfGDI
);
344 success
= SurfGDI
->SetPalette(dc
->PDev
, sysPtr
, 0, 0, sysGDI
->NumColors
);
345 IntUnLockGDIDriver(SurfGDI
);
349 // need to pass this to IntEngCreateXlate with palettes unlocked
350 sysMode
= sysGDI
->Mode
;
351 palMode
= palGDI
->Mode
;
352 PALETTE_UnlockPalette(systemPalette
);
353 PALETTE_UnlockPalette(dc
->w
.hPalette
);
355 // Step 3: Create the XLATEOBJ for device managed DCs
356 if(dc
->w
.flags
!= DC_MEMORY
)
359 palGDI
->logicalToSystem
= IntEngCreateXlate(sysGDI
->Mode
, palGDI
->Mode
, systemPalette
, dc
->w
.hPalette
);
367 BOOL STDCALL
NtGdiResizePalette(HPALETTE hpal
,
370 /* PALOBJ *palPtr = (PALOBJ*)AccessUserObject(hPal);
371 UINT cPrevEnt, prevVer;
372 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
373 XLATEOBJ *XlateObj = NULL;
375 if(!palPtr) return FALSE;
376 cPrevEnt = palPtr->logpalette->palNumEntries;
377 prevVer = palPtr->logpalette->palVersion;
378 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
379 size += sizeof(int*) + sizeof(GDIOBJHDR);
380 XlateObj = palPtr->logicalToSystem;
382 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
386 XLATEOBJ *NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
387 if(NewXlateObj == NULL)
389 ERR("Can not resize logicalToSystem -- out of memory!");
390 GDI_ReleaseObj( hPal );
393 palPtr->logicalToSystem = NewXlateObj;
396 if(cEntries > cPrevEnt)
398 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
399 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
400 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
402 palPtr->logpalette->palNumEntries = cEntries;
403 palPtr->logpalette->palVersion = prevVer;
404 // GDI_ReleaseObj( hPal );
411 * Select logical palette into device context.
412 * \param hDC handle to the device context
413 * \param hpal handle to the palette
414 * \param ForceBackground If this value is FALSE the logical palette will be copied to the device palette only when the applicatioon
415 * is in the foreground. If this value is TRUE then map the colors in the logical palette to the device
416 * palette colors in the best way.
417 * \return old palette
419 * \todo implement ForceBackground == TRUE
421 HPALETTE STDCALL
NtGdiSelectPalette(HDC hDC
,
423 BOOL ForceBackground
)
429 // FIXME: mark the palette as a [fore\back]ground pal
433 /* Check if this is a valid palette handle */
434 PalGDI
= PALETTE_LockPalette(hpal
);
437 PALETTE_UnlockPalette(hpal
);
438 oldPal
= dc
->w
.hPalette
;
439 dc
->w
.hPalette
= hpal
;
451 BOOL STDCALL
NtGdiSetColorAdjustment(HDC hDC
,
452 CONST LPCOLORADJUSTMENT ca
)
457 UINT STDCALL
NtGdiSetPaletteEntries(HPALETTE hpal
,
460 CONST LPPALETTEENTRY pe
)
465 palGDI
= PALETTE_LockPalette(hpal
);
466 if (!palGDI
) return 0;
468 numEntries
= palGDI
->NumColors
;
469 if (Start
>= numEntries
)
471 PALETTE_UnlockPalette(hpal
);
474 if (numEntries
< Start
+ Entries
)
476 Entries
= numEntries
- Start
;
478 memcpy(&palGDI
->IndexedColors
[Start
], pe
, Entries
* sizeof(PALETTEENTRY
));
479 PALETTE_ValidateFlags(palGDI
->IndexedColors
, palGDI
->NumColors
);
480 ExFreePool(palGDI
->logicalToSystem
);
481 palGDI
->logicalToSystem
= NULL
;
482 PALETTE_UnlockPalette(hpal
);
488 NtGdiSetSystemPaletteUse(HDC hDC
, UINT Usage
)
494 NtGdiUnrealizeObject(HGDIOBJ hgdiobj
)
500 NtGdiUpdateColors(HDC hDC
)
504 hWnd
= IntWindowFromDC(hDC
);
507 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
510 return NtUserRedrawWindow(hWnd
, NULL
, 0, RDW_INVALIDATE
);
513 INT STDCALL
COLOR_PaletteLookupPixel(PALETTEENTRY
*palPalEntry
, INT size
,
514 XLATEOBJ
*XlateObj
, COLORREF col
, BOOL skipReserved
)
516 int i
, best
= 0, diff
= 0x7fffffff;
519 for( i
= 0; i
< size
&& diff
; i
++ )
521 if(!(palPalEntry
[i
].peFlags
& PC_SYS_USED
) || (skipReserved
&& palPalEntry
[i
].peFlags
& PC_SYS_RESERVED
))
524 r
= palPalEntry
[i
].peRed
- GetRValue(col
);
525 g
= palPalEntry
[i
].peGreen
- GetGValue(col
);
526 b
= palPalEntry
[i
].peBlue
- GetBValue(col
);
530 if( r
< diff
) { best
= i
; diff
= r
; }
533 if (XlateObj
== NULL
)
536 return (XlateObj
->pulXlate
) ? (INT
)XlateObj
->pulXlate
[best
] : best
;
539 COLORREF STDCALL
COLOR_LookupNearestColor( PALETTEENTRY
* palPalEntry
, int size
, COLORREF color
)
544 index
= COLOR_PaletteLookupPixel(palPalEntry
, size
, NULL
, color
, FALSE
);
546 palPalEntry
[index
].peRed
,
547 palPalEntry
[index
].peGreen
,
548 palPalEntry
[index
].peBlue
);
550 unsigned char spec_type
= color
>> 24;
552 PALETTEENTRY
*COLOR_sysPal
= (PALETTEENTRY
*)ReturnSystemPalette();
554 // we need logical palette for PALETTERGB and PALETTEINDEX colorrefs
556 if( spec_type
== 2 ) /* PALETTERGB */
557 color
= *(COLORREF
*)(palPalEntry
+ COLOR_PaletteLookupPixel(palPalEntry
,size
,NULL
,color
,FALSE
));
559 else if( spec_type
== 1 ) /* PALETTEINDEX */
561 if( (i
= color
& 0x0000ffff) >= size
)
563 DbgPrint("RGB(%lx) : idx %d is out of bounds, assuming NULL\n", color
, i
);
564 color
= *(COLORREF
*)palPalEntry
;
566 else color
= *(COLORREF
*)(palPalEntry
+ i
);
570 return (0x00ffffff & *(COLORREF
*)(COLOR_sysPal
+ COLOR_PaletteLookupPixel(COLOR_sysPal
, 256, NULL
, color
, FALSE
)));
574 int STDCALL
COLOR_PaletteLookupExactIndex( PALETTEENTRY
* palPalEntry
, int size
,
578 BYTE r
= GetRValue(col
), g
= GetGValue(col
), b
= GetBValue(col
);
579 for( i
= 0; i
< size
; i
++ )
581 if( palPalEntry
[i
].peFlags
& PC_SYS_USED
) /* skips gap */
582 if(palPalEntry
[i
].peRed
== r
&& palPalEntry
[i
].peGreen
== g
&& palPalEntry
[i
].peBlue
== b
) return i
;