Return NULL, if failed to lock the provided palette in InrEngCreateXlate. Fixes bug...
[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, PPALETTE 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 PALETTE *SourcePalGDI = 0;
156 PALETTE *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 {
181 if (!SourcePalGDI)
182 {
183 DPRINT1("Failed to lock source palette %p\n", PaletteSource);
184 return NULL;
185 }
186 SourcePalType = SourcePalGDI->Mode;
187 }
188 if (DestPalType == 0)
189 {
190 if (!DestPalGDI)
191 {
192 DPRINT1("Failed to lock dest palette %p\n", PaletteDest);
193 return NULL;
194 }
195 DestPalType = DestPalGDI->Mode;
196 }
197
198 XlateObj->iSrcType = SourcePalType;
199 XlateObj->iDstType = DestPalType;
200 XlateObj->flXlate = 0;
201 XlateObj->cEntries = 0;
202
203 /* Store handles of palettes in internal Xlate GDI object (or NULLs) */
204 XlateGDI->SourcePal = PaletteSource;
205 XlateGDI->DestPal = PaletteDest;
206
207 XlateGDI->UseShiftAndMask = FALSE;
208
209 /*
210 * Compute bit fiddeling constants unless both palettes are indexed, then
211 * we don't need them.
212 */
213 if (SourcePalType != PAL_INDEXED || DestPalType != PAL_INDEXED)
214 {
215 BitMasksFromPal(SourcePalType, SourcePalGDI, &SourceRedMask,
216 &SourceBlueMask, &SourceGreenMask);
217 BitMasksFromPal(DestPalType, DestPalGDI, &DestRedMask,
218 &DestBlueMask, &DestGreenMask);
219 XlateGDI->RedShift = CalculateShift(SourceRedMask) - CalculateShift(DestRedMask);
220 XlateGDI->RedMask = DestRedMask;
221 XlateGDI->GreenShift = CalculateShift(SourceGreenMask) - CalculateShift(DestGreenMask);
222 XlateGDI->GreenMask = DestGreenMask;
223 XlateGDI->BlueShift = CalculateShift(SourceBlueMask) - CalculateShift(DestBlueMask);
224 XlateGDI->BlueMask = DestBlueMask;
225 }
226
227 /* If source and destination palettes are the same or if they're RGB/BGR */
228 if (PaletteDest == PaletteSource ||
229 (DestPalType == PAL_RGB && SourcePalType == PAL_RGB) ||
230 (DestPalType == PAL_BGR && SourcePalType == PAL_BGR))
231 {
232 XlateObj->flXlate |= XO_TRIVIAL;
233 goto end;
234 }
235
236 /*
237 * If source and destination are bitfield based (RGB and BGR are just
238 * special bitfields) we can use simple shifting.
239 */
240 if ((DestPalType == PAL_RGB || DestPalType == PAL_BGR ||
241 DestPalType == PAL_BITFIELDS) &&
242 (SourcePalType == PAL_RGB || SourcePalType == PAL_BGR ||
243 SourcePalType == PAL_BITFIELDS))
244 {
245 if (SourceRedMask == DestRedMask &&
246 SourceBlueMask == DestBlueMask &&
247 SourceGreenMask == DestGreenMask)
248 {
249 XlateObj->flXlate |= XO_TRIVIAL;
250 }
251 XlateGDI->UseShiftAndMask = TRUE;
252 goto end;
253 }
254
255 /* Indexed -> Indexed */
256 if (SourcePalType == PAL_INDEXED && DestPalType == PAL_INDEXED)
257 {
258 XlateObj->cEntries = SourcePalGDI->NumColors;
259 XlateObj->pulXlate =
260 EngAllocMem(0, sizeof(ULONG) * XlateObj->cEntries, TAG_XLATEOBJ);
261
262 XlateObj->flXlate |= XO_TRIVIAL;
263 for (i = 0; i < XlateObj->cEntries; i++)
264 {
265 XlateObj->pulXlate[i] = ClosestColorMatch(
266 XlateGDI, SourcePalGDI->IndexedColors + i,
267 DestPalGDI->IndexedColors, DestPalGDI->NumColors);
268 if (XlateObj->pulXlate[i] != i)
269 XlateObj->flXlate &= ~XO_TRIVIAL;
270 }
271
272 XlateObj->flXlate |= XO_TABLE;
273 goto end;
274 }
275
276 /* Indexed -> Bitfields/RGB/BGR */
277 if (SourcePalType == PAL_INDEXED)
278 {
279 XlateObj->cEntries = SourcePalGDI->NumColors;
280 XlateObj->pulXlate =
281 EngAllocMem(0, sizeof(ULONG) * XlateObj->cEntries, TAG_XLATEOBJ);
282 for (i = 0; i < XlateObj->cEntries; i++)
283 XlateObj->pulXlate[i] =
284 ShiftAndMask(XlateGDI, *((ULONG *)&SourcePalGDI->IndexedColors[i]));
285 XlateObj->flXlate |= XO_TABLE;
286 goto end;
287 }
288
289 /*
290 * Last case: Bitfields/RGB/BGR -> Indexed
291 * isn't handled here yet and all the logic is in XLATEOBJ_iXlate now.
292 */
293
294 end:
295 if (PaletteDest != NULL)
296 if (PaletteDest != PaletteSource)
297 if (DestPalGDI != NULL)
298 PALETTE_UnlockPalette(DestPalGDI);
299
300
301 if (PaletteSource != NULL)
302 PALETTE_UnlockPalette(SourcePalGDI);
303
304 return XlateObj;
305 }
306
307 XLATEOBJ* FASTCALL
308 IntEngCreateMonoXlate(
309 USHORT SourcePalType, HPALETTE PaletteDest, HPALETTE PaletteSource,
310 ULONG BackgroundColor)
311 {
312 XLATEOBJ *XlateObj;
313 XLATEGDI *XlateGDI;
314 PALETTE *SourcePalGDI;
315
316 XlateGDI = EngAllocMem(0, sizeof(XLATEGDI), TAG_XLATEOBJ);
317 if (XlateGDI == NULL)
318 {
319 DPRINT1("Failed to allocate memory for a XLATE structure!\n");
320 return NULL;
321 }
322 XlateObj = GDIToObj(XlateGDI, XLATE);
323
324 SourcePalGDI = PALETTE_LockPalette(PaletteSource);
325 /* FIXME - SourcePalGDI can be NULL!!! Handle this case instead of ASSERT! */
326 ASSERT(SourcePalGDI);
327
328 if (SourcePalType == 0)
329 SourcePalType = SourcePalGDI->Mode;
330
331 XlateObj->iSrcType = SourcePalType;
332 XlateObj->iDstType = PAL_INDEXED;
333
334 /* Store handles of palettes in internal Xlate GDI object (or NULLs) */
335 XlateGDI->DestPal = PaletteDest;
336 XlateGDI->SourcePal = PaletteSource;
337
338 XlateObj->flXlate = XO_TO_MONO;
339 XlateObj->cEntries = 1;
340 XlateObj->pulXlate = &XlateGDI->BackgroundColor;
341 switch (SourcePalType)
342 {
343 case PAL_INDEXED:
344 XlateGDI->BackgroundColor = NtGdiGetNearestPaletteIndex(
345 PaletteSource, BackgroundColor);
346 break;
347 case PAL_BGR:
348 XlateGDI->BackgroundColor = BackgroundColor;
349 break;
350 case PAL_RGB:
351 XlateGDI->BackgroundColor =
352 ((BackgroundColor & 0xFF) << 16) |
353 ((BackgroundColor & 0xFF0000) >> 16) |
354 (BackgroundColor & 0xFF00);
355 break;
356 case PAL_BITFIELDS:
357 {
358 BitMasksFromPal(SourcePalType, SourcePalGDI, &XlateGDI->RedMask,
359 &XlateGDI->BlueMask, &XlateGDI->GreenMask);
360 XlateGDI->RedShift = CalculateShift(0xFF) - CalculateShift(XlateGDI->RedMask);
361 XlateGDI->GreenShift = CalculateShift(0xFF00) - CalculateShift(XlateGDI->GreenMask);
362 XlateGDI->BlueShift = CalculateShift(0xFF0000) - CalculateShift(XlateGDI->BlueMask);
363 XlateGDI->BackgroundColor = ShiftAndMask(XlateGDI, BackgroundColor);
364 }
365 break;
366 }
367
368 PALETTE_UnlockPalette(SourcePalGDI);
369
370 return XlateObj;
371 }
372
373 XLATEOBJ* FASTCALL
374 IntEngCreateSrcMonoXlate(HPALETTE PaletteDest,
375 ULONG Color0,
376 ULONG Color1)
377 {
378 XLATEOBJ *XlateObj;
379 XLATEGDI *XlateGDI;
380 PALETTE *DestPalGDI;
381
382 DestPalGDI = PALETTE_LockPalette(PaletteDest);
383 if (DestPalGDI == NULL)
384 return NULL;
385
386 XlateGDI = EngAllocMem(0, sizeof(XLATEGDI), TAG_XLATEOBJ);
387 if (XlateGDI == NULL)
388 {
389 PALETTE_UnlockPalette(DestPalGDI);
390 DPRINT1("Failed to allocate memory for a XLATE structure!\n");
391 return NULL;
392 }
393 XlateObj = GDIToObj(XlateGDI, XLATE);
394
395 XlateObj->cEntries = 2;
396 XlateObj->pulXlate = EngAllocMem(0, sizeof(ULONG) * XlateObj->cEntries, TAG_XLATEOBJ);
397 if (XlateObj->pulXlate == NULL)
398 {
399 PALETTE_UnlockPalette(DestPalGDI);
400 EngFreeMem(XlateGDI);
401 return NULL;
402 }
403
404 XlateObj->iSrcType = PAL_INDEXED;
405 XlateObj->iDstType = DestPalGDI->Mode;
406
407 /* Store handles of palettes in internal Xlate GDI object (or NULLs) */
408 XlateGDI->SourcePal = NULL;
409 XlateGDI->DestPal = PaletteDest;
410
411 XlateObj->flXlate = XO_TABLE;
412
413 BitMasksFromPal(DestPalGDI->Mode, DestPalGDI, &XlateGDI->RedMask,
414 &XlateGDI->BlueMask, &XlateGDI->GreenMask);
415
416 XlateGDI->RedShift = CalculateShift(RGB(0xFF, 0x00, 0x00)) - CalculateShift(XlateGDI->RedMask);
417 XlateGDI->GreenShift = CalculateShift(RGB(0x00, 0xFF, 0x00)) - CalculateShift(XlateGDI->GreenMask);
418 XlateGDI->BlueShift = CalculateShift(RGB(0x00, 0x00, 0xFF)) - CalculateShift(XlateGDI->BlueMask);
419
420 /* Yes, that's how Windows works, ... */
421 XlateObj->pulXlate[1] = ShiftAndMask(XlateGDI, Color1);
422 XlateObj->pulXlate[0] = ShiftAndMask(XlateGDI, Color0);
423
424 if (XlateObj->iDstType == PAL_INDEXED)
425 {
426 XlateObj->pulXlate[0] =
427 ClosestColorMatch(XlateGDI,
428 (LPPALETTEENTRY)&XlateObj->pulXlate[0],
429 DestPalGDI->IndexedColors,
430 DestPalGDI->NumColors);
431 XlateObj->pulXlate[1] =
432 ClosestColorMatch(XlateGDI,
433 (LPPALETTEENTRY)&XlateObj->pulXlate[1],
434 DestPalGDI->IndexedColors,
435 DestPalGDI->NumColors);
436 }
437
438 PALETTE_UnlockPalette(DestPalGDI);
439
440 return XlateObj;
441 }
442
443 HPALETTE FASTCALL
444 IntEngGetXlatePalette(XLATEOBJ *XlateObj,
445 ULONG Palette)
446 {
447 XLATEGDI *XlateGDI = ObjToGDI(XlateObj, XLATE);
448 switch (Palette)
449 {
450 case XO_DESTPALETTE:
451 return XlateGDI->DestPal;
452 break;
453
454 case XO_SRCPALETTE:
455 return XlateGDI->SourcePal;
456 break;
457 }
458 return 0;
459 }
460
461 XLATEOBJ*
462 FASTCALL
463 IntCreateXlateForBlt(PDC pDCDest, PDC pDCSrc, SURFACE* psurfDest, SURFACE* psurfSrc)
464 {
465 XLATEOBJ *XlateObj;
466 HPALETTE DestPalette, SourcePalette;
467 PDC_ATTR pdcattr;
468
469 DPRINT("Enter IntCreateXlateFromDCs\n");
470
471 if (psurfDest == psurfSrc)
472 {
473 return NULL;
474 }
475
476 DestPalette = psurfDest->hDIBPalette;
477 if (!DestPalette) DestPalette = pPrimarySurface->DevInfo.hpalDefault;
478
479 SourcePalette = psurfSrc->hDIBPalette;
480 if (!SourcePalette) SourcePalette = pPrimarySurface->DevInfo.hpalDefault;
481
482 DPRINT("DestPalette = %p, SourcePalette = %p, DefaultPatelle = %p\n", DestPalette, SourcePalette, NtGdiGetStockObject((INT)DEFAULT_PALETTE));
483
484 /* KB41464 details how to convert between mono and color */
485 if (psurfDest->SurfObj.iBitmapFormat == BMF_1BPP)
486 {
487 if (psurfSrc->SurfObj.iBitmapFormat == BMF_1BPP)
488 {
489 XlateObj = NULL;
490 }
491 else
492 {
493 pdcattr = pDCSrc->pdcattr;
494 XlateObj = IntEngCreateMonoXlate(0, DestPalette, SourcePalette, pdcattr->crBackgroundClr);
495 }
496 }
497 else
498 {
499 if (psurfSrc->SurfObj.iBitmapFormat == BMF_1BPP)
500 {
501 /* DIB sections need special handling */
502 if (psurfSrc->hSecure)
503 {
504 PPALETTE ppal = PALETTE_LockPalette(psurfSrc->hDIBPalette);
505 if (ppal)
506 {
507 XlateObj = IntEngCreateSrcMonoXlate(DestPalette, ((ULONG*)ppal->IndexedColors)[0], ((ULONG*)ppal->IndexedColors)[1]);
508 PALETTE_UnlockPalette(ppal);
509 }
510 else
511 XlateObj = NULL;
512 }
513 else
514 {
515 pdcattr = pDCDest->pdcattr;
516 XlateObj = IntEngCreateSrcMonoXlate(DestPalette, pdcattr->crForegroundClr, pdcattr->crBackgroundClr);
517 }
518 }
519 else
520 {
521 XlateObj = IntEngCreateXlate(0, 0, DestPalette, SourcePalette);
522 }
523 if (!XlateObj)
524 {
525 return (XLATEOBJ*)-1;
526 }
527 }
528 return XlateObj;
529 }
530
531 /* PUBLIC FUNCTIONS ***********************************************************/
532
533 /*
534 * @implemented /// this is not a public function!
535 */
536 VOID FASTCALL
537 EngDeleteXlate(XLATEOBJ *XlateObj)
538 {
539 XLATEGDI *XlateGDI;
540
541 if (XlateObj == NULL)
542 {
543 DPRINT1("Trying to delete NULL XLATEOBJ\n");
544 return;
545 }
546
547 XlateGDI = ObjToGDI(XlateObj, XLATE);
548
549 if (!XlateGDI) return;
550
551 if ((XlateObj->flXlate & XO_TABLE) &&
552 XlateObj->pulXlate != NULL)
553 {
554 EngFreeMem(XlateObj->pulXlate);
555 }
556
557 EngFreeMem(XlateGDI);
558 }
559
560 /*
561 * @implemented
562 */
563 PULONG APIENTRY
564 XLATEOBJ_piVector(XLATEOBJ *XlateObj)
565 {
566 if (XlateObj->iSrcType == PAL_INDEXED)
567 {
568 return XlateObj->pulXlate;
569 }
570
571 return NULL;
572 }
573
574 /*
575 * @implemented
576 */
577 ULONG APIENTRY
578 XLATEOBJ_iXlate(XLATEOBJ *XlateObj, ULONG Color)
579 {
580 XLATEGDI *XlateGDI;
581 PALETTE *PalGDI;
582 ULONG Closest;
583
584 /* Return the original color if there's no color translation object. */
585 if (!XlateObj)
586 return Color;
587
588 if (XlateObj->flXlate & XO_TRIVIAL)
589 return Color;
590
591 if (XlateObj->flXlate & XO_TABLE)
592 {
593 if (Color >= XlateObj->cEntries)
594 Color %= XlateObj->cEntries;
595
596 return XlateObj->pulXlate[Color];
597 }
598
599
600 if (XlateObj->flXlate & XO_TO_MONO)
601 return Color == XlateObj->pulXlate[0];
602
603 XlateGDI = ObjToGDI(XlateObj, XLATE);
604
605 if (XlateGDI->UseShiftAndMask)
606 return ShiftAndMask(XlateGDI, Color);
607
608 if (XlateObj->iSrcType == PAL_RGB || XlateObj->iSrcType == PAL_BGR ||
609 XlateObj->iSrcType == PAL_BITFIELDS)
610 {
611 /* FIXME: should we cache colors used often? */
612 /* FIXME: won't work if destination isn't indexed */
613
614 /* Convert the source color to the palette RGB format. */
615 Color = ShiftAndMask(XlateGDI, Color);
616
617 /* Extract the destination palette. */
618 PalGDI = PALETTE_LockPalette(XlateGDI->DestPal);
619 if(PalGDI != NULL)
620 {
621 /* Return closest match for the given color. */
622 Closest = ClosestColorMatch(XlateGDI, (LPPALETTEENTRY)&Color, PalGDI->IndexedColors, PalGDI->NumColors);
623 PALETTE_UnlockPalette(PalGDI);
624 return Closest;
625 }
626 }
627
628 return 0;
629 }
630
631 /*
632 * @implemented
633 */
634 ULONG APIENTRY
635 XLATEOBJ_cGetPalette(XLATEOBJ *XlateObj, ULONG PalOutType, ULONG cPal,
636 ULONG *OutPal)
637 {
638 HPALETTE hPalette;
639 XLATEGDI *XlateGDI;
640 PALETTE *PalGDI;
641 ULONG *InPal;
642
643 XlateGDI = ObjToGDI(XlateObj, XLATE);
644 if (PalOutType == XO_SRCPALETTE)
645 hPalette = XlateGDI->SourcePal;
646 else if (PalOutType == XO_DESTPALETTE)
647 hPalette = XlateGDI->DestPal;
648 else
649 {
650 UNIMPLEMENTED;
651 return 0;
652 }
653
654 PalGDI = PALETTE_LockPalette(hPalette);
655 if(PalGDI != NULL)
656 {
657 /* copy the indexed colors into the buffer */
658
659 for(InPal = (ULONG*)PalGDI->IndexedColors;
660 cPal > 0;
661 cPal--, InPal++, OutPal++)
662 {
663 *OutPal = *InPal;
664 }
665
666 PALETTE_UnlockPalette(PalGDI);
667
668 return cPal;
669 }
670
671 return 0;
672 }
673
674 /* EOF */