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