Identation corrected, many fixes and minor improvements, initial DIB support
[reactos.git] / reactos / subsys / win32k / objects / color.c
1 // FIXME: Use PXLATEOBJ logicalToSystem instead of int *mapping
2
3 #undef WIN32_LEAN_AND_MEAN
4 #include <windows.h>
5 #include <ddk/ntddk.h>
6 #include <ddk/winddi.h>
7 #include <win32k/dc.h>
8 #include <win32k/color.h>
9 #include "../eng/objects.h"
10
11 // #define NDEBUG
12 #include <win32k/debug1.h>
13
14 int COLOR_gapStart = 256;
15 int COLOR_gapEnd = -1;
16 int COLOR_gapFilled = 0;
17 int COLOR_max = 256;
18
19 static HPALETTE hPrimaryPalette = 0; // used for WM_PALETTECHANGED
20 static HPALETTE hLastRealizedPalette = 0; // UnrealizeObject() needs it
21
22 const PALETTEENTRY COLOR_sysPalTemplate[NB_RESERVED_COLORS] =
23 {
24 // first 10 entries in the system palette
25 // red green blue flags
26 { 0x00, 0x00, 0x00, PC_SYS_USED },
27 { 0x80, 0x00, 0x00, PC_SYS_USED },
28 { 0x00, 0x80, 0x00, PC_SYS_USED },
29 { 0x80, 0x80, 0x00, PC_SYS_USED },
30 { 0x00, 0x00, 0x80, PC_SYS_USED },
31 { 0x80, 0x00, 0x80, PC_SYS_USED },
32 { 0x00, 0x80, 0x80, PC_SYS_USED },
33 { 0xc0, 0xc0, 0xc0, PC_SYS_USED },
34 { 0xc0, 0xdc, 0xc0, PC_SYS_USED },
35 { 0xa6, 0xca, 0xf0, PC_SYS_USED },
36
37 // ... c_min/2 dynamic colorcells
38 // ... gap (for sparse palettes)
39 // ... c_min/2 dynamic colorcells
40
41 { 0xff, 0xfb, 0xf0, PC_SYS_USED },
42 { 0xa0, 0xa0, 0xa4, PC_SYS_USED },
43 { 0x80, 0x80, 0x80, PC_SYS_USED },
44 { 0xff, 0x00, 0x00, PC_SYS_USED },
45 { 0x00, 0xff, 0x00, PC_SYS_USED },
46 { 0xff, 0xff, 0x00, PC_SYS_USED },
47 { 0x00, 0x00, 0xff, PC_SYS_USED },
48 { 0xff, 0x00, 0xff, PC_SYS_USED },
49 { 0x00, 0xff, 0xff, PC_SYS_USED },
50 { 0xff, 0xff, 0xff, PC_SYS_USED } // last 10
51 };
52
53 const PALETTEENTRY* COLOR_GetSystemPaletteTemplate(void)
54 {
55 return COLOR_sysPalTemplate;
56 }
57
58 BOOL STDCALL W32kAnimatePalette(HPALETTE hpal,
59 UINT StartIndex,
60 UINT Entries,
61 CONST PPALETTEENTRY ppe)
62 {
63 /*
64 if( hPal != W32kGetStockObject(DEFAULT_PALETTE) )
65 {
66 PALETTEOBJ* palPtr = (PALETTEOBJ *)GDI_GetObjPtr(hPal, PALETTE_MAGIC);
67 if (!palPtr) return FALSE;
68
69 if( (StartIndex + NumEntries) <= palPtr->logpalette.palNumEntries )
70 {
71 UINT u;
72 for( u = 0; u < NumEntries; u++ )
73 palPtr->logpalette.palPalEntry[u + StartIndex] = PaletteColors[u];
74 PALETTE_Driver->pSetMapping(palPtr, StartIndex, NumEntries, hPal != hPrimaryPalette );
75 GDI_ReleaseObj(hPal);
76 return TRUE;
77 }
78 GDI_ReleaseObj(hPal);
79 }
80 return FALSE;
81 */
82 UNIMPLEMENTED;
83 }
84
85 HPALETTE STDCALL W32kCreateHalftonePalette(HDC hDC)
86 {
87 int i, r, g, b;
88 struct {
89 WORD Version;
90 WORD NumberOfEntries;
91 PALETTEENTRY aEntries[256];
92 } Palette;
93
94 Palette.Version = 0x300;
95 Palette.NumberOfEntries = 256;
96 W32kGetSystemPaletteEntries(hDC, 0, 256, Palette.aEntries);
97
98 for (r = 0; r < 6; r++) {
99 for (g = 0; g < 6; g++) {
100 for (b = 0; b < 6; b++) {
101 i = r + g*6 + b*36 + 10;
102 Palette.aEntries[i].peRed = r * 51;
103 Palette.aEntries[i].peGreen = g * 51;
104 Palette.aEntries[i].peBlue = b * 51;
105 }
106 }
107 }
108
109 for (i = 216; i < 246; i++) {
110 int v = (i - 216) * 8;
111 Palette.aEntries[i].peRed = v;
112 Palette.aEntries[i].peGreen = v;
113 Palette.aEntries[i].peBlue = v;
114 }
115
116 return W32kCreatePalette((LOGPALETTE *)&Palette);
117 }
118
119 HPALETTE STDCALL W32kCreatePalette(CONST PLOGPALETTE palette)
120 {
121 PPALOBJ PalObj;
122 HPALETTE NewPalette = EngCreatePalette(PAL_INDEXED, palette->palNumEntries, palette->palPalEntry, 0, 0, 0);
123 ULONG size;
124
125 PalObj = AccessUserObject(NewPalette);
126
127 size = sizeof(LOGPALETTE) + (palette->palNumEntries - 1) * sizeof(PALETTEENTRY);
128 memcpy(&PalObj->logpalette, palette, size);
129 PALETTE_ValidateFlags(PalObj->logpalette.palPalEntry, PalObj->logpalette.palNumEntries);
130 PalObj->logicalToSystem = NULL;
131
132 return NewPalette;
133 }
134
135 BOOL STDCALL W32kGetColorAdjustment(HDC hDC,
136 LPCOLORADJUSTMENT ca)
137 {
138 UNIMPLEMENTED;
139 }
140
141 COLORREF STDCALL W32kGetNearestColor(HDC hDC,
142 COLORREF Color)
143 {
144 COLORREF nearest = CLR_INVALID;
145 PDC dc;
146 PPALOBJ palObj;
147
148 if(DC_HandleToPtr(hDC))
149 {
150 HPALETTE hpal = (dc->w.hPalette)? dc->w.hPalette : W32kGetStockObject(DEFAULT_PALETTE);
151 palObj = AccessUserObject(hpal);
152 if (!palObj) {
153 // GDI_ReleaseObj(hdc);
154 return nearest;
155 }
156
157 nearest = COLOR_LookupNearestColor(palObj->logpalette.palPalEntry,
158 palObj->logpalette.palNumEntries, Color);
159
160 // GDI_ReleaseObj( hpal );
161 // GDI_ReleaseObj( hdc );
162 }
163
164 return nearest;
165 }
166
167 UINT STDCALL W32kGetNearestPaletteIndex(HPALETTE hpal,
168 COLORREF Color)
169 {
170 PPALOBJ palObj = AccessUserObject(hpal);
171 UINT index = 0;
172
173 if( palObj )
174 {
175 // Return closest match for the given RGB color
176 index = COLOR_PaletteLookupPixel(palObj->logpalette.palPalEntry, palObj->logpalette.palNumEntries, NULL, Color, FALSE);
177 // GDI_ReleaseObj( hpalette );
178 }
179
180 return index;
181 }
182
183 UINT STDCALL W32kGetPaletteEntries(HPALETTE hpal,
184 UINT StartIndex,
185 UINT Entries,
186 LPPALETTEENTRY pe)
187 {
188 PPALOBJ palPtr;
189 UINT numEntries;
190
191 palPtr = AccessUserObject(hpal);
192 if (!palPtr) return 0;
193
194 numEntries = palPtr->logpalette.palNumEntries;
195 if (StartIndex + Entries > numEntries) Entries = numEntries - StartIndex;
196 if (pe)
197 {
198 if (StartIndex >= numEntries)
199 {
200 // GDI_ReleaseObj( hpalette );
201 return 0;
202 }
203 memcpy(pe, &palPtr->logpalette.palPalEntry[StartIndex], Entries * sizeof(PALETTEENTRY));
204 for(numEntries = 0; numEntries < Entries ; numEntries++)
205 if (pe[numEntries].peFlags & 0xF0)
206 pe[numEntries].peFlags = 0;
207 }
208
209 // GDI_ReleaseObj( hpalette );
210 return Entries;
211 }
212
213 UINT STDCALL W32kGetSystemPaletteEntries(HDC hDC,
214 UINT StartIndex,
215 UINT Entries,
216 LPPALETTEENTRY pe)
217 {
218 UINT i;
219 PDC dc;
220 /*
221 if (!(dc = AccessUserObject(hdc))) return 0;
222
223 if (!pe)
224 {
225 Entries = dc->devCaps->sizePalette;
226 goto done;
227 }
228
229 if (StartIndex >= dc->devCaps->sizePalette)
230 {
231 Entries = 0;
232 goto done;
233 }
234
235 if (StartIndex + Entries >= dc->devCaps->sizePalette) Entries = dc->devCaps->sizePalette - StartIndex;
236
237 for (i = 0; i < Entries; i++)
238 {
239 *(COLORREF*)(entries + i) = COLOR_GetSystemPaletteEntry(StartIndex + i);
240 }
241
242 done:
243 // GDI_ReleaseObj(hdc);
244 return count; */
245 }
246
247 UINT STDCALL W32kGetSystemPaletteUse(HDC hDC)
248 {
249 UNIMPLEMENTED;
250 }
251
252 UINT STDCALL W32kRealizePalette(HDC hDC)
253 /*
254 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.
255
256 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.
257
258 1= IF DRAWING TO A DEVICE
259 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
260 the system palette.
261 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the system palette.
262
263 2= IF DRAWING TO A MEMORY DC\BITMAP
264 -- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and
265 the dc palette.
266 -- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the dc palette.
267 */
268 {
269 PPALOBJ palPtr, sysPtr;
270 PPALGDI palGDI, sysGDI;
271 int realized = 0;
272 PDC dc = AccessUserObject(hDC);
273 HPALETTE systemPalette;
274 PSURFGDI SurfGDI;
275 BOOLEAN success;
276
277 if (!dc) return 0;
278
279 palPtr = AccessUserObject(dc->w.hPalette);
280 SurfGDI = AccessInternalObjectFromUserObject(dc->Surface);
281 systemPalette = W32kGetStockObject(STOCK_DEFAULT_PALETTE);
282 sysPtr = AccessInternalObject(systemPalette);
283 palGDI = AccessInternalObject(dc->w.hPalette);
284 sysGDI = AccessInternalObject(systemPalette);
285
286 // Step 1: Create mapping of system palette\DC palette
287 realized = PALETTE_SetMapping(palPtr, 0, palPtr->logpalette.palNumEntries,
288 (dc->w.hPalette != hPrimaryPalette) ||
289 (dc->w.hPalette == W32kGetStockObject(DEFAULT_PALETTE)));
290
291 // Step 2:
292 // The RealizePalette function modifies the palette for the device associated with the specified device context. If the
293 // device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device
294 // context is a display DC, the physical palette for that device is modified.
295 if(dc->w.flags == DC_MEMORY)
296 {
297 // Memory managed DC
298 DbgPrint("win32k: realizepalette unimplemented step 2 for DC_MEMORY");
299 } else {
300 if(SurfGDI->SetPalette)
301 {
302 success = SurfGDI->SetPalette(dc->PDev, sysPtr, 0, 0, sysPtr->logpalette.palNumEntries);
303 }
304 }
305
306 // Step 3: Create the XLATEOBJ for device managed DCs
307 if(dc->w.flags != DC_MEMORY)
308 {
309 // Device managed DC
310 palPtr->logicalToSystem = EngCreateXlate(sysGDI->Mode, palGDI->Mode, systemPalette, dc->w.hPalette);
311 }
312
313 // GDI_ReleaseObj(dc->w.hPalette);
314 // GDI_ReleaseObj(hdc);
315
316 return realized;
317 }
318
319 BOOL STDCALL W32kResizePalette(HPALETTE hpal,
320 UINT Entries)
321 {
322 /* PPALOBJ palPtr = (PPALOBJ)AccessUserObject(hPal);
323 UINT cPrevEnt, prevVer;
324 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
325 PXLATEOBJ XlateObj = NULL;
326
327 if(!palPtr) return FALSE;
328 cPrevEnt = palPtr->logpalette.palNumEntries;
329 prevVer = palPtr->logpalette.palVersion;
330 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
331 size += sizeof(int*) + sizeof(GDIOBJHDR);
332 XlateObj = palPtr->logicalToSystem;
333
334 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
335
336 if(XlateObj)
337 {
338 PXLATEOBJ NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
339 if(NewXlateObj == NULL)
340 {
341 ERR("Can not resize logicalToSystem -- out of memory!");
342 GDI_ReleaseObj( hPal );
343 return FALSE;
344 }
345 palPtr->logicalToSystem = NewXlateObj;
346 }
347
348 if(cEntries > cPrevEnt)
349 {
350 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
351 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
352 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
353 }
354 palPtr->logpalette.palNumEntries = cEntries;
355 palPtr->logpalette.palVersion = prevVer;
356 // GDI_ReleaseObj( hPal );
357 return TRUE; */
358
359 UNIMPLEMENTED;
360 }
361
362 HPALETTE STDCALL W32kSelectPalette(HDC hDC,
363 HPALETTE hpal,
364 BOOL ForceBackground)
365 {
366 PDC dc = AccessUserObject(hDC);
367 HPALETTE oldPal;
368
369 oldPal = dc->w.hPalette;
370 dc->w.hPalette = hpal;
371
372 // FIXME: mark the palette as a [fore\back]ground pal
373
374 return oldPal;
375 }
376
377 BOOL STDCALL W32kSetColorAdjustment(HDC hDC,
378 CONST LPCOLORADJUSTMENT ca)
379 {
380 UNIMPLEMENTED;
381 }
382
383 UINT STDCALL W32kSetPaletteEntries(HPALETTE hpal,
384 UINT Start,
385 UINT Entries,
386 CONST LPPALETTEENTRY pe)
387 {
388 PPALOBJ palPtr;
389 INT numEntries;
390
391 palPtr = AccessUserObject(hpal);
392 if (!palPtr) return 0;
393
394 numEntries = palPtr->logpalette.palNumEntries;
395 if (Start >= numEntries)
396 {
397 // GDI_ReleaseObj( hpalette );
398 return 0;
399 }
400 if (Start + Entries > numEntries) Entries = numEntries - Start;
401 memcpy(&palPtr->logpalette.palPalEntry[Start], pe, Entries * sizeof(PALETTEENTRY));
402 PALETTE_ValidateFlags(palPtr->logpalette.palPalEntry, palPtr->logpalette.palNumEntries);
403 ExFreePool(palPtr->logicalToSystem);
404 palPtr->logicalToSystem = NULL;
405 // GDI_ReleaseObj( hpalette );
406 return Entries;
407 }
408
409 UINT STDCALL W32kSetSystemPaletteUse(HDC hDC,
410 UINT Usage)
411 {
412 UNIMPLEMENTED;
413 }
414
415 BOOL STDCALL W32kUnrealizeObject(HGDIOBJ hgdiobj)
416 {
417 UNIMPLEMENTED;
418 }
419
420 BOOL STDCALL W32kUpdateColors(HDC hDC)
421 {
422 PDC dc;
423 HWND hWnd;
424 int size;
425 /*
426 if (!(dc = AccessUserObject(hDC))) return 0;
427 size = dc->devCaps->sizePalette;
428 // GDI_ReleaseObj( hDC );
429
430 if (Callout.WindowFromDC)
431 {
432 hWnd = Callout.WindowFromDC( hDC );
433
434 // Docs say that we have to remap current drawable pixel by pixel
435 // but it would take forever given the speed of XGet/PutPixel.
436 if (hWnd && size) Callout.RedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE );
437 } */
438 return 0x666;
439 }
440
441 int COLOR_PaletteLookupPixel(PALETTEENTRY *palPalEntry, int size,
442 PXLATEOBJ XlateObj, COLORREF col, BOOL skipReserved)
443 {
444 int i, best = 0, diff = 0x7fffffff;
445 int r, g, b;
446
447 for( i = 0; i < size && diff ; i++ )
448 {
449 if(!(palPalEntry[i].peFlags & PC_SYS_USED) || (skipReserved && palPalEntry[i].peFlags & PC_SYS_RESERVED))
450 continue;
451
452 r = palPalEntry[i].peRed - GetRValue(col);
453 g = palPalEntry[i].peGreen - GetGValue(col);
454 b = palPalEntry[i].peBlue - GetBValue(col);
455
456 r = r*r + g*g + b*b;
457
458 if( r < diff ) { best = i; diff = r; }
459 }
460 return (XlateObj->pulXlate) ? XlateObj->pulXlate[best] : best;
461 }
462
463 COLORREF COLOR_LookupNearestColor( PALETTEENTRY* palPalEntry, int size, COLORREF color )
464 {
465 unsigned char spec_type = color >> 24;
466 int i;
467 PALETTEENTRY *COLOR_sysPal = ReturnSystemPalette();
468
469 // we need logical palette for PALETTERGB and PALETTEINDEX colorrefs
470
471 if( spec_type == 2 ) /* PALETTERGB */
472 color = *(COLORREF*)(palPalEntry + COLOR_PaletteLookupPixel(palPalEntry,size,NULL,color,FALSE));
473
474 else if( spec_type == 1 ) /* PALETTEINDEX */
475 {
476 if( (i = color & 0x0000ffff) >= size )
477 {
478 DbgPrint("RGB(%lx) : idx %d is out of bounds, assuming NULL\n", color, i);
479 color = *(COLORREF*)palPalEntry;
480 }
481 else color = *(COLORREF*)(palPalEntry + i);
482 }
483
484 color &= 0x00ffffff;
485 return (0x00ffffff & *(COLORREF*)(COLOR_sysPal + COLOR_PaletteLookupPixel(COLOR_sysPal, 256, NULL, color, FALSE)));
486 }
487
488 int COLOR_PaletteLookupExactIndex( PALETTEENTRY* palPalEntry, int size,
489 COLORREF col )
490 {
491 int i;
492 BYTE r = GetRValue(col), g = GetGValue(col), b = GetBValue(col);
493 for( i = 0; i < size; i++ )
494 {
495 if( palPalEntry[i].peFlags & PC_SYS_USED ) /* skips gap */
496 if(palPalEntry[i].peRed == r && palPalEntry[i].peGreen == g && palPalEntry[i].peBlue == b) return i;
497 }
498 return -1;
499 }