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