Update IntEngCreateSrcMonoXlate parameter names and function call with brush colors...
[reactos.git] / reactos / subsystems / win32 / win32k / eng / xlate.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$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: GDI Color Translation Functions
24 * FILE: subsys/win32k/eng/xlate.c
25 * PROGRAMER: Jason Filby
26 * REVISION HISTORY:
27 * 8/20/1999: Created
28 */
29
30 #include <w32k.h>
31
32 #define NDEBUG
33 #include <debug.h>
34
35 static __inline ULONG
36 ShiftAndMask(XLATEGDI *XlateGDI, ULONG Color)
37 {
38 ULONG TranslatedColor;
39
40 if (XlateGDI->RedShift < 0)
41 TranslatedColor = (Color >> -(XlateGDI->RedShift)) & XlateGDI->RedMask;
42 else
43 TranslatedColor = (Color << XlateGDI->RedShift) & XlateGDI->RedMask;
44 if (XlateGDI->GreenShift < 0)
45 TranslatedColor |= (Color >> -(XlateGDI->GreenShift)) & XlateGDI->GreenMask;
46 else
47 TranslatedColor |= (Color << XlateGDI->GreenShift) & XlateGDI->GreenMask;
48 if (XlateGDI->BlueShift < 0)
49 TranslatedColor |= (Color >> -(XlateGDI->BlueShift)) & XlateGDI->BlueMask;
50 else
51 TranslatedColor |= (Color << XlateGDI->BlueShift) & XlateGDI->BlueMask;
52
53 return TranslatedColor;
54 }
55
56
57 static __inline ULONG
58 ClosestColorMatch(XLATEGDI *XlateGDI, LPPALETTEENTRY SourceColor,
59 PALETTEENTRY *DestColors, ULONG NumColors)
60 {
61 ULONG SourceRed, SourceGreen, SourceBlue;
62 ULONG cxRed, cxGreen, cxBlue, Rating, BestMatch = 0xFFFFFF;
63 ULONG CurrentIndex, BestIndex = 0;
64
65 SourceRed = SourceColor->peRed;
66 SourceGreen = SourceColor->peGreen;
67 SourceBlue = SourceColor->peBlue;
68
69 for (CurrentIndex = 0; CurrentIndex < NumColors; CurrentIndex++, DestColors++)
70 {
71 cxRed = abs((SHORT)SourceRed - (SHORT)DestColors->peRed);
72 cxRed *= cxRed;
73 cxGreen = abs((SHORT)SourceGreen - (SHORT)DestColors->peGreen);
74 cxGreen *= cxGreen;
75 cxBlue = abs((SHORT)SourceBlue - (SHORT)DestColors->peBlue);
76 cxBlue *= cxBlue;
77
78 Rating = cxRed + cxGreen + cxBlue;
79
80 if (Rating == 0)
81 {
82 /* Exact match */
83 BestIndex = CurrentIndex;
84 break;
85 }
86
87 if (Rating < BestMatch)
88 {
89 BestIndex = CurrentIndex;
90 BestMatch = Rating;
91 }
92 }
93
94 return BestIndex;
95 }
96
97 static __inline VOID
98 BitMasksFromPal(USHORT PalType, PPALGDI Palette,
99 PULONG RedMask, PULONG BlueMask, PULONG GreenMask)
100 {
101 static const union { PALETTEENTRY Color; ULONG Mask; } Red = {{0xFF, 0x00, 0x00}};
102 static const union { PALETTEENTRY Color; ULONG Mask; } Green = {{0x00, 0xFF, 0x00}};
103 static const union { PALETTEENTRY Color; ULONG Mask; } Blue = {{0x00, 0x00, 0xFF}};
104
105 switch (PalType)
106 {
107 case PAL_RGB:
108 *RedMask = RGB(0xFF, 0x00, 0x00);
109 *GreenMask = RGB(0x00, 0xFF, 0x00);
110 *BlueMask = RGB(0x00, 0x00, 0xFF);
111 break;
112 case PAL_BGR:
113 *RedMask = RGB(0x00, 0x00, 0xFF);
114 *GreenMask = RGB(0x00, 0xFF, 0x00);
115 *BlueMask = RGB(0xFF, 0x00, 0x00);
116 break;
117 case PAL_BITFIELDS:
118 *RedMask = Palette->RedMask;
119 *GreenMask = Palette->GreenMask;
120 *BlueMask = Palette->BlueMask;
121 break;
122 case PAL_INDEXED:
123 *RedMask = Red.Mask;
124 *GreenMask = Green.Mask;
125 *BlueMask = Blue.Mask;
126 break;
127 }
128 }
129
130 /*
131 * Calculate the number of bits Mask must be shift to the left to get a
132 * 1 in the most significant bit position
133 */
134 static __inline INT
135 CalculateShift(ULONG Mask)
136 {
137 ULONG Shift = 0;
138 ULONG LeftmostBit = 1 << (8 * sizeof(ULONG) - 1);
139
140 while (0 == (Mask & LeftmostBit) && Shift < 8 * sizeof(ULONG))
141 {
142 Mask = Mask << 1;
143 Shift++;
144 }
145
146 return Shift;
147 }
148
149 XLATEOBJ* FASTCALL
150 IntEngCreateXlate(USHORT DestPalType, USHORT SourcePalType,
151 HPALETTE PaletteDest, HPALETTE PaletteSource)
152 {
153 XLATEOBJ *XlateObj;
154 XLATEGDI *XlateGDI;
155 PALGDI *SourcePalGDI = 0;
156 PALGDI *DestPalGDI = 0;
157 ULONG SourceRedMask = 0, SourceGreenMask = 0, SourceBlueMask = 0;
158 ULONG DestRedMask = 0, DestGreenMask = 0, DestBlueMask = 0;
159 ULONG i;
160
161 ASSERT(SourcePalType || PaletteSource);
162 ASSERT(DestPalType || PaletteDest);
163
164 XlateGDI = EngAllocMem(0, sizeof(XLATEGDI), TAG_XLATEOBJ);
165 if (XlateGDI == NULL)
166 {
167 DPRINT1("Failed to allocate memory for a XLATE structure!\n");
168 return NULL;
169 }
170 XlateObj = GDIToObj(XlateGDI, XLATE);
171
172 if (PaletteSource != NULL)
173 SourcePalGDI = PALETTE_LockPalette(PaletteSource);
174 if (PaletteDest == PaletteSource)
175 DestPalGDI = SourcePalGDI;
176 else if (PaletteDest != NULL)
177 DestPalGDI = PALETTE_LockPalette(PaletteDest);
178
179 if (SourcePalType == 0)
180 SourcePalType = SourcePalGDI->Mode;
181 if (DestPalType == 0)
182 DestPalType = DestPalGDI->Mode;
183
184 XlateObj->iSrcType = SourcePalType;
185 XlateObj->iDstType = DestPalType;
186 XlateObj->flXlate = 0;
187 XlateObj->cEntries = 0;
188
189 /* Store handles of palettes in internal Xlate GDI object (or NULLs) */
190 XlateGDI->SourcePal = PaletteSource;
191 XlateGDI->DestPal = PaletteDest;
192
193 XlateGDI->UseShiftAndMask = FALSE;
194
195 /*
196 * Compute bit fiddeling constants unless both palettes are indexed, then
197 * we don't need them.
198 */
199 if (SourcePalType != PAL_INDEXED || DestPalType != PAL_INDEXED)
200 {
201 BitMasksFromPal(SourcePalType, SourcePalGDI, &SourceRedMask,
202 &SourceBlueMask, &SourceGreenMask);
203 BitMasksFromPal(DestPalType, DestPalGDI, &DestRedMask,
204 &DestBlueMask, &DestGreenMask);
205 XlateGDI->RedShift = CalculateShift(SourceRedMask) - CalculateShift(DestRedMask);
206 XlateGDI->RedMask = DestRedMask;
207 XlateGDI->GreenShift = CalculateShift(SourceGreenMask) - CalculateShift(DestGreenMask);
208 XlateGDI->GreenMask = DestGreenMask;
209 XlateGDI->BlueShift = CalculateShift(SourceBlueMask) - CalculateShift(DestBlueMask);
210 XlateGDI->BlueMask = DestBlueMask;
211 }
212
213 /* If source and destination palettes are the same or if they're RGB/BGR */
214 if (PaletteDest == PaletteSource ||
215 (DestPalType == PAL_RGB && SourcePalType == PAL_RGB) ||
216 (DestPalType == PAL_BGR && SourcePalType == PAL_BGR))
217 {
218 XlateObj->flXlate |= XO_TRIVIAL;
219 goto end;
220 }
221
222 /*
223 * If source and destination are bitfield based (RGB and BGR are just
224 * special bitfields) we can use simple shifting.
225 */
226 if ((DestPalType == PAL_RGB || DestPalType == PAL_BGR ||
227 DestPalType == PAL_BITFIELDS) &&
228 (SourcePalType == PAL_RGB || SourcePalType == PAL_BGR ||
229 SourcePalType == PAL_BITFIELDS))
230 {
231 if (SourceRedMask == DestRedMask &&
232 SourceBlueMask == DestBlueMask &&
233 SourceGreenMask == DestGreenMask)
234 {
235 XlateObj->flXlate |= XO_TRIVIAL;
236 }
237 XlateGDI->UseShiftAndMask = TRUE;
238 goto end;
239 }
240
241 /* Indexed -> Indexed */
242 if (SourcePalType == PAL_INDEXED && DestPalType == PAL_INDEXED)
243 {
244 XlateObj->cEntries = SourcePalGDI->NumColors;
245 XlateObj->pulXlate =
246 EngAllocMem(0, sizeof(ULONG) * XlateObj->cEntries, TAG_XLATEOBJ);
247
248 XlateObj->flXlate |= XO_TRIVIAL;
249 for (i = 0; i < XlateObj->cEntries; i++)
250 {
251 XlateObj->pulXlate[i] = ClosestColorMatch(
252 XlateGDI, SourcePalGDI->IndexedColors + i,
253 DestPalGDI->IndexedColors, XlateObj->cEntries);
254 if (XlateObj->pulXlate[i] != i)
255 XlateObj->flXlate &= ~XO_TRIVIAL;
256 }
257
258 XlateObj->flXlate |= XO_TABLE;
259 goto end;
260 }
261
262 /* Indexed -> Bitfields/RGB/BGR */
263 if (SourcePalType == PAL_INDEXED)
264 {
265 XlateObj->cEntries = SourcePalGDI->NumColors;
266 XlateObj->pulXlate =
267 EngAllocMem(0, sizeof(ULONG) * XlateObj->cEntries, TAG_XLATEOBJ);
268 for (i = 0; i < XlateObj->cEntries; i++)
269 XlateObj->pulXlate[i] =
270 ShiftAndMask(XlateGDI, *((ULONG *)&SourcePalGDI->IndexedColors[i]));
271 XlateObj->flXlate |= XO_TABLE;
272 goto end;
273 }
274
275 /*
276 * Last case: Bitfields/RGB/BGR -> Indexed
277 * isn't handled here yet and all the logic is in XLATEOBJ_iXlate now.
278 */
279
280 end:
281 if (PaletteDest != NULL)
282 if (PaletteDest != PaletteSource)
283 if (DestPalGDI != NULL)
284 PALETTE_UnlockPalette(DestPalGDI);
285
286
287 if (PaletteSource != NULL)
288 PALETTE_UnlockPalette(SourcePalGDI);
289
290 return XlateObj;
291 }
292
293 XLATEOBJ* FASTCALL
294 IntEngCreateMonoXlate(
295 USHORT SourcePalType, HPALETTE PaletteDest, HPALETTE PaletteSource,
296 ULONG BackgroundColor)
297 {
298 XLATEOBJ *XlateObj;
299 XLATEGDI *XlateGDI;
300 PALGDI *SourcePalGDI;
301
302 XlateGDI = EngAllocMem(0, sizeof(XLATEGDI), TAG_XLATEOBJ);
303 if (XlateGDI == NULL)
304 {
305 DPRINT1("Failed to allocate memory for a XLATE structure!\n");
306 return NULL;
307 }
308 XlateObj = GDIToObj(XlateGDI, XLATE);
309
310 SourcePalGDI = PALETTE_LockPalette(PaletteSource);
311 /* FIXME - SourcePalGDI can be NULL!!! Handle this case instead of ASSERT! */
312 ASSERT(SourcePalGDI);
313
314 if (SourcePalType == 0)
315 SourcePalType = SourcePalGDI->Mode;
316
317 XlateObj->iSrcType = SourcePalType;
318 XlateObj->iDstType = PAL_INDEXED;
319
320 /* Store handles of palettes in internal Xlate GDI object (or NULLs) */
321 XlateGDI->DestPal = PaletteDest;
322 XlateGDI->SourcePal = PaletteSource;
323
324 XlateObj->flXlate = XO_TO_MONO;
325 XlateObj->cEntries = 1;
326 XlateObj->pulXlate = &XlateGDI->BackgroundColor;
327 switch (SourcePalType)
328 {
329 case PAL_INDEXED:
330 XlateGDI->BackgroundColor = NtGdiGetNearestPaletteIndex(
331 PaletteSource, BackgroundColor);
332 break;
333 case PAL_BGR:
334 XlateGDI->BackgroundColor = BackgroundColor;
335 break;
336 case PAL_RGB:
337 XlateGDI->BackgroundColor =
338 ((BackgroundColor & 0xFF) << 16) |
339 ((BackgroundColor & 0xFF0000) >> 16) |
340 (BackgroundColor & 0xFF00);
341 break;
342 case PAL_BITFIELDS:
343 {
344 BitMasksFromPal(SourcePalType, SourcePalGDI, &XlateGDI->RedMask,
345 &XlateGDI->BlueMask, &XlateGDI->GreenMask);
346 XlateGDI->RedShift = CalculateShift(0xFF) - CalculateShift(XlateGDI->RedMask);
347 XlateGDI->GreenShift = CalculateShift(0xFF00) - CalculateShift(XlateGDI->GreenMask);
348 XlateGDI->BlueShift = CalculateShift(0xFF0000) - CalculateShift(XlateGDI->BlueMask);
349 XlateGDI->BackgroundColor = ShiftAndMask(XlateGDI, BackgroundColor);
350 }
351 break;
352 }
353
354 PALETTE_UnlockPalette(SourcePalGDI);
355
356 return XlateObj;
357 }
358
359 XLATEOBJ* FASTCALL
360 IntEngCreateSrcMonoXlate(HPALETTE PaletteDest,
361 ULONG Color0,
362 ULONG Color1)
363 {
364 XLATEOBJ *XlateObj;
365 XLATEGDI *XlateGDI;
366 PALGDI *DestPalGDI;
367
368 DestPalGDI = PALETTE_LockPalette(PaletteDest);
369 if (DestPalGDI == NULL)
370 return NULL;
371
372 XlateGDI = EngAllocMem(0, sizeof(XLATEGDI), TAG_XLATEOBJ);
373 if (XlateGDI == NULL)
374 {
375 PALETTE_UnlockPalette(DestPalGDI);
376 DPRINT1("Failed to allocate memory for a XLATE structure!\n");
377 return NULL;
378 }
379 XlateObj = GDIToObj(XlateGDI, XLATE);
380
381 XlateObj->cEntries = 2;
382 XlateObj->pulXlate = EngAllocMem(0, sizeof(ULONG) * XlateObj->cEntries, TAG_XLATEOBJ);
383 if (XlateObj->pulXlate == NULL)
384 {
385 PALETTE_UnlockPalette(DestPalGDI);
386 EngFreeMem(XlateGDI);
387 return NULL;
388 }
389
390 XlateObj->iSrcType = PAL_INDEXED;
391 XlateObj->iDstType = DestPalGDI->Mode;
392
393 /* Store handles of palettes in internal Xlate GDI object (or NULLs) */
394 XlateGDI->SourcePal = NULL;
395 XlateGDI->DestPal = PaletteDest;
396
397 XlateObj->flXlate = XO_TABLE;
398
399 BitMasksFromPal(DestPalGDI->Mode, DestPalGDI, &XlateGDI->RedMask,
400 &XlateGDI->BlueMask, &XlateGDI->GreenMask);
401
402 XlateGDI->RedShift = CalculateShift(RGB(0xFF, 0x00, 0x00)) - CalculateShift(XlateGDI->RedMask);
403 XlateGDI->GreenShift = CalculateShift(RGB(0x00, 0xFF, 0x00)) - CalculateShift(XlateGDI->GreenMask);
404 XlateGDI->BlueShift = CalculateShift(RGB(0x00, 0x00, 0xFF)) - CalculateShift(XlateGDI->BlueMask);
405
406 /* Yes, that's how Windows works, ... */
407 XlateObj->pulXlate[1] = ShiftAndMask(XlateGDI, Color1);
408 XlateObj->pulXlate[0] = ShiftAndMask(XlateGDI, Color0);
409
410 if (XlateObj->iDstType == PAL_INDEXED)
411 {
412 XlateObj->pulXlate[0] =
413 ClosestColorMatch(XlateGDI,
414 (LPPALETTEENTRY)&XlateObj->pulXlate[0],
415 DestPalGDI->IndexedColors,
416 DestPalGDI->NumColors);
417 XlateObj->pulXlate[1] =
418 ClosestColorMatch(XlateGDI,
419 (LPPALETTEENTRY)&XlateObj->pulXlate[1],
420 DestPalGDI->IndexedColors,
421 DestPalGDI->NumColors);
422 }
423
424 PALETTE_UnlockPalette(DestPalGDI);
425
426 return XlateObj;
427 }
428
429 HPALETTE FASTCALL
430 IntEngGetXlatePalette(XLATEOBJ *XlateObj,
431 ULONG Palette)
432 {
433 XLATEGDI *XlateGDI = ObjToGDI(XlateObj, XLATE);
434 switch (Palette)
435 {
436 case XO_DESTPALETTE:
437 return XlateGDI->DestPal;
438 break;
439
440 case XO_SRCPALETTE:
441 return XlateGDI->SourcePal;
442 break;
443 }
444 return 0;
445 }
446
447 XLATEOBJ*
448 FASTCALL
449 IntCreateXlateForBlt(PDC pDCDest, PDC pDCSrc, SURFACE* psurfDest, SURFACE* psurfSrc)
450 {
451 XLATEOBJ *XlateObj;
452 HPALETTE DestPalette, SourcePalette;
453 PDC_ATTR pDc_Attr;
454
455 DPRINT("Enter IntCreateXlateFromDCs\n");
456
457 if (psurfDest == psurfSrc)
458 {
459 return NULL;
460 }
461
462 DestPalette = psurfDest->hDIBPalette;
463 if (!DestPalette) DestPalette = pPrimarySurface->DevInfo.hpalDefault;
464
465 SourcePalette = psurfSrc->hDIBPalette;
466 if (!SourcePalette) SourcePalette = pPrimarySurface->DevInfo.hpalDefault;
467
468 DPRINT("DestPalette = %p, SourcePalette = %p, DefaultPatelle = %p\n", DestPalette, SourcePalette, NtGdiGetStockObject((INT)DEFAULT_PALETTE));
469
470 /* KB41464 details how to convert between mono and color */
471 if (psurfDest->SurfObj.iBitmapFormat == BMF_1BPP)
472 {
473 if (psurfSrc->SurfObj.iBitmapFormat == BMF_1BPP)
474 {
475 XlateObj = NULL;
476 }
477 else
478 {
479 pDc_Attr = pDCSrc->pDc_Attr;
480 if (!pDc_Attr) pDc_Attr = &pDCSrc->Dc_Attr;
481 XlateObj = IntEngCreateMonoXlate(0, DestPalette, SourcePalette, pDc_Attr->crBackgroundClr);
482 }
483 }
484 else
485 {
486 if (psurfSrc->SurfObj.iBitmapFormat == BMF_1BPP)
487 {
488 /* DIB sections need special handling */
489 if (psurfSrc->hSecure)
490 {
491 PPALGDI ppal = PALETTE_LockPalette(psurfSrc->hDIBPalette);
492 if (ppal)
493 {
494 XlateObj = IntEngCreateSrcMonoXlate(DestPalette, ((ULONG*)ppal->IndexedColors)[0], ((ULONG*)ppal->IndexedColors)[1]);
495 PALETTE_UnlockPalette(ppal);
496 }
497 else
498 XlateObj = NULL;
499 }
500 else
501 {
502 pDc_Attr = pDCDest->pDc_Attr;
503 if (!pDc_Attr) pDc_Attr = &pDCDest->Dc_Attr;
504 XlateObj = IntEngCreateSrcMonoXlate(DestPalette, pDc_Attr->crForegroundClr, pDc_Attr->crBackgroundClr);
505 }
506 }
507 else
508 {
509 XlateObj = IntEngCreateXlate(0, 0, DestPalette, SourcePalette);
510 }
511 if (!XlateObj)
512 {
513 return (XLATEOBJ*)-1;
514 }
515 }
516 return XlateObj;
517 }
518
519 /* PUBLIC FUNCTIONS ***********************************************************/
520
521 /*
522 * @implemented /// this is not a public function!
523 */
524 VOID FASTCALL
525 EngDeleteXlate(XLATEOBJ *XlateObj)
526 {
527 XLATEGDI *XlateGDI;
528
529 if (XlateObj == NULL)
530 {
531 DPRINT1("Trying to delete NULL XLATEOBJ\n");
532 return;
533 }
534
535 XlateGDI = ObjToGDI(XlateObj, XLATE);
536
537 if (!XlateGDI) return;
538
539 if ((XlateObj->flXlate & XO_TABLE) &&
540 XlateObj->pulXlate != NULL)
541 {
542 EngFreeMem(XlateObj->pulXlate);
543 }
544
545 EngFreeMem(XlateGDI);
546 }
547
548 /*
549 * @implemented
550 */
551 PULONG APIENTRY
552 XLATEOBJ_piVector(XLATEOBJ *XlateObj)
553 {
554 if (XlateObj->iSrcType == PAL_INDEXED)
555 {
556 return XlateObj->pulXlate;
557 }
558
559 return NULL;
560 }
561
562 /*
563 * @implemented
564 */
565 ULONG APIENTRY
566 XLATEOBJ_iXlate(XLATEOBJ *XlateObj, ULONG Color)
567 {
568 XLATEGDI *XlateGDI;
569 PALGDI *PalGDI;
570 ULONG Closest;
571
572 /* Return the original color if there's no color translation object. */
573 if (!XlateObj)
574 return Color;
575
576 if (XlateObj->flXlate & XO_TRIVIAL)
577 return Color;
578
579 if (XlateObj->flXlate & XO_TABLE)
580 {
581 if (Color >= XlateObj->cEntries)
582 Color %= XlateObj->cEntries;
583
584 return XlateObj->pulXlate[Color];
585 }
586
587
588 if (XlateObj->flXlate & XO_TO_MONO)
589 return Color == XlateObj->pulXlate[0];
590
591 XlateGDI = ObjToGDI(XlateObj, XLATE);
592
593 if (XlateGDI->UseShiftAndMask)
594 return ShiftAndMask(XlateGDI, Color);
595
596 if (XlateObj->iSrcType == PAL_RGB || XlateObj->iSrcType == PAL_BGR ||
597 XlateObj->iSrcType == PAL_BITFIELDS)
598 {
599 /* FIXME: should we cache colors used often? */
600 /* FIXME: won't work if destination isn't indexed */
601
602 /* Convert the source color to the palette RGB format. */
603 Color = ShiftAndMask(XlateGDI, Color);
604
605 /* Extract the destination palette. */
606 PalGDI = PALETTE_LockPalette(XlateGDI->DestPal);
607 if(PalGDI != NULL)
608 {
609 /* Return closest match for the given color. */
610 Closest = ClosestColorMatch(XlateGDI, (LPPALETTEENTRY)&Color, PalGDI->IndexedColors, PalGDI->NumColors);
611 PALETTE_UnlockPalette(PalGDI);
612 return Closest;
613 }
614 }
615
616 return 0;
617 }
618
619 /*
620 * @implemented
621 */
622 ULONG APIENTRY
623 XLATEOBJ_cGetPalette(XLATEOBJ *XlateObj, ULONG PalOutType, ULONG cPal,
624 ULONG *OutPal)
625 {
626 HPALETTE hPalette;
627 XLATEGDI *XlateGDI;
628 PALGDI *PalGDI;
629 ULONG *InPal;
630
631 XlateGDI = ObjToGDI(XlateObj, XLATE);
632 if (PalOutType == XO_SRCPALETTE)
633 hPalette = XlateGDI->SourcePal;
634 else if (PalOutType == XO_DESTPALETTE)
635 hPalette = XlateGDI->DestPal;
636 else
637 {
638 UNIMPLEMENTED;
639 return 0;
640 }
641
642 PalGDI = PALETTE_LockPalette(hPalette);
643 if(PalGDI != NULL)
644 {
645 /* copy the indexed colors into the buffer */
646
647 for(InPal = (ULONG*)PalGDI->IndexedColors;
648 cPal > 0;
649 cPal--, InPal++, OutPal++)
650 {
651 *OutPal = *InPal;
652 }
653
654 PALETTE_UnlockPalette(PalGDI);
655
656 return cPal;
657 }
658
659 return 0;
660 }
661
662 /* EOF */