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.
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 NtGdiGetSysColor(int nIndex)
80 const PALETTEENTRY *p = COLOR_sysPalTemplate + (nIndex * sizeof(PALETTEENTRY));
81 return RGB(p->peRed, p->peGreen, p->peBlue);
84 HPEN STDCALL NtGdiGetSysColorPen(int nIndex)
87 memcpy(&Col, COLOR_sysPalTemplate + nIndex, sizeof(COLORREF));
88 return(NtGdiCreatePen(PS_SOLID, 1, Col));
91 HBRUSH STDCALL NtGdiGetSysColorBrush(int nIndex)
94 memcpy(&Col, COLOR_sysPalTemplate + nIndex, sizeof(COLORREF));
95 return(NtGdiCreateSolidBrush(Col));
100 const PALETTEENTRY* FASTCALL COLOR_GetSystemPaletteTemplate(void)
102 return (const PALETTEENTRY*)&COLOR_sysPalTemplate;
105 BOOL STDCALL NtGdiAnimatePalette(HPALETTE hpal,
108 CONST PPALETTEENTRY ppe)
111 if( hPal != NtGdiGetStockObject(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 NtGdiCreateHalftonePalette(HDC hDC)
137 WORD NumberOfEntries;
138 PALETTEENTRY aEntries[256];
141 Palette.Version = 0x300;
142 Palette.NumberOfEntries = 256;
143 NtGdiGetSystemPaletteEntries(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 NtGdiCreatePalette((LOGPALETTE *)&Palette);
166 HPALETTE STDCALL NtGdiCreatePalette(CONST PLOGPALETTE palette)
170 HPALETTE NewPalette = PALETTE_AllocPalette(
172 palette->palNumEntries,
173 (PULONG)palette->palPalEntry,
177 PalObj = (PPALOBJ) PALETTE_LockPalette(NewPalette);
179 size = sizeof(LOGPALETTE) + (palette->palNumEntries * sizeof(PALETTEENTRY));
180 PalObj->logpalette = ExAllocatePool(NonPagedPool, size);
181 memcpy(PalObj->logpalette, palette, size);
182 PALETTE_ValidateFlags(PalObj->logpalette->palPalEntry, PalObj->logpalette->palNumEntries);
183 PalObj->logicalToSystem = NULL;
185 PALETTE_UnlockPalette(NewPalette);
190 BOOL STDCALL NtGdiGetColorAdjustment(HDC hDC,
191 LPCOLORADJUSTMENT ca)
196 COLORREF STDCALL NtGdiGetNearestColor(HDC hDC,
199 COLORREF nearest = CLR_INVALID;
206 HPALETTE hpal = (dc->w.hPalette) ? dc->w.hPalette : NtGdiGetStockObject(DEFAULT_PALETTE);
207 palObj = (PPALOBJ) PALETTE_LockPalette(hpal);
214 nearest = COLOR_LookupNearestColor(palObj->logpalette->palPalEntry,
215 palObj->logpalette->palNumEntries, Color);
216 PALETTE_UnlockPalette(hpal);
223 UINT STDCALL NtGdiGetNearestPaletteIndex(HPALETTE hpal,
226 PPALOBJ palObj = (PPALOBJ) PALETTE_LockPalette(hpal);
231 /* Return closest match for the given RGB color */
232 index = COLOR_PaletteLookupPixel(palObj->logpalette->palPalEntry, palObj->logpalette->palNumEntries, NULL, Color, FALSE);
233 PALETTE_UnlockPalette(hpal);
239 UINT STDCALL NtGdiGetPaletteEntries(HPALETTE hpal,
247 palPtr = (PPALOBJ) PALETTE_LockPalette(hpal);
253 numEntries = palPtr->logpalette->palNumEntries;
254 if (numEntries < StartIndex + Entries)
256 Entries = numEntries - StartIndex;
260 if (numEntries <= StartIndex)
262 PALETTE_UnlockPalette(hpal);
265 memcpy(pe, &palPtr->logpalette->palPalEntry[StartIndex], Entries * sizeof(PALETTEENTRY));
266 for (numEntries = 0; numEntries < Entries; numEntries++)
268 if (pe[numEntries].peFlags & 0xF0)
270 pe[numEntries].peFlags = 0;
275 PALETTE_UnlockPalette(hpal);
279 UINT STDCALL NtGdiGetSystemPaletteEntries(HDC hDC,
287 if (!(dc = AccessUserObject(hdc))) return 0;
291 Entries = dc->GDIInfo->ulNumPalReg;
295 if (StartIndex >= dc->GDIInfo->ulNumPalReg)
301 if (StartIndex + Entries >= dc->GDIInfo->ulNumPalReg) Entries = dc->GDIInfo->ulNumPalReg - StartIndex;
303 for (i = 0; i < Entries; i++)
305 *(COLORREF*)(entries + i) = COLOR_GetSystemPaletteEntry(StartIndex + i);
309 // GDI_ReleaseObj(hdc);
311 // FIXME UNIMPLEMENTED;
315 UINT STDCALL NtGdiGetSystemPaletteUse(HDC hDC)
322 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.
324 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.
326 1= IF DRAWING TO A DEVICE
327 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
329 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the system palette.
331 2= IF DRAWING TO A MEMORY DC\BITMAP
332 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
334 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the dc palette.
336 UINT STDCALL NtGdiRealizePalette(HDC hDC)
338 PPALOBJ palPtr, sysPtr;
339 PPALGDI palGDI, sysGDI;
342 HPALETTE systemPalette;
345 USHORT sysMode, palMode;
351 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG)dc->Surface);
352 systemPalette = NtGdiGetStockObject((INT)DEFAULT_PALETTE);
353 palGDI = PALETTE_LockPalette(dc->w.hPalette);
354 palPtr = (PPALOBJ) palGDI;
355 sysGDI = PALETTE_LockPalette(systemPalette);
356 sysPtr = (PPALOBJ) sysGDI;
358 // Step 1: Create mapping of system palette\DC palette
359 realized = PALETTE_SetMapping(palPtr, 0, palPtr->logpalette->palNumEntries,
360 (dc->w.hPalette != hPrimaryPalette) ||
361 (dc->w.hPalette == NtGdiGetStockObject(DEFAULT_PALETTE)));
364 // The RealizePalette function modifies the palette for the device associated with the specified device context. If the
365 // device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device
366 // context is a display DC, the physical palette for that device is modified.
367 if(dc->w.flags == DC_MEMORY)
370 DbgPrint("win32k: realizepalette unimplemented step 2 for DC_MEMORY");
372 if(SurfGDI->SetPalette)
374 success = SurfGDI->SetPalette(dc->PDev, sysPtr, 0, 0, sysPtr->logpalette->palNumEntries);
378 // need to pass this to IntEngCreateXlate with palettes unlocked
379 sysMode = sysGDI->Mode;
380 palMode = palGDI->Mode;
381 PALETTE_UnlockPalette(systemPalette);
382 PALETTE_UnlockPalette(dc->w.hPalette);
384 // Step 3: Create the XLATEOBJ for device managed DCs
385 if(dc->w.flags != DC_MEMORY)
388 palPtr->logicalToSystem = IntEngCreateXlate(sysGDI->Mode, palGDI->Mode, systemPalette, dc->w.hPalette);
396 BOOL STDCALL NtGdiResizePalette(HPALETTE hpal,
399 /* PPALOBJ palPtr = (PPALOBJ)AccessUserObject(hPal);
400 UINT cPrevEnt, prevVer;
401 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
402 PXLATEOBJ XlateObj = NULL;
404 if(!palPtr) return FALSE;
405 cPrevEnt = palPtr->logpalette->palNumEntries;
406 prevVer = palPtr->logpalette->palVersion;
407 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
408 size += sizeof(int*) + sizeof(GDIOBJHDR);
409 XlateObj = palPtr->logicalToSystem;
411 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
415 PXLATEOBJ NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
416 if(NewXlateObj == NULL)
418 ERR("Can not resize logicalToSystem -- out of memory!");
419 GDI_ReleaseObj( hPal );
422 palPtr->logicalToSystem = NewXlateObj;
425 if(cEntries > cPrevEnt)
427 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
428 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
429 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
431 palPtr->logpalette->palNumEntries = cEntries;
432 palPtr->logpalette->palVersion = prevVer;
433 // GDI_ReleaseObj( hPal );
440 * Select logical palette into device context.
441 * \param hDC handle to the device context
442 * \param hpal handle to the palette
443 * \param ForceBackground If this value is FALSE the logical palette will be copied to the device palette only when the applicatioon
444 * is in the foreground. If this value is TRUE then map the colors in the logical palette to the device
445 * palette colors in the best way.
446 * \return old palette
448 * \todo implement ForceBackground == TRUE
450 HPALETTE STDCALL NtGdiSelectPalette(HDC hDC,
452 BOOL ForceBackground)
458 // FIXME: mark the palette as a [fore\back]ground pal
462 /* Check if this is a valid palette handle */
463 PalGDI = PALETTE_LockPalette(hpal);
466 PALETTE_UnlockPalette(hpal);
467 oldPal = dc->w.hPalette;
468 dc->w.hPalette = hpal;
480 BOOL STDCALL NtGdiSetColorAdjustment(HDC hDC,
481 CONST LPCOLORADJUSTMENT ca)
486 UINT STDCALL NtGdiSetPaletteEntries(HPALETTE hpal,
489 CONST LPPALETTEENTRY pe)
494 palPtr = (PPALOBJ)PALETTE_LockPalette(hpal);
495 if (!palPtr) return 0;
497 numEntries = palPtr->logpalette->palNumEntries;
498 if (Start >= numEntries)
500 PALETTE_UnlockPalette(hpal);
503 if (numEntries < Start + Entries)
505 Entries = numEntries - Start;
507 memcpy(&palPtr->logpalette->palPalEntry[Start], pe, Entries * sizeof(PALETTEENTRY));
508 PALETTE_ValidateFlags(palPtr->logpalette->palPalEntry, palPtr->logpalette->palNumEntries);
509 ExFreePool(palPtr->logicalToSystem);
510 palPtr->logicalToSystem = NULL;
511 PALETTE_UnlockPalette(hpal);
516 UINT STDCALL NtGdiSetSystemPaletteUse(HDC hDC,
522 BOOL STDCALL NtGdiUnrealizeObject(HGDIOBJ hgdiobj)
527 BOOL STDCALL NtGdiUpdateColors(HDC hDC)
533 if (!(dc = AccessUserObject(hDC))) return 0;
534 size = dc->GDIInfo->ulNumPalReg;
535 // GDI_ReleaseObj( hDC );
537 if (Callout.WindowFromDC)
539 hWnd = Callout.WindowFromDC( hDC );
541 // Docs say that we have to remap current drawable pixel by pixel
542 // but it would take forever given the speed of XGet/PutPixel.
543 if (hWnd && size) Callout.RedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE );
545 // FIXME UNIMPLEMENTED
549 INT STDCALL COLOR_PaletteLookupPixel(PALETTEENTRY *palPalEntry, INT size,
550 PXLATEOBJ XlateObj, COLORREF col, BOOL skipReserved)
552 int i, best = 0, diff = 0x7fffffff;
555 for( i = 0; i < size && diff ; i++ )
557 if(!(palPalEntry[i].peFlags & PC_SYS_USED) || (skipReserved && palPalEntry[i].peFlags & PC_SYS_RESERVED))
560 r = palPalEntry[i].peRed - GetRValue(col);
561 g = palPalEntry[i].peGreen - GetGValue(col);
562 b = palPalEntry[i].peBlue - GetBValue(col);
566 if( r < diff ) { best = i; diff = r; }
568 return (XlateObj->pulXlate) ? (INT)XlateObj->pulXlate[best] : best;
571 COLORREF STDCALL COLOR_LookupNearestColor( PALETTEENTRY* palPalEntry, int size, COLORREF color )
573 unsigned char spec_type = color >> 24;
575 PALETTEENTRY *COLOR_sysPal = (PALETTEENTRY*)ReturnSystemPalette();
577 // we need logical palette for PALETTERGB and PALETTEINDEX colorrefs
579 if( spec_type == 2 ) /* PALETTERGB */
580 color = *(COLORREF*)(palPalEntry + COLOR_PaletteLookupPixel(palPalEntry,size,NULL,color,FALSE));
582 else if( spec_type == 1 ) /* PALETTEINDEX */
584 if( (i = color & 0x0000ffff) >= size )
586 DbgPrint("RGB(%lx) : idx %d is out of bounds, assuming NULL\n", color, i);
587 color = *(COLORREF*)palPalEntry;
589 else color = *(COLORREF*)(palPalEntry + i);
593 return (0x00ffffff & *(COLORREF*)(COLOR_sysPal + COLOR_PaletteLookupPixel(COLOR_sysPal, 256, NULL, color, FALSE)));
596 int STDCALL COLOR_PaletteLookupExactIndex( PALETTEENTRY* palPalEntry, int size,
600 BYTE r = GetRValue(col), g = GetGValue(col), b = GetBValue(col);
601 for( i = 0; i < size; i++ )
603 if( palPalEntry[i].peFlags & PC_SYS_USED ) /* skips gap */
604 if(palPalEntry[i].peRed == r && palPalEntry[i].peGreen == g && palPalEntry[i].peBlue == b) return i;