WIN32K code cleanup.
[reactos.git] / reactos / subsys / win32k / objects / color.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id: color.c,v 1.17 2003/05/18 17:16:17 ea Exp $ */
20
21 // FIXME: Use PXLATEOBJ logicalToSystem instead of int *mapping
22
23 #undef WIN32_LEAN_AND_MEAN
24 #include <windows.h>
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>
35
36 #define NDEBUG
37 #include <win32k/debug1.h>
38
39 int COLOR_gapStart = 256;
40 int COLOR_gapEnd = -1;
41 int COLOR_gapFilled = 0;
42 int COLOR_max = 256;
43
44 static HPALETTE hPrimaryPalette = 0; // used for WM_PALETTECHANGED
45 static HPALETTE hLastRealizedPalette = 0; // UnrealizeObject() needs it
46
47 const PALETTEENTRY COLOR_sysPalTemplate[NB_RESERVED_COLORS] =
48 {
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 },
61
62 // ... c_min/2 dynamic colorcells
63 // ... gap (for sparse palettes)
64 // ... c_min/2 dynamic colorcells
65
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
76 };
77
78 ULONG FASTCALL W32kGetSysColor(int nIndex)
79 {
80 PALETTEENTRY *p = COLOR_sysPalTemplate + (nIndex * sizeof(PALETTEENTRY));
81 return RGB(p->peRed, p->peGreen, p->peBlue);
82 }
83
84 HPEN STDCALL W32kGetSysColorPen(int nIndex)
85 {
86 COLORREF Col;
87 memcpy(&Col, COLOR_sysPalTemplate + nIndex, sizeof(COLORREF));
88 return(W32kCreatePen(PS_SOLID, 1, Col));
89 }
90
91 HBRUSH STDCALL W32kGetSysColorBrush(int nIndex)
92 {
93 COLORREF Col;
94 memcpy(&Col, COLOR_sysPalTemplate + nIndex, sizeof(COLORREF));
95 return(W32kCreateSolidBrush(Col));
96 }
97
98
99
100 const PALETTEENTRY* FASTCALL COLOR_GetSystemPaletteTemplate(void)
101 {
102 return (const PALETTEENTRY*)&COLOR_sysPalTemplate;
103 }
104
105 BOOL STDCALL W32kAnimatePalette(HPALETTE hpal,
106 UINT StartIndex,
107 UINT Entries,
108 CONST PPALETTEENTRY ppe)
109 {
110 /*
111 if( hPal != W32kGetStockObject(DEFAULT_PALETTE) )
112 {
113 PALETTEOBJ* palPtr = (PALETTEOBJ *)GDI_GetObjPtr(hPal, PALETTE_MAGIC);
114 if (!palPtr) return FALSE;
115
116 if( (StartIndex + NumEntries) <= palPtr->logpalette.palNumEntries )
117 {
118 UINT u;
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);
123 return TRUE;
124 }
125 GDI_ReleaseObj(hPal);
126 }
127 return FALSE;
128 */
129 UNIMPLEMENTED;
130 }
131
132 HPALETTE STDCALL W32kCreateHalftonePalette(HDC hDC)
133 {
134 int i, r, g, b;
135 struct {
136 WORD Version;
137 WORD NumberOfEntries;
138 PALETTEENTRY aEntries[256];
139 } Palette;
140
141 Palette.Version = 0x300;
142 Palette.NumberOfEntries = 256;
143 W32kGetSystemPaletteEntries(hDC, 0, 256, Palette.aEntries);
144
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;
152 }
153 }
154 }
155
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;
161 }
162
163 return W32kCreatePalette((LOGPALETTE *)&Palette);
164 }
165
166 HPALETTE STDCALL W32kCreatePalette(CONST PLOGPALETTE palette)
167 {
168 PPALOBJ PalObj;
169
170 HPALETTE NewPalette = (HPALETTE)EngCreatePalette(PAL_INDEXED, palette->palNumEntries, (PULONG*) palette->palPalEntry, 0, 0, 0);
171 ULONG size;
172
173 PalObj = (PPALOBJ)AccessUserObject(NewPalette);
174
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;
180
181 return NewPalette;
182 }
183
184 BOOL STDCALL W32kGetColorAdjustment(HDC hDC,
185 LPCOLORADJUSTMENT ca)
186 {
187 UNIMPLEMENTED;
188 }
189
190 COLORREF STDCALL W32kGetNearestColor(HDC hDC,
191 COLORREF Color)
192 {
193 COLORREF nearest = CLR_INVALID;
194 PDC dc;
195 PPALOBJ palObj;
196
197 if( (dc = DC_HandleToPtr(hDC) ) )
198 {
199 HPALETTE hpal = (dc->w.hPalette)? dc->w.hPalette : W32kGetStockObject(DEFAULT_PALETTE);
200 palObj = (PPALOBJ)AccessUserObject(hpal);
201 if (!palObj) {
202 // GDI_ReleaseObj(hdc);
203 return nearest;
204 }
205
206 nearest = COLOR_LookupNearestColor(palObj->logpalette->palPalEntry,
207 palObj->logpalette->palNumEntries, Color);
208 // FIXME: release hpal!!
209 // GDI_ReleaseObj( hpal );
210 DC_ReleasePtr( hDC );
211 }
212
213 return nearest;
214 }
215
216 UINT STDCALL W32kGetNearestPaletteIndex(HPALETTE hpal,
217 COLORREF Color)
218 {
219 PPALOBJ palObj = (PPALOBJ)AccessUserObject(hpal);
220 UINT index = 0;
221
222 if( palObj )
223 {
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 );
227 }
228
229 return index;
230 }
231
232 UINT STDCALL W32kGetPaletteEntries(HPALETTE hpal,
233 UINT StartIndex,
234 UINT Entries,
235 LPPALETTEENTRY pe)
236 {
237 PPALOBJ palPtr;
238 UINT numEntries;
239
240 palPtr = (PPALOBJ)AccessUserObject(hpal);
241 if (!palPtr) return 0;
242
243 numEntries = palPtr->logpalette->palNumEntries;
244 if (StartIndex + Entries > numEntries) Entries = numEntries - StartIndex;
245 if (pe)
246 {
247 if (StartIndex >= numEntries)
248 {
249 // GDI_ReleaseObj( hpalette );
250 return 0;
251 }
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;
256 }
257
258 // GDI_ReleaseObj( hpalette );
259 return Entries;
260 }
261
262 UINT STDCALL W32kGetSystemPaletteEntries(HDC hDC,
263 UINT StartIndex,
264 UINT Entries,
265 LPPALETTEENTRY pe)
266 {
267 UINT i;
268 PDC dc;
269 /*
270 if (!(dc = AccessUserObject(hdc))) return 0;
271
272 if (!pe)
273 {
274 Entries = dc->GDIInfo->ulNumPalReg;
275 goto done;
276 }
277
278 if (StartIndex >= dc->GDIInfo->ulNumPalReg)
279 {
280 Entries = 0;
281 goto done;
282 }
283
284 if (StartIndex + Entries >= dc->GDIInfo->ulNumPalReg) Entries = dc->GDIInfo->ulNumPalReg - StartIndex;
285
286 for (i = 0; i < Entries; i++)
287 {
288 *(COLORREF*)(entries + i) = COLOR_GetSystemPaletteEntry(StartIndex + i);
289 }
290
291 done:
292 // GDI_ReleaseObj(hdc);
293 return count; */
294 }
295
296 UINT STDCALL W32kGetSystemPaletteUse(HDC hDC)
297 {
298 UNIMPLEMENTED;
299 }
300
301 /*!
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.
303
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.
305
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
308 the system palette.
309 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the system palette.
310
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
313 the dc palette.
314 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the dc palette.
315 */
316 UINT STDCALL W32kRealizePalette(HDC hDC)
317 {
318 PPALOBJ palPtr, sysPtr;
319 PPALGDI palGDI, sysGDI;
320 int realized = 0;
321 PDC dc;
322 HPALETTE systemPalette;
323 PSURFGDI SurfGDI;
324 BOOLEAN success;
325
326 dc = DC_HandleToPtr(hDC);
327 if (!dc)
328 return 0;
329
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);
336
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)));
341
342 // Step 2:
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)
347 {
348 // Memory managed DC
349 DbgPrint("win32k: realizepalette unimplemented step 2 for DC_MEMORY");
350 } else {
351 if(SurfGDI->SetPalette)
352 {
353 success = SurfGDI->SetPalette(dc->PDev, sysPtr, 0, 0, sysPtr->logpalette->palNumEntries);
354 }
355 }
356
357 // Step 3: Create the XLATEOBJ for device managed DCs
358 if(dc->w.flags != DC_MEMORY)
359 {
360 // Device managed DC
361 palPtr->logicalToSystem = IntEngCreateXlate(sysGDI->Mode, palGDI->Mode, systemPalette, dc->w.hPalette);
362 }
363
364 // GDI_ReleaseObj(dc->w.hPalette);
365 // GDI_ReleaseObj(hdc);
366
367 return realized;
368 }
369
370 BOOL STDCALL W32kResizePalette(HPALETTE hpal,
371 UINT Entries)
372 {
373 /* PPALOBJ palPtr = (PPALOBJ)AccessUserObject(hPal);
374 UINT cPrevEnt, prevVer;
375 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
376 PXLATEOBJ XlateObj = NULL;
377
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;
384
385 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
386
387 if(XlateObj)
388 {
389 PXLATEOBJ NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
390 if(NewXlateObj == NULL)
391 {
392 ERR("Can not resize logicalToSystem -- out of memory!");
393 GDI_ReleaseObj( hPal );
394 return FALSE;
395 }
396 palPtr->logicalToSystem = NewXlateObj;
397 }
398
399 if(cEntries > cPrevEnt)
400 {
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 );
404 }
405 palPtr->logpalette->palNumEntries = cEntries;
406 palPtr->logpalette->palVersion = prevVer;
407 // GDI_ReleaseObj( hPal );
408 return TRUE; */
409
410 UNIMPLEMENTED;
411 }
412
413 /*!
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
421 *
422 * \todo implement ForceBackground == TRUE
423 */
424 HPALETTE STDCALL W32kSelectPalette(HDC hDC,
425 HPALETTE hpal,
426 BOOL ForceBackground)
427 {
428 PDC dc;
429 HPALETTE oldPal;
430
431 // FIXME: mark the palette as a [fore\back]ground pal
432 dc = DC_HandleToPtr(hDC);
433 if( dc ){
434 oldPal = dc->w.hPalette;
435 dc->w.hPalette = hpal;
436 DC_ReleasePtr( hDC );
437 }
438
439 return oldPal;
440 }
441
442 BOOL STDCALL W32kSetColorAdjustment(HDC hDC,
443 CONST LPCOLORADJUSTMENT ca)
444 {
445 UNIMPLEMENTED;
446 }
447
448 UINT STDCALL W32kSetPaletteEntries(HPALETTE hpal,
449 UINT Start,
450 UINT Entries,
451 CONST LPPALETTEENTRY pe)
452 {
453 PPALOBJ palPtr;
454 INT numEntries;
455
456 palPtr = (PPALOBJ)AccessUserObject(hpal);
457 if (!palPtr) return 0;
458
459 numEntries = palPtr->logpalette->palNumEntries;
460 if (Start >= numEntries)
461 {
462 // GDI_ReleaseObj( hpalette );
463 return 0;
464 }
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 );
471 return Entries;
472 }
473
474 UINT STDCALL W32kSetSystemPaletteUse(HDC hDC,
475 UINT Usage)
476 {
477 UNIMPLEMENTED;
478 }
479
480 BOOL STDCALL W32kUnrealizeObject(HGDIOBJ hgdiobj)
481 {
482 UNIMPLEMENTED;
483 }
484
485 BOOL STDCALL W32kUpdateColors(HDC hDC)
486 {
487 PDC dc;
488 HWND hWnd;
489 int size;
490 /*
491 if (!(dc = AccessUserObject(hDC))) return 0;
492 size = dc->GDIInfo->ulNumPalReg;
493 // GDI_ReleaseObj( hDC );
494
495 if (Callout.WindowFromDC)
496 {
497 hWnd = Callout.WindowFromDC( hDC );
498
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 );
502 } */
503 return 0x666;
504 }
505
506 INT STDCALL COLOR_PaletteLookupPixel(PALETTEENTRY *palPalEntry, INT size,
507 PXLATEOBJ XlateObj, COLORREF col, BOOL skipReserved)
508 {
509 int i, best = 0, diff = 0x7fffffff;
510 int r, g, b;
511
512 for( i = 0; i < size && diff ; i++ )
513 {
514 if(!(palPalEntry[i].peFlags & PC_SYS_USED) || (skipReserved && palPalEntry[i].peFlags & PC_SYS_RESERVED))
515 continue;
516
517 r = palPalEntry[i].peRed - GetRValue(col);
518 g = palPalEntry[i].peGreen - GetGValue(col);
519 b = palPalEntry[i].peBlue - GetBValue(col);
520
521 r = r*r + g*g + b*b;
522
523 if( r < diff ) { best = i; diff = r; }
524 }
525 return (XlateObj->pulXlate) ? XlateObj->pulXlate[best] : best;
526 }
527
528 COLORREF STDCALL COLOR_LookupNearestColor( PALETTEENTRY* palPalEntry, int size, COLORREF color )
529 {
530 unsigned char spec_type = color >> 24;
531 int i;
532 PALETTEENTRY *COLOR_sysPal = (PALETTEENTRY*)ReturnSystemPalette();
533
534 // we need logical palette for PALETTERGB and PALETTEINDEX colorrefs
535
536 if( spec_type == 2 ) /* PALETTERGB */
537 color = *(COLORREF*)(palPalEntry + COLOR_PaletteLookupPixel(palPalEntry,size,NULL,color,FALSE));
538
539 else if( spec_type == 1 ) /* PALETTEINDEX */
540 {
541 if( (i = color & 0x0000ffff) >= size )
542 {
543 DbgPrint("RGB(%lx) : idx %d is out of bounds, assuming NULL\n", color, i);
544 color = *(COLORREF*)palPalEntry;
545 }
546 else color = *(COLORREF*)(palPalEntry + i);
547 }
548
549 color &= 0x00ffffff;
550 return (0x00ffffff & *(COLORREF*)(COLOR_sysPal + COLOR_PaletteLookupPixel(COLOR_sysPal, 256, NULL, color, FALSE)));
551 }
552
553 int STDCALL COLOR_PaletteLookupExactIndex( PALETTEENTRY* palPalEntry, int size,
554 COLORREF col )
555 {
556 int i;
557 BYTE r = GetRValue(col), g = GetGValue(col), b = GetBValue(col);
558 for( i = 0; i < size; i++ )
559 {
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;
562 }
563 return -1;
564 }
565 /* EOF */