e472798ef50f52ee88c244d80ff0ab1f8151d457
[reactos.git] / subsystems / win32 / win32k / eng / xlate.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI Color Translation Functions
5 * FILE: subsystems/win32/win32k/eng/xlate.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
7 */
8
9 #include <win32k.h>
10
11 #include <intrin.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16
17 /** Globals *******************************************************************/
18
19 ULONG giUniqueXlate = 0;
20 EXLATEOBJ gexloTrivial;
21 XLATEOBJ* gpxloTrivial = &gexloTrivial.xlo;
22
23 const BYTE gajXlate5to8[32] =
24 { 0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99,107,115,123,
25 132,140,148,156,165,173,181,189,197,206,214,222,231,239,247,255};
26
27 const BYTE gajXlate6to8[64] =
28 { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 52, 57, 61,
29 65, 69, 73, 77, 81, 85, 89, 93, 97,101,105,109,113,117,121,125,
30 130,134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,
31 194,198,202,207,210,215,219,223,227,231,235,239,243,247,251,255};
32
33
34 /** iXlate functions **********************************************************/
35
36 ULONG
37 FASTCALL
38 EXLATEOBJ_iXlateTrivial(PEXLATEOBJ pexlo, ULONG iColor)
39 {
40 return iColor;
41 }
42
43 ULONG
44 FASTCALL
45 EXLATEOBJ_iXlateToMono(PEXLATEOBJ pexlo, ULONG iColor)
46 {
47 return (iColor == pexlo->xlo.pulXlate[0]);
48 }
49
50 ULONG
51 FASTCALL
52 EXLATEOBJ_iXlateTable(PEXLATEOBJ pexlo, ULONG iColor)
53 {
54 if (iColor >= pexlo->xlo.cEntries)
55 {
56 iColor %= pexlo->xlo.cEntries;
57 }
58 return pexlo->xlo.pulXlate[iColor];
59 }
60
61 ULONG
62 FASTCALL
63 EXLATEOBJ_iXlateRGBtoBGR(PEXLATEOBJ pxlo, ULONG iColor)
64 {
65 ULONG iNewColor;
66
67 /* Copy green */
68 iNewColor = iColor & 0x00ff00;
69
70 /* Mask red and blue */
71 iColor &= 0xff00ff;
72
73 /* Shift and copy red and blue */
74 iNewColor |= iColor >> 16;
75 iNewColor |= iColor << 16;
76
77 return iNewColor;
78 }
79
80 ULONG
81 FASTCALL
82 EXLATEOBJ_iXlateRGBto555(PEXLATEOBJ pxlo, ULONG iColor)
83 {
84 ULONG iNewColor;
85
86 /* Copy red */
87 iColor <<= 7;
88 iNewColor = iColor & 0x7C00;
89
90 /* Copy green */
91 iColor >>= 13;
92 iNewColor |= iColor & 0x3E0;
93
94 /* Copy green */
95 iColor >>= 13;
96 iNewColor |= iColor & 0x1F;
97
98 return iNewColor;
99 }
100
101 ULONG
102 FASTCALL
103 EXLATEOBJ_iXlateBGRto555(PEXLATEOBJ pxlo, ULONG iColor)
104 {
105 ULONG iNewColor;
106
107 /* Copy blue */
108 iColor >>= 3;
109 iNewColor = iColor & 0x1f;
110
111 /* Copy green */
112 iColor >>= 3;
113 iNewColor |= (iColor & 0x3E0);
114
115 /* Copy red */
116 iColor >>= 3;
117 iNewColor |= (iColor & 0x7C00);
118
119 return iNewColor;
120 }
121
122 ULONG
123 FASTCALL
124 EXLATEOBJ_iXlateRGBto565(PEXLATEOBJ pxlo, ULONG iColor)
125 {
126 ULONG iNewColor;
127
128 /* Copy red */
129 iColor <<= 8;
130 iNewColor = iColor & 0xF800;
131
132 /* Copy green */
133 iColor >>= 13;
134 iNewColor |= iColor & 0x7E0;
135
136 /* Copy green */
137 iColor >>= 14;
138 iNewColor |= iColor & 0x1F;
139
140 return iNewColor;
141 }
142
143 ULONG
144 FASTCALL
145 EXLATEOBJ_iXlateBGRto565(PEXLATEOBJ pxlo, ULONG iColor)
146 {
147 ULONG iNewColor;
148
149 /* Copy blue */
150 iColor >>= 3;
151 iNewColor = iColor & 0x1f;
152
153 /* Copy green */
154 iColor >>= 2;
155 iNewColor |= (iColor & 0x7E0);
156
157 /* Copy red */
158 iColor >>= 3;
159 iNewColor |= (iColor & 0xF800);
160
161 return iNewColor;
162 }
163
164 ULONG
165 FASTCALL
166 EXLATEOBJ_iXlateRGBtoPal(PEXLATEOBJ pexlo, ULONG iColor)
167 {
168 return PALETTE_ulGetNearestPaletteIndex(pexlo->ppalDst, iColor);
169 }
170
171 ULONG
172 FASTCALL
173 EXLATEOBJ_iXlate555toRGB(PEXLATEOBJ pxlo, ULONG iColor)
174 {
175 ULONG iNewColor;
176
177 /* Copy blue */
178 iNewColor = gajXlate5to8[iColor & 0x1F] << 16;
179
180 /* Copy green */
181 iColor >>= 5;
182 iNewColor |= gajXlate5to8[iColor & 0x1F] << 8;
183
184 /* Copy red */
185 iColor >>= 5;
186 iNewColor |= gajXlate5to8[iColor & 0x1F];
187
188 return iNewColor;
189 }
190
191 ULONG
192 FASTCALL
193 EXLATEOBJ_iXlate555toBGR(PEXLATEOBJ pxlo, ULONG iColor)
194 {
195 ULONG iNewColor;
196
197 /* Copy blue */
198 iNewColor = gajXlate5to8[iColor & 0x1F];
199
200 /* Copy green */
201 iColor >>= 5;
202 iNewColor |= gajXlate5to8[iColor & 0x1F] << 8;
203
204 /* Copy red */
205 iColor >>= 5;
206 iNewColor |= gajXlate5to8[iColor & 0x1F] << 16;
207
208 return iNewColor;
209 }
210
211 ULONG
212 FASTCALL
213 EXLATEOBJ_iXlate555to565(PEXLATEOBJ pxlo, ULONG iColor)
214 {
215 ULONG iNewColor;
216
217 /* Copy blue */
218 iNewColor = iColor & 0x1f;
219
220 /* Copy red and green */
221 iColor <<= 1;
222 iNewColor |= iColor & 0xFFC0;
223
224 /* Duplicate highest green bit */
225 iColor >>= 5;
226 iNewColor |= (iColor & 0x20);
227
228 return iNewColor;
229 }
230
231 ULONG
232 FASTCALL
233 EXLATEOBJ_iXlate555toPal(PEXLATEOBJ pexlo, ULONG iColor)
234 {
235 iColor = EXLATEOBJ_iXlate555toRGB(pexlo, iColor);
236
237 return PALETTE_ulGetNearestPaletteIndex(pexlo->ppalDst, iColor);
238 }
239
240 ULONG
241 FASTCALL
242 EXLATEOBJ_iXlate565to555(PEXLATEOBJ pxlo, ULONG iColor)
243 {
244 ULONG iNewColor;
245
246 /* Copy blue */
247 iNewColor = iColor & 0x1f;
248
249 /* Copy red and green */
250 iColor >>= 1;
251 iNewColor |= iColor & 0x7FE0;
252
253 return iNewColor;
254 }
255
256 ULONG
257 FASTCALL
258 EXLATEOBJ_iXlate565toRGB(PEXLATEOBJ pexlo, ULONG iColor)
259 {
260 ULONG iNewColor;
261
262 /* Copy blue */
263 iNewColor = gajXlate5to8[iColor & 0x1F] << 16;
264
265 /* Copy green */
266 iColor >>= 5;
267 iNewColor |= gajXlate6to8[iColor & 0x3F] << 8;
268
269 /* Copy red */
270 iColor >>= 6;
271 iNewColor |= gajXlate5to8[iColor & 0x1F];
272
273 return iNewColor;
274 }
275
276 ULONG
277 FASTCALL
278 EXLATEOBJ_iXlate565toBGR(PEXLATEOBJ pexlo, ULONG iColor)
279 {
280 ULONG iNewColor;
281
282 /* Copy blue */
283 iNewColor = gajXlate5to8[iColor & 0x1F];
284
285 /* Copy green */
286 iColor >>= 5;
287 iNewColor |= gajXlate6to8[iColor & 0x3F] << 8;
288
289 /* Copy blue */
290 iColor >>= 6;
291 iNewColor |= gajXlate5to8[iColor & 0x1F] << 16;
292
293 return iNewColor;
294 }
295
296 ULONG
297 FASTCALL
298 EXLATEOBJ_iXlate565toPal(EXLATEOBJ *pexlo, ULONG iColor)
299 {
300 iColor = EXLATEOBJ_iXlate565toRGB(pexlo, iColor);
301
302 return PALETTE_ulGetNearestPaletteIndex(pexlo->ppalDst, iColor);
303 }
304
305 ULONG
306 FASTCALL
307 EXLATEOBJ_iXlateShiftAndMask(PEXLATEOBJ pexlo, ULONG iColor)
308 {
309 ULONG iNewColor;
310
311 iNewColor = _rotl(iColor, pexlo->ulRedShift) & pexlo->ulRedMask;
312 iNewColor |= _rotl(iColor, pexlo->ulGreenShift) & pexlo->ulGreenMask;
313 iNewColor |= _rotl(iColor, pexlo->ulBlueShift) & pexlo->ulBlueMask;
314
315 return iNewColor;
316 }
317
318 ULONG
319 FASTCALL
320 EXLATEOBJ_iXlateBitfieldsToPal(PEXLATEOBJ pexlo, ULONG iColor)
321 {
322 /* Convert bitfields to RGB */
323 iColor = EXLATEOBJ_iXlateShiftAndMask(pexlo, iColor);
324
325 /* Return nearest index */
326 return PALETTE_ulGetNearestPaletteIndex(pexlo->ppalDst, iColor);
327 }
328
329
330 /** Private Functions *********************************************************/
331
332 VOID
333 NTAPI
334 EXLATEOBJ_vInitTrivial(PEXLATEOBJ pexlo)
335 {
336 pexlo->xlo.iUniq = InterlockedIncrement((LONG*)&giUniqueXlate);
337 pexlo->xlo.flXlate = XO_TRIVIAL;
338 pexlo->xlo.iSrcType = PAL_RGB;
339 pexlo->xlo.iDstType = PAL_RGB;
340 pexlo->xlo.cEntries = 0;
341 pexlo->xlo.pulXlate = pexlo->aulXlate;
342 pexlo->pfnXlate = EXLATEOBJ_iXlateTrivial;
343 pexlo->ppalSrc = &gpalRGB;
344 pexlo->ppalDst = &gpalRGB;
345 pexlo->ppalDstDc = &gpalRGB;
346 pexlo->hColorTransform = NULL;
347 }
348
349 VOID
350 NTAPI
351 EXLATEOBJ_vInitialize(
352 PEXLATEOBJ pexlo,
353 PALETTE *ppalSrc,
354 PALETTE *ppalDst,
355 COLORREF crSrcBackColor,
356 COLORREF crDstBackColor,
357 COLORREF crDstForeColor)
358 {
359 ULONG cEntries;
360 ULONG i, ulColor;
361
362 EXLATEOBJ_vInitTrivial(pexlo);
363
364 if (ppalDst == ppalSrc || !ppalSrc || !ppalDst ||
365 ((ppalDst->Mode == PAL_RGB || ppalDst->Mode == PAL_BGR) &&
366 ppalDst->Mode == ppalSrc->Mode))
367 {
368 return;
369 }
370
371 pexlo->ppalSrc = ppalSrc;
372 pexlo->ppalDst = ppalDst;
373 pexlo->xlo.iSrcType = ppalSrc->Mode;
374 pexlo->xlo.iDstType = ppalDst->Mode;
375
376 /* Chack if both of the pallettes are indexed */
377 if (!(ppalSrc->Mode & PAL_INDEXED) || !(ppalDst->Mode & PAL_INDEXED))
378 {
379 /* At least one palette is not indexed, calculate shifts/masks */
380 ULONG aulMasksSrc[3], aulMasksDst[3];
381
382 PALETTE_vGetBitMasks(ppalSrc, aulMasksSrc);
383 PALETTE_vGetBitMasks(ppalDst, aulMasksDst);
384
385 pexlo->ulRedMask = aulMasksDst[0];
386 pexlo->ulGreenMask = aulMasksDst[1];
387 pexlo->ulBlueMask = aulMasksDst[2];
388
389 pexlo->ulRedShift = CalculateShift(aulMasksSrc[0], aulMasksDst[0]);
390 pexlo->ulGreenShift = CalculateShift(aulMasksSrc[1], aulMasksDst[1]);
391 pexlo->ulBlueShift = CalculateShift(aulMasksSrc[2], aulMasksDst[2]);
392 }
393
394 if (ppalSrc->Mode & PAL_MONOCHROME)
395 {
396 /* This is a monochrome palette */
397 if (!(ppalDst->Mode & PAL_MONOCHROME))
398 {
399 /* Mono to color, use the dest DC's fore and back color */
400 pexlo->pfnXlate = EXLATEOBJ_iXlateTable;
401 pexlo->xlo.flXlate |= XO_TABLE;
402 pexlo->xlo.cEntries = 2;
403 pexlo->xlo.pulXlate[0] =
404 PALETTE_ulGetNearestIndex(ppalDst, crDstForeColor);
405 pexlo->xlo.pulXlate[1] =
406 PALETTE_ulGetNearestIndex(ppalDst, crDstBackColor);
407 }
408 }
409 else if (ppalDst->Mode & PAL_MONOCHROME)
410 {
411 pexlo->pfnXlate = EXLATEOBJ_iXlateToMono;
412 pexlo->xlo.flXlate |= XO_TO_MONO;
413 pexlo->xlo.cEntries = 1;
414
415 if (ppalSrc->Mode & PAL_INDEXED)
416 {
417 pexlo->aulXlate[0] =
418 PALETTE_ulGetNearestPaletteIndex(ppalSrc, crSrcBackColor);
419 }
420 else if (ppalSrc->Mode & PAL_BGR)
421 {
422 pexlo->aulXlate[0] = crSrcBackColor;
423 }
424 else if (ppalSrc->Mode & PAL_RGB)
425 {
426 pexlo->aulXlate[0] = RGB(GetBValue(crSrcBackColor),
427 GetGValue(crSrcBackColor),
428 GetRValue(crSrcBackColor));
429 }
430 else if (ppalSrc->Mode & PAL_BITFIELDS)
431 {
432 PALETTE_vGetBitMasks(ppalSrc, &pexlo->ulRedMask);
433 pexlo->ulRedShift = CalculateShift(0xFF, pexlo->ulRedMask);
434 pexlo->ulGreenShift = CalculateShift(0xFF00, pexlo->ulGreenMask);
435 pexlo->ulBlueShift = CalculateShift(0xFF0000, pexlo->ulBlueMask);
436
437 pexlo->aulXlate[0] = EXLATEOBJ_iXlateShiftAndMask(pexlo, crSrcBackColor);
438 }
439 }
440 else if (ppalSrc->Mode & PAL_INDEXED)
441 {
442 cEntries = ppalSrc->NumColors;
443
444 /* Allocate buffer if needed */
445 if (cEntries > 6)
446 {
447 pexlo->xlo.pulXlate = EngAllocMem(0,
448 cEntries * sizeof(ULONG),
449 TAG_XLATEOBJ);
450 if (!pexlo->xlo.pulXlate)
451 {
452 DPRINT1("Could not allocate pulXlate buffer.\n");
453 pexlo->pfnXlate = EXLATEOBJ_iXlateTrivial;
454 pexlo->xlo.flXlate = XO_TRIVIAL;
455 return;
456 }
457 }
458 pexlo->xlo.cEntries = cEntries;
459
460 pexlo->pfnXlate = EXLATEOBJ_iXlateTable;
461 if (ppalDst->Mode & PAL_INDEXED)
462 {
463 pexlo->xlo.flXlate |= XO_TABLE;
464
465 for (i = 0; i < cEntries; i++)
466 {
467 ulColor = RGB(ppalSrc->IndexedColors[i].peRed,
468 ppalSrc->IndexedColors[i].peGreen,
469 ppalSrc->IndexedColors[i].peBlue);
470
471 pexlo->xlo.pulXlate[i] =
472 PALETTE_ulGetNearestPaletteIndex(ppalDst, ulColor);
473
474 if (pexlo->xlo.pulXlate[i] != i)
475 pexlo->xlo.flXlate &= ~XO_TRIVIAL;
476 }
477
478 if (pexlo->xlo.flXlate & XO_TRIVIAL)
479 {
480 if (pexlo->xlo.pulXlate != pexlo->aulXlate)
481 {
482 EngFreeMem(pexlo->xlo.pulXlate);
483 pexlo->xlo.pulXlate = pexlo->aulXlate;
484 }
485 pexlo->pfnXlate = EXLATEOBJ_iXlateTrivial;
486 pexlo->xlo.flXlate = XO_TRIVIAL;
487 return;
488 }
489 }
490 else
491 {
492 // FIXME: use PALETTE_ulGetNearest
493 EXLATEOBJ exloTmp = *pexlo;
494 exloTmp.xlo.pulXlate = exloTmp.aulXlate;
495
496 pexlo->xlo.flXlate |= XO_TABLE;
497 for (i = 0; i < pexlo->xlo.cEntries; i++)
498 {
499 ulColor = RGB(ppalSrc->IndexedColors[i].peRed,
500 ppalSrc->IndexedColors[i].peGreen,
501 ppalSrc->IndexedColors[i].peBlue);
502 pexlo->xlo.pulXlate[i] =
503 EXLATEOBJ_iXlateShiftAndMask(&exloTmp, ulColor);
504 }
505 }
506 }
507 else if (ppalSrc->Mode & PAL_RGB)
508 {
509 if (ppalDst->Mode & PAL_INDEXED)
510 pexlo->pfnXlate = EXLATEOBJ_iXlateRGBtoPal;
511
512 else if (ppalDst->Mode & PAL_BGR)
513 pexlo->pfnXlate = EXLATEOBJ_iXlateRGBtoBGR;
514
515 else if (ppalDst->Mode & PAL_RGB16_555)
516 pexlo->pfnXlate = EXLATEOBJ_iXlateRGBto555;
517
518 else if (ppalDst->Mode & PAL_RGB16_565)
519 pexlo->pfnXlate = EXLATEOBJ_iXlateRGBto565;
520
521 else if (ppalDst->Mode & PAL_BITFIELDS)
522 pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
523 }
524 else if (ppalSrc->Mode & PAL_BGR)
525 {
526 if (ppalDst->Mode & PAL_INDEXED)
527 pexlo->pfnXlate = EXLATEOBJ_iXlateBitfieldsToPal;
528
529 else if (ppalDst->Mode & PAL_RGB)
530 /* The inverse function works the same */
531 pexlo->pfnXlate = EXLATEOBJ_iXlateRGBtoBGR;
532
533 else if (ppalDst->Mode & PAL_RGB16_555)
534 pexlo->pfnXlate = EXLATEOBJ_iXlateBGRto555;
535
536 else if (ppalDst->Mode & PAL_RGB16_565)
537 pexlo->pfnXlate = EXLATEOBJ_iXlateBGRto565;
538
539 else if (ppalDst->Mode & PAL_BITFIELDS)
540 pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
541 }
542 else if (ppalSrc->Mode & PAL_RGB16_555)
543 {
544 if (ppalDst->Mode & PAL_INDEXED)
545 pexlo->pfnXlate = EXLATEOBJ_iXlate555toPal;
546
547 else if (ppalDst->Mode & PAL_RGB)
548 pexlo->pfnXlate = EXLATEOBJ_iXlate555toRGB;
549
550 else if (ppalDst->Mode & PAL_BGR)
551 pexlo->pfnXlate = EXLATEOBJ_iXlate555toBGR;
552
553 else if (ppalDst->Mode & PAL_RGB16_565)
554 pexlo->pfnXlate = EXLATEOBJ_iXlate555to565;
555
556 else if (ppalDst->Mode & PAL_BITFIELDS)
557 pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
558 }
559 else if (ppalSrc->Mode & PAL_RGB16_565)
560 {
561 if (ppalDst->Mode & PAL_INDEXED)
562 pexlo->pfnXlate = EXLATEOBJ_iXlate565toPal;
563
564 else if (ppalDst->Mode & PAL_RGB)
565 pexlo->pfnXlate = EXLATEOBJ_iXlate565toRGB;
566
567 else if (ppalDst->Mode & PAL_BGR)
568 pexlo->pfnXlate = EXLATEOBJ_iXlate565toBGR;
569
570 else if (ppalDst->Mode & PAL_RGB16_555)
571 pexlo->pfnXlate = EXLATEOBJ_iXlate565to555;
572
573 else if (ppalDst->Mode & PAL_BITFIELDS)
574 pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
575 }
576 else if (ppalSrc->Mode & PAL_BITFIELDS)
577 {
578 if (ppalDst->Mode & PAL_INDEXED)
579 pexlo->pfnXlate = EXLATEOBJ_iXlateBitfieldsToPal;
580 else
581 pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
582 }
583
584 /* Check for a trivial shift and mask operation */
585 if (pexlo->pfnXlate == EXLATEOBJ_iXlateShiftAndMask &&
586 !pexlo->ulRedShift && !pexlo->ulGreenShift && !pexlo->ulBlueShift)
587 {
588 pexlo->pfnXlate = EXLATEOBJ_iXlateTrivial;
589 }
590
591 /* Check for trivial xlate */
592 if (pexlo->pfnXlate == EXLATEOBJ_iXlateTrivial)
593 pexlo->xlo.flXlate = XO_TRIVIAL;
594 else
595 pexlo->xlo.flXlate &= ~XO_TRIVIAL;
596 }
597
598 VOID
599 NTAPI
600 EXLATEOBJ_vInitXlateFromDCs(
601 EXLATEOBJ* pexlo,
602 PDC pdcSrc,
603 PDC pdcDst)
604 {
605 PSURFACE psurfDst, psurfSrc;
606 PPALETTE ppalSrc, ppalDst, ppalDstDc;
607
608 DPRINT("Enter EXLATEOBJ_vInitXlateFromDCs\n");
609
610 /* Do basic init */
611 EXLATEOBJ_vInitTrivial(pexlo);
612
613 psurfDst = pdcDst->dclevel.pSurface;
614 psurfSrc = pdcSrc->dclevel.pSurface;
615
616 if (psurfDst == psurfSrc)
617 {
618 return;
619 }
620
621 if (psurfSrc->hDIBPalette)
622 {
623 ppalSrc = PALETTE_ShareLockPalette(psurfSrc->hDIBPalette);
624 }
625 else if (psurfSrc->ppal)
626 {
627 ppalSrc = psurfSrc->ppal;
628 GDIOBJ_IncrementShareCount(&ppalSrc->BaseObject);
629 }
630 else
631 ppalSrc = PALETTE_ShareLockPalette(pdcSrc->ppdev->devinfo.hpalDefault);
632
633 if(!ppalSrc)
634 return;
635
636 if (psurfDst->hDIBPalette)
637 {
638 ppalDst = PALETTE_ShareLockPalette(psurfDst->hDIBPalette);
639 }
640 else if (psurfDst->ppal)
641 {
642 ppalDst = psurfDst->ppal;
643 GDIOBJ_IncrementShareCount(&ppalDst->BaseObject);
644 }
645 else
646 ppalDst = PALETTE_ShareLockPalette(pdcDst->ppdev->devinfo.hpalDefault);
647
648 if (!ppalDst)
649 {
650 PALETTE_ShareUnlockPalette(ppalSrc);
651 return;
652 }
653
654 ppalDstDc = pdcDst->dclevel.ppal;
655 ASSERT(ppalDstDc);
656
657 /* KB41464 details how to convert between mono and color */
658 if (psurfDst->SurfObj.iBitmapFormat == BMF_1BPP)
659 {
660 if (psurfSrc->SurfObj.iBitmapFormat != BMF_1BPP)
661 {
662 // HACK!! FIXME: 1bpp DDBs should have gpalMono already!
663 EXLATEOBJ_vInitialize(pexlo,
664 ppalSrc,
665 &gpalMono,
666 pdcSrc->pdcattr->crBackgroundClr,
667 pdcDst->pdcattr->crBackgroundClr,
668 pdcDst->pdcattr->crForegroundClr);
669 }
670 }
671 else if (psurfSrc->SurfObj.iBitmapFormat == BMF_1BPP && !psurfSrc->hSecure)
672 {
673 // HACK!! FIXME: 1bpp DDBs should have gpalMono already!
674 EXLATEOBJ_vInitialize(pexlo,
675 &gpalMono,
676 ppalDst,
677 0,
678 pdcDst->pdcattr->crBackgroundClr,
679 pdcDst->pdcattr->crForegroundClr);
680 }
681 else
682 {
683 EXLATEOBJ_vInitialize(pexlo, ppalSrc, ppalDst, 0, 0, 0);
684 }
685
686 PALETTE_ShareUnlockPalette(ppalDst);
687 PALETTE_ShareUnlockPalette(ppalSrc);
688 }
689
690
691 VOID
692 NTAPI
693 EXLATEOBJ_vInitBrushXlate(
694 PEXLATEOBJ pexlo,
695 BRUSH *pbrush,
696 SURFACE *psurfDst,
697 COLORREF crForegroundClr,
698 COLORREF crBackgroundClr)
699 {
700 PPALETTE ppalDst, ppalPattern;
701 SURFACE *psurfPattern;
702
703 ASSERT(pexlo);
704 ASSERT(pbrush);
705 ASSERT(psurfDst);
706 ASSERT(!(pbrush->flAttrs & (GDIBRUSH_IS_SOLID | GDIBRUSH_IS_NULL)));
707
708 EXLATEOBJ_vInitTrivial(pexlo);
709
710 if (psurfDst->hDIBPalette)
711 {
712 ppalDst = PALETTE_ShareLockPalette(psurfDst->hDIBPalette);
713 }
714 else if (psurfDst->ppal)
715 {
716 ppalDst = psurfDst->ppal;
717 GDIOBJ_IncrementShareCount(&ppalDst->BaseObject);
718 }
719 else
720 ppalDst = PALETTE_ShareLockPalette(pPrimarySurface->devinfo.hpalDefault);
721
722 if (!ppalDst)
723 {
724 DPRINT1("No ppalDst!\n");
725 return;
726 }
727
728 psurfPattern = SURFACE_ShareLockSurface(pbrush->hbmPattern);
729 if (!psurfPattern)
730 {
731 PALETTE_ShareUnlockPalette(ppalDst);
732 return;
733 }
734
735 #if 0
736 if (psurfDst->SurfObj.iBitmapFormat == BMF_1BPP)
737 {
738 if (psurfSrc->SurfObj.iBitmapFormat != BMF_1BPP)
739 {
740 // HACK!! FIXME: 1bpp DDBs should have gpalMono already!
741 EXLATEOBJ_vInitialize(pexlo,
742 ppalSrc,
743 &gpalMono,
744 0,
745 crBackgroundClr,
746 crForegroundClr);
747 }
748 }
749 else
750 #endif
751 if (psurfPattern->SurfObj.iBitmapFormat == BMF_1BPP &&
752 !(pbrush->flAttrs & GDIBRUSH_IS_DIB))
753 {
754 /* Special case: 1 bpp pattern, not a DIB brush. */
755 if (psurfDst->SurfObj.iBitmapFormat != BMF_1BPP)
756 {
757 // HACK!! FIXME: 1bpp DDBs should have gpalMono already!
758 EXLATEOBJ_vInitialize(pexlo,
759 &gpalMono,
760 ppalDst,
761 0,
762 crBackgroundClr,
763 crForegroundClr);
764 }
765 }
766 else
767 {
768 /* Default: use the patterns' palette */
769 ppalPattern = PALETTE_LockPalette(psurfPattern->hDIBPalette);
770 if (ppalPattern)
771 {
772 EXLATEOBJ_vInitialize(pexlo, &gpalRGB, ppalDst, 0, 0, 0);
773 PALETTE_UnlockPalette(ppalPattern);
774 }
775 }
776
777 PALETTE_ShareUnlockPalette(ppalDst);
778 SURFACE_ShareUnlockSurface(psurfPattern);
779 }
780
781 VOID
782 NTAPI
783 EXLATEOBJ_vCleanup(PEXLATEOBJ pexlo)
784 {
785 if (pexlo->xlo.pulXlate != pexlo->aulXlate)
786 {
787 EngFreeMem(pexlo->xlo.pulXlate);
788 }
789 pexlo->xlo.pulXlate = pexlo->aulXlate;
790 }
791
792 VOID
793 InitXlateImpl(VOID)
794 {
795
796 EXLATEOBJ_vInitTrivial(&gexloTrivial);
797 }
798
799
800 /** Public DDI Functions ******************************************************/
801
802 #undef XLATEOBJ_iXlate
803 ULONG
804 NTAPI
805 XLATEOBJ_iXlate(XLATEOBJ *pxlo, ULONG iColor)
806 {
807 PEXLATEOBJ pexlo = (PEXLATEOBJ)pxlo;
808
809 if (!pxlo)
810 return iColor;
811
812 /* Call the iXlate function */
813 return pexlo->pfnXlate(pexlo, iColor);
814 }
815
816 ULONG
817 NTAPI
818 XLATEOBJ_cGetPalette(XLATEOBJ *pxlo, ULONG iPal, ULONG cPal, ULONG *pPalOut)
819 {
820 PEXLATEOBJ pexlo = (PEXLATEOBJ)pxlo;
821 PPALETTE ppal;
822 INT i;
823
824 if (!pxlo)
825 {
826 return 0;
827 }
828
829 if (iPal > 5)
830 {
831 DPRINT1("XLATEOBJ_cGetPalette called with wrong iPal: %d\n", iPal);
832 return 0;
833 }
834
835 /* Get the requested palette */
836 if (iPal == XO_DESTDCPALETTE)
837 {
838 ppal = pexlo->ppalDstDc;
839 }
840 else if (iPal == XO_SRCPALETTE || iPal == XO_SRCBITFIELDS)
841 {
842 ppal = pexlo->ppalSrc;
843 }
844 else
845 {
846 ppal = pexlo->ppalDst;
847 }
848
849 /* Verify palette type match */
850 if (!ppal ||
851 ((iPal == XO_SRCPALETTE || iPal == XO_DESTPALETTE)
852 && !(ppal->Mode & PAL_INDEXED)) ||
853 ((iPal == XO_SRCBITFIELDS || iPal == XO_DESTBITFIELDS)
854 && !(ppal->Mode & PAL_BITFIELDS)))
855 {
856 return 0;
857 }
858
859 if(!pPalOut)
860 {
861 return ppal->NumColors;
862 }
863
864 /* Copy the values into the buffer */
865 if (ppal->Mode & PAL_INDEXED)
866 {
867 cPal = min(cPal, ppal->NumColors);
868 for (i = 0; i < cPal; i++)
869 {
870 pPalOut[i] = RGB(ppal->IndexedColors[i].peRed,
871 ppal->IndexedColors[i].peGreen,
872 ppal->IndexedColors[i].peBlue);
873 }
874 }
875 else
876 {
877 // FIXME: should use the above code
878 pPalOut[0] = ppal->RedMask;
879 pPalOut[1] = ppal->GreenMask;
880 pPalOut[2] = ppal->BlueMask;
881 }
882
883 return cPal;
884 }
885
886 HANDLE
887 NTAPI
888 XLATEOBJ_hGetColorTransform(XLATEOBJ *pxlo)
889 {
890 PEXLATEOBJ pexlo = (PEXLATEOBJ)pxlo;
891 return pexlo->hColorTransform;
892 }
893
894 PULONG
895 NTAPI
896 XLATEOBJ_piVector(XLATEOBJ *pxlo)
897 {
898 if (pxlo->iSrcType == PAL_INDEXED)
899 {
900 return pxlo->pulXlate;
901 }
902
903 return NULL;
904 }
905
906 /* EOF */