- Merge to trunk r37270.
[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 ForegroundColor,
362 ULONG BackgroundColor)
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 XlateObj->pulXlate[0] = ShiftAndMask(XlateGDI, BackgroundColor);
407 XlateObj->pulXlate[1] = ShiftAndMask(XlateGDI, ForegroundColor);
408
409 if (XlateObj->iDstType == PAL_INDEXED)
410 {
411 XlateObj->pulXlate[0] =
412 ClosestColorMatch(XlateGDI,
413 (LPPALETTEENTRY)&XlateObj->pulXlate[0],
414 DestPalGDI->IndexedColors,
415 DestPalGDI->NumColors);
416 XlateObj->pulXlate[1] =
417 ClosestColorMatch(XlateGDI,
418 (LPPALETTEENTRY)&XlateObj->pulXlate[1],
419 DestPalGDI->IndexedColors,
420 DestPalGDI->NumColors);
421 }
422
423 PALETTE_UnlockPalette(DestPalGDI);
424
425 return XlateObj;
426 }
427
428 HPALETTE FASTCALL
429 IntEngGetXlatePalette(XLATEOBJ *XlateObj,
430 ULONG Palette)
431 {
432 XLATEGDI *XlateGDI = ObjToGDI(XlateObj, XLATE);
433 switch (Palette)
434 {
435 case XO_DESTPALETTE:
436 return XlateGDI->DestPal;
437 break;
438
439 case XO_SRCPALETTE:
440 return XlateGDI->SourcePal;
441 break;
442 }
443 return 0;
444 }
445
446 XLATEOBJ*
447 FASTCALL
448 IntCreateXlateForBlt(PDC pDCDest, PDC pDCSrc, BITMAPOBJ* pDestSurf, BITMAPOBJ* pSrcSurf)
449 {
450 XLATEOBJ *XlateObj;
451 HPALETTE DestPalette, SourcePalette;
452 PDC_ATTR pDc_Attr;
453
454 DPRINT("Enter IntCreateXlateFromDCs\n");
455
456 if (pDestSurf == pSrcSurf)
457 {
458 return NULL;
459 }
460
461 DestPalette = pDestSurf->hDIBPalette;
462 if (!DestPalette) DestPalette = pPrimarySurface->DevInfo.hpalDefault;
463
464 SourcePalette = pSrcSurf->hDIBPalette;
465 if (!SourcePalette) SourcePalette = pPrimarySurface->DevInfo.hpalDefault;
466
467 DPRINT("DestPalette = %p, SourcePalette = %p, DefaultPatelle = %p\n", DestPalette, SourcePalette, NtGdiGetStockObject((INT)DEFAULT_PALETTE));
468
469 /* KB41464 details how to convert between mono and color */
470 if (pDestSurf->SurfObj.iBitmapFormat == BMF_1BPP)
471 {
472 if (pSrcSurf->SurfObj.iBitmapFormat == BMF_1BPP)
473 {
474 XlateObj = NULL;
475 }
476 else
477 {
478 pDc_Attr = pDCSrc->pDc_Attr;
479 if (!pDc_Attr) pDc_Attr = &pDCSrc->Dc_Attr;
480 XlateObj = IntEngCreateMonoXlate(0, DestPalette, SourcePalette, pDc_Attr->crBackgroundClr);
481 }
482 }
483 else
484 {
485 if (pSrcSurf->SurfObj.iBitmapFormat == BMF_1BPP)
486 {
487 pDc_Attr = pDCDest->pDc_Attr;
488 if (!pDc_Attr) pDc_Attr = &pDCDest->Dc_Attr;
489 XlateObj = IntEngCreateSrcMonoXlate(DestPalette, pDc_Attr->crBackgroundClr, pDc_Attr->crForegroundClr);
490 }
491 else
492 {
493 XlateObj = IntEngCreateXlate(0, 0, DestPalette, SourcePalette);
494 }
495 if (!XlateObj)
496 {
497 return (XLATEOBJ*)-1;
498 }
499 }
500 return XlateObj;
501 }
502
503 /* PUBLIC FUNCTIONS ***********************************************************/
504
505 /*
506 * @implemented /// this is not a public function!
507 */
508 VOID FASTCALL
509 EngDeleteXlate(XLATEOBJ *XlateObj)
510 {
511 XLATEGDI *XlateGDI;
512
513 if (XlateObj == NULL)
514 {
515 DPRINT1("Trying to delete NULL XLATEOBJ\n");
516 return;
517 }
518
519 XlateGDI = ObjToGDI(XlateObj, XLATE);
520
521 if (!XlateGDI) return;
522
523 if ((XlateObj->flXlate & XO_TABLE) &&
524 XlateObj->pulXlate != NULL)
525 {
526 EngFreeMem(XlateObj->pulXlate);
527 }
528
529 EngFreeMem(XlateGDI);
530 }
531
532 /*
533 * @implemented
534 */
535 PULONG STDCALL
536 XLATEOBJ_piVector(XLATEOBJ *XlateObj)
537 {
538 if (XlateObj->iSrcType == PAL_INDEXED)
539 {
540 return XlateObj->pulXlate;
541 }
542
543 return NULL;
544 }
545
546 /*
547 * @implemented
548 */
549 ULONG STDCALL
550 XLATEOBJ_iXlate(XLATEOBJ *XlateObj, ULONG Color)
551 {
552 XLATEGDI *XlateGDI;
553 PALGDI *PalGDI;
554 ULONG Closest;
555
556 /* Return the original color if there's no color translation object. */
557 if (!XlateObj)
558 return Color;
559
560 if (XlateObj->flXlate & XO_TRIVIAL)
561 return Color;
562
563 if (XlateObj->flXlate & XO_TABLE)
564 {
565 if (Color >= XlateObj->cEntries)
566 Color %= XlateObj->cEntries;
567
568 return XlateObj->pulXlate[Color];
569 }
570
571
572 if (XlateObj->flXlate & XO_TO_MONO)
573 return Color == XlateObj->pulXlate[0];
574
575 XlateGDI = ObjToGDI(XlateObj, XLATE);
576
577 if (XlateGDI->UseShiftAndMask)
578 return ShiftAndMask(XlateGDI, Color);
579
580 if (XlateObj->iSrcType == PAL_RGB || XlateObj->iSrcType == PAL_BGR ||
581 XlateObj->iSrcType == PAL_BITFIELDS)
582 {
583 /* FIXME: should we cache colors used often? */
584 /* FIXME: won't work if destination isn't indexed */
585
586 /* Convert the source color to the palette RGB format. */
587 Color = ShiftAndMask(XlateGDI, Color);
588
589 /* Extract the destination palette. */
590 PalGDI = PALETTE_LockPalette(XlateGDI->DestPal);
591 if(PalGDI != NULL)
592 {
593 /* Return closest match for the given color. */
594 Closest = ClosestColorMatch(XlateGDI, (LPPALETTEENTRY)&Color, PalGDI->IndexedColors, PalGDI->NumColors);
595 PALETTE_UnlockPalette(PalGDI);
596 return Closest;
597 }
598 }
599
600 return 0;
601 }
602
603 /*
604 * @implemented
605 */
606 ULONG STDCALL
607 XLATEOBJ_cGetPalette(XLATEOBJ *XlateObj, ULONG PalOutType, ULONG cPal,
608 ULONG *OutPal)
609 {
610 HPALETTE hPalette;
611 XLATEGDI *XlateGDI;
612 PALGDI *PalGDI;
613 ULONG *InPal;
614
615 XlateGDI = ObjToGDI(XlateObj, XLATE);
616 if (PalOutType == XO_SRCPALETTE)
617 hPalette = XlateGDI->SourcePal;
618 else if (PalOutType == XO_DESTPALETTE)
619 hPalette = XlateGDI->DestPal;
620 else
621 {
622 UNIMPLEMENTED;
623 return 0;
624 }
625
626 PalGDI = PALETTE_LockPalette(hPalette);
627 if(PalGDI != NULL)
628 {
629 /* copy the indexed colors into the buffer */
630
631 for(InPal = (ULONG*)PalGDI->IndexedColors;
632 cPal > 0;
633 cPal--, InPal++, OutPal++)
634 {
635 *OutPal = *InPal;
636 }
637
638 PALETTE_UnlockPalette(PalGDI);
639
640 return cPal;
641 }
642
643 return 0;
644 }
645
646 /* EOF */