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.
26 // FIXME: Use PXLATEOBJ logicalToSystem instead of int *mapping
28 int COLOR_gapStart
= 256;
29 int COLOR_gapEnd
= -1;
30 int COLOR_gapFilled
= 0;
34 static HPALETTE hPrimaryPalette
= 0; // used for WM_PALETTECHANGED
36 //static HPALETTE hLastRealizedPalette = 0; // UnrealizeObject() needs it
39 static UINT SystemPaletteUse
= SYSPAL_NOSTATIC
; /* the program need save the palate and restore it */
41 const PALETTEENTRY COLOR_sysPalTemplate
[NB_RESERVED_COLORS
] =
43 // first 10 entries in the system palette
44 // red green blue flags
45 { 0x00, 0x00, 0x00, PC_SYS_USED
},
46 { 0x80, 0x00, 0x00, PC_SYS_USED
},
47 { 0x00, 0x80, 0x00, PC_SYS_USED
},
48 { 0x80, 0x80, 0x00, PC_SYS_USED
},
49 { 0x00, 0x00, 0x80, PC_SYS_USED
},
50 { 0x80, 0x00, 0x80, PC_SYS_USED
},
51 { 0x00, 0x80, 0x80, PC_SYS_USED
},
52 { 0xc0, 0xc0, 0xc0, PC_SYS_USED
},
53 { 0xc0, 0xdc, 0xc0, PC_SYS_USED
},
54 { 0xd4, 0xd0, 0xc7, PC_SYS_USED
},
56 // ... c_min/2 dynamic colorcells
57 // ... gap (for sparse palettes)
58 // ... c_min/2 dynamic colorcells
60 { 0xff, 0xfb, 0xf0, PC_SYS_USED
},
61 { 0x3a, 0x6e, 0xa5, PC_SYS_USED
},
62 { 0x80, 0x80, 0x80, PC_SYS_USED
},
63 { 0xff, 0x00, 0x00, PC_SYS_USED
},
64 { 0x00, 0xff, 0x00, PC_SYS_USED
},
65 { 0xff, 0xff, 0x00, PC_SYS_USED
},
66 { 0x00, 0x00, 0xff, PC_SYS_USED
},
67 { 0xff, 0x00, 0xff, PC_SYS_USED
},
68 { 0x00, 0xff, 0xff, PC_SYS_USED
},
69 { 0xff, 0xff, 0xff, PC_SYS_USED
} // last 10
72 const PALETTEENTRY
* FASTCALL
COLOR_GetSystemPaletteTemplate(void)
74 return (const PALETTEENTRY
*)&COLOR_sysPalTemplate
;
77 BOOL STDCALL
NtGdiAnimatePalette(HPALETTE hPal
, UINT StartIndex
,
78 UINT NumEntries
, CONST PPALETTEENTRY PaletteColors
)
80 if( hPal
!= NtGdiGetStockObject(DEFAULT_PALETTE
) )
87 const PALETTEENTRY
*pptr
= PaletteColors
;
89 palPtr
= (PPALGDI
)PALETTE_LockPalette(hPal
);
90 if (!palPtr
) return FALSE
;
92 pal_entries
= palPtr
->NumColors
;
93 if (StartIndex
>= pal_entries
)
95 PALETTE_UnlockPalette(palPtr
);
98 if (StartIndex
+NumEntries
> pal_entries
) NumEntries
= pal_entries
- StartIndex
;
100 for (NumEntries
+= StartIndex
; StartIndex
< NumEntries
; StartIndex
++, pptr
++) {
101 /* According to MSDN, only animate PC_RESERVED colours */
102 if (palPtr
->IndexedColors
[StartIndex
].peFlags
& PC_RESERVED
) {
103 memcpy( &palPtr
->IndexedColors
[StartIndex
], pptr
,
104 sizeof(PALETTEENTRY
) );
105 PALETTE_ValidateFlags(&palPtr
->IndexedColors
[StartIndex
], 1);
109 PALETTE_UnlockPalette(palPtr
);
111 /* Immediately apply the new palette if current window uses it */
112 Wnd
= UserGetDesktopWindow();
113 hDC
= (HDC
)UserGetWindowDC(Wnd
);
117 if (dc
->w
.hPalette
== hPal
)
120 NtGdiRealizePalette(hDC
);
125 UserReleaseDC(Wnd
,hDC
, FALSE
);
130 HPALETTE STDCALL
NtGdiCreateHalftonePalette(HDC hDC
)
135 WORD NumberOfEntries
;
136 PALETTEENTRY aEntries
[256];
139 Palette
.Version
= 0x300;
140 Palette
.NumberOfEntries
= 256;
141 if (NtGdiGetSystemPaletteEntries(hDC
, 0, 256, Palette
.aEntries
) == 0)
146 for (r
= 0; r
< 6; r
++)
147 for (g
= 0; g
< 6; g
++)
148 for (b
= 0; b
< 6; b
++)
150 i
= r
+ g
*6 + b
*36 + 10;
151 Palette
.aEntries
[i
].peRed
= r
* 51;
152 Palette
.aEntries
[i
].peGreen
= g
* 51;
153 Palette
.aEntries
[i
].peBlue
= b
* 51;
156 for (i
= 216; i
< 246; i
++)
158 int v
= (i
- 216) << 3;
159 Palette
.aEntries
[i
].peRed
= v
;
160 Palette
.aEntries
[i
].peGreen
= v
;
161 Palette
.aEntries
[i
].peBlue
= v
;
164 return NtGdiCreatePalette((LOGPALETTE
*)&Palette
);
167 HPALETTE STDCALL
NtGdiCreatePalette(CONST PLOGPALETTE palette
)
171 HPALETTE NewPalette
= PALETTE_AllocPalette(
173 palette
->palNumEntries
,
174 (PULONG
)palette
->palPalEntry
,
177 PalGDI
= (PPALGDI
) PALETTE_LockPalette(NewPalette
);
178 /* FIXME - Handle PalGDI == NULL!!!! */
180 PALETTE_ValidateFlags(PalGDI
->IndexedColors
, PalGDI
->NumColors
);
181 PalGDI
->logicalToSystem
= NULL
;
183 PALETTE_UnlockPalette(PalGDI
);
188 BOOL STDCALL
NtGdiGetColorAdjustment(HDC hDC
,
189 LPCOLORADJUSTMENT ca
)
195 unsigned short GetNumberOfBits(unsigned int dwMask
)
197 unsigned short wBits
;
198 for (wBits
= 0; dwMask
; dwMask
= dwMask
& (dwMask
- 1))
203 COLORREF STDCALL
NtGdiGetNearestColor(HDC hDC
, COLORREF Color
)
205 COLORREF nearest
= CLR_INVALID
;
208 LONG RBits
, GBits
, BBits
;
213 HPALETTE hpal
= dc
->w
.hPalette
;
214 palGDI
= (PPALGDI
) PALETTE_LockPalette(hpal
);
221 switch (palGDI
->Mode
)
224 nearest
= COLOR_LookupNearestColor(palGDI
->IndexedColors
,
225 palGDI
->NumColors
, Color
);
232 RBits
= 8 - GetNumberOfBits(palGDI
->RedMask
);
233 GBits
= 8 - GetNumberOfBits(palGDI
->GreenMask
);
234 BBits
= 8 - GetNumberOfBits(palGDI
->BlueMask
);
236 (GetRValue(Color
) >> RBits
) << RBits
,
237 (GetGValue(Color
) >> GBits
) << GBits
,
238 (GetBValue(Color
) >> BBits
) << BBits
);
241 PALETTE_UnlockPalette(palGDI
);
248 UINT STDCALL
NtGdiGetNearestPaletteIndex(HPALETTE hpal
,
251 PPALGDI palGDI
= (PPALGDI
) PALETTE_LockPalette(hpal
);
256 /* Return closest match for the given RGB color */
257 index
= COLOR_PaletteLookupPixel(palGDI
->IndexedColors
, palGDI
->NumColors
, NULL
, Color
, FALSE
);
258 PALETTE_UnlockPalette(palGDI
);
264 UINT STDCALL
NtGdiGetPaletteEntries(HPALETTE hpal
,
272 palGDI
= (PPALGDI
) PALETTE_LockPalette(hpal
);
278 numEntries
= palGDI
->NumColors
;
279 if (numEntries
< StartIndex
+ Entries
)
281 Entries
= numEntries
- StartIndex
;
285 if (numEntries
<= StartIndex
)
287 PALETTE_UnlockPalette(palGDI
);
290 memcpy(pe
, palGDI
->IndexedColors
+ StartIndex
, Entries
* sizeof(PALETTEENTRY
));
291 for (numEntries
= 0; numEntries
< Entries
; numEntries
++)
293 if (pe
[numEntries
].peFlags
& 0xF0)
295 pe
[numEntries
].peFlags
= 0;
300 PALETTE_UnlockPalette(palGDI
);
304 UINT STDCALL
NtGdiGetSystemPaletteEntries(HDC hDC
,
312 if (!(dc = AccessUserObject(hdc))) return 0;
316 Entries = dc->GDIInfo->ulNumPalReg;
320 if (StartIndex >= dc->GDIInfo->ulNumPalReg)
326 if (StartIndex + Entries >= dc->GDIInfo->ulNumPalReg) Entries = dc->GDIInfo->ulNumPalReg - StartIndex;
328 for (i = 0; i < Entries; i++)
330 *(COLORREF*)(entries + i) = COLOR_GetSystemPaletteEntry(StartIndex + i);
334 // GDI_ReleaseObj(hdc);
336 // FIXME UNIMPLEMENTED;
340 UINT STDCALL
NtGdiGetSystemPaletteUse(HDC hDC
)
342 return SystemPaletteUse
;
346 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.
348 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.
350 1= IF DRAWING TO A DEVICE
351 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
353 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the system palette.
355 2= IF DRAWING TO A MEMORY DC\BITMAP
356 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
358 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the dc palette.
360 UINT STDCALL
NtGdiRealizePalette(HDC hDC
)
363 * This function doesn't do any real work now and there's plenty
364 * of bugd in it (calling SetPalette for high/true-color modes,
365 * using DEFAULT_PALETTE instead of the device palette, ...).
368 PALOBJ
*palPtr
, *sysPtr
;
369 PPALGDI palGDI
, sysGDI
;
372 HPALETTE systemPalette
;
374 USHORT sysMode
, palMode
;
380 systemPalette
= NtGdiGetStockObject((INT
)DEFAULT_PALETTE
);
381 palGDI
= PALETTE_LockPalette(dc
->w
.hPalette
);
382 palPtr
= (PALOBJ
*) palGDI
;
383 /* FIXME - Handle palGDI == NULL!!!! */
385 // Step 1: Create mapping of system palette\DC palette
387 realized
= PALETTE_SetMapping(palPtr
, 0, palGDI
->NumColors
,
388 (dc
->w
.hPalette
!= hPrimaryPalette
) ||
389 (dc
->w
.hPalette
== NtGdiGetStockObject(DEFAULT_PALETTE
)));
394 sysGDI
= PALETTE_LockPalette(systemPalette
);
395 sysPtr
= (PALOBJ
*) sysGDI
;
396 /* FIXME - Handle sysGDI == NULL!!!!! */
399 // The RealizePalette function modifies the palette for the device associated with the specified device context. If the
400 // device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device
401 // context is a display DC, the physical palette for that device is modified.
402 if(dc
->w
.flags
== DC_MEMORY
)
405 DbgPrint("win32k: realizepalette unimplemented step 2 for DC_MEMORY");
407 if( ((GDIDEVICE
*)dc
->GDIDevice
)->DriverFunctions
.SetPalette
)
409 ASSERT(palGDI
->NumColors
<= 256);
410 success
= ((GDIDEVICE
*)dc
->GDIDevice
)->DriverFunctions
.SetPalette(
411 dc
->PDev
, palPtr
, 0, 0, palGDI
->NumColors
);
415 // need to pass this to IntEngCreateXlate with palettes unlocked
416 sysMode
= sysGDI
->Mode
;
417 palMode
= palGDI
->Mode
;
418 PALETTE_UnlockPalette(sysGDI
);
419 PALETTE_UnlockPalette(palGDI
);
421 // Step 3: Create the XLATEOBJ for device managed DCs
422 if(dc
->w
.flags
!= DC_MEMORY
)
425 palGDI
->logicalToSystem
= IntEngCreateXlate(sysMode
, palMode
, systemPalette
, dc
->w
.hPalette
);
433 BOOL STDCALL
NtGdiResizePalette(HPALETTE hpal
,
436 /* PALOBJ *palPtr = (PALOBJ*)AccessUserObject(hPal);
437 UINT cPrevEnt, prevVer;
438 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
439 XLATEOBJ *XlateObj = NULL;
441 if(!palPtr) return FALSE;
442 cPrevEnt = palPtr->logpalette->palNumEntries;
443 prevVer = palPtr->logpalette->palVersion;
444 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
445 size += sizeof(int*) + sizeof(GDIOBJHDR);
446 XlateObj = palPtr->logicalToSystem;
448 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
452 XLATEOBJ *NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
453 if(NewXlateObj == NULL)
455 ERR("Can not resize logicalToSystem -- out of memory!");
456 GDI_ReleaseObj( hPal );
459 palPtr->logicalToSystem = NewXlateObj;
462 if(cEntries > cPrevEnt)
464 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
465 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
466 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
468 palPtr->logpalette->palNumEntries = cEntries;
469 palPtr->logpalette->palVersion = prevVer;
470 // GDI_ReleaseObj( hPal );
478 * Select logical palette into device context.
479 * \param hDC handle to the device context
480 * \param hpal handle to the palette
481 * \param ForceBackground If this value is FALSE the logical palette will be copied to the device palette only when the applicatioon
482 * is in the foreground. If this value is TRUE then map the colors in the logical palette to the device
483 * palette colors in the best way.
484 * \return old palette
486 * \todo implement ForceBackground == TRUE
488 HPALETTE STDCALL
NtGdiSelectPalette(HDC hDC
,
490 BOOL ForceBackground
)
493 HPALETTE oldPal
= NULL
;
496 // FIXME: mark the palette as a [fore\back]ground pal
500 /* Check if this is a valid palette handle */
501 PalGDI
= PALETTE_LockPalette(hpal
);
504 /* Is this a valid palette for this depth? */
505 if ((dc
->w
.bitsPerPixel
<= 8 && PAL_INDEXED
== PalGDI
->Mode
)
506 || (8 < dc
->w
.bitsPerPixel
&& PAL_INDEXED
!= PalGDI
->Mode
))
508 PALETTE_UnlockPalette(PalGDI
);
509 oldPal
= dc
->w
.hPalette
;
510 dc
->w
.hPalette
= hpal
;
514 PALETTE_UnlockPalette(PalGDI
);
528 BOOL STDCALL
NtGdiSetColorAdjustment(HDC hDC
,
529 CONST LPCOLORADJUSTMENT ca
)
535 UINT STDCALL
NtGdiSetPaletteEntries(HPALETTE hpal
,
538 CONST LPPALETTEENTRY pe
)
543 palGDI
= PALETTE_LockPalette(hpal
);
544 if (!palGDI
) return 0;
546 numEntries
= palGDI
->NumColors
;
547 if (Start
>= numEntries
)
549 PALETTE_UnlockPalette(palGDI
);
552 if (numEntries
< Start
+ Entries
)
554 Entries
= numEntries
- Start
;
556 memcpy(palGDI
->IndexedColors
+ Start
, pe
, Entries
* sizeof(PALETTEENTRY
));
557 PALETTE_ValidateFlags(palGDI
->IndexedColors
, palGDI
->NumColors
);
558 ExFreePool(palGDI
->logicalToSystem
);
559 palGDI
->logicalToSystem
= NULL
;
560 PALETTE_UnlockPalette(palGDI
);
566 NtGdiSetSystemPaletteUse(HDC hDC
, UINT Usage
)
568 UINT old
= SystemPaletteUse
;
570 /* Device doesn't support colour palettes */
571 if (!(NtGdiGetDeviceCaps(hDC
, RASTERCAPS
) & RC_PALETTE
)) {
577 case SYSPAL_NOSTATIC
:
578 case SYSPAL_NOSTATIC256
:
580 SystemPaletteUse
= Usage
;
592 Win 2k Graphics API, Black Book. by coriolis.com
593 Page 62, Note that Steps 3, 5, and 6 are not required for Windows NT(tm)
594 and Windows 2000(tm).
596 Step 5. UnrealizeObject(hTrackBrush);
599 NtGdiUnrealizeObject(HGDIOBJ hgdiobj
)
606 ptr
= GDIOBJ_LockObj(hgdiobj
, GDI_OBJECT_TYPE_DONTCARE
);
609 SetLastWin32Error(ERROR_INVALID_HANDLE
);
612 objectType
= GDIOBJ_GetObjectType(hgdiobj
);
617 "Windows 2000/XP: If hgdiobj is a brush, UnrealizeObject does nothing,
618 and the function returns TRUE. Use SetBrushOrgEx to set the origin of
621 case GDI_OBJECT_TYPE_BRUSH
:
623 DPRINT("GDI_OBJECT_TYPE_BRUSH\n");
628 DPRINT1("Magic 0x%08x not implemented\n", objectType
);
632 GDIOBJ_UnlockObjByPtr(ptr
);
637 NtGdiUpdateColors(HDC hDC
)
640 BOOL calledFromUser
, ret
;
641 USER_REFERENCE_ENTRY Ref
;
643 calledFromUser
= UserIsEntered();
645 if (!calledFromUser
){
646 UserEnterExclusive();
649 Wnd
= UserGetWindowObject(IntWindowFromDC(hDC
));
652 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
654 if (!calledFromUser
){
661 UserRefObjectCo(Wnd
, &Ref
);
662 ret
= co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_INVALIDATE
);
663 UserDerefObjectCo(Wnd
);
665 if (!calledFromUser
){
672 INT STDCALL
COLOR_PaletteLookupPixel(PALETTEENTRY
*palPalEntry
, INT size
,
673 XLATEOBJ
*XlateObj
, COLORREF col
, BOOL skipReserved
)
675 int i
, best
= 0, diff
= 0x7fffffff;
678 for( i
= 0; i
< size
&& diff
; i
++ )
681 if(!(palPalEntry
[i
].peFlags
& PC_SYS_USED
) || (skipReserved
&& palPalEntry
[i
].peFlags
& PC_SYS_RESERVED
))
685 r
= abs((SHORT
)palPalEntry
[i
].peRed
- GetRValue(col
));
686 g
= abs((SHORT
)palPalEntry
[i
].peGreen
- GetGValue(col
));
687 b
= abs((SHORT
)palPalEntry
[i
].peBlue
- GetBValue(col
));
691 if( r
< diff
) { best
= i
; diff
= r
; }
694 if (XlateObj
== NULL
)
697 return (XlateObj
->pulXlate
) ? (INT
)XlateObj
->pulXlate
[best
] : best
;
700 COLORREF STDCALL
COLOR_LookupNearestColor( PALETTEENTRY
* palPalEntry
, int size
, COLORREF color
)
704 index
= COLOR_PaletteLookupPixel(palPalEntry
, size
, NULL
, color
, FALSE
);
706 palPalEntry
[index
].peRed
,
707 palPalEntry
[index
].peGreen
,
708 palPalEntry
[index
].peBlue
);
711 int STDCALL
COLOR_PaletteLookupExactIndex( PALETTEENTRY
* palPalEntry
, int size
,
715 BYTE r
= GetRValue(col
), g
= GetGValue(col
), b
= GetBValue(col
);
716 for( i
= 0; i
< size
; i
++ )
718 if( palPalEntry
[i
].peFlags
& PC_SYS_USED
) /* skips gap */
719 if(palPalEntry
[i
].peRed
== r
&& palPalEntry
[i
].peGreen
== g
&& palPalEntry
[i
].peBlue
== b
) return i
;