[NtGdi]
[reactos.git] / reactos / win32ss / gdi / ntgdi / dcutil.c
1 #include <win32k.h>
2
3 #define NDEBUG
4 #include <debug.h>
5
6 BOOL FASTCALL
7 GreDPtoLP(HDC hdc, LPPOINT lpPoints, INT nCount)
8 {
9 PDC dc;
10 if (!(dc = DC_LockDc(hdc)))
11 {
12 EngSetLastError(ERROR_INVALID_HANDLE);
13 return FALSE;
14 }
15 IntDPtoLP(dc, lpPoints, nCount);
16 DC_UnlockDc(dc);
17 return TRUE;
18 }
19
20 BOOL FASTCALL
21 GreLPtoDP(HDC hdc, LPPOINT lpPoints, INT nCount)
22 {
23 PDC dc;
24 if (!(dc = DC_LockDc(hdc)))
25 {
26 EngSetLastError(ERROR_INVALID_HANDLE);
27 return FALSE;
28 }
29 IntLPtoDP(dc, lpPoints, nCount);
30 DC_UnlockDc(dc);
31 return TRUE;
32 }
33
34 int FASTCALL
35 GreGetBkMode(HDC hdc)
36 {
37 PDC dc;
38 LONG lBkMode;
39 if (!(dc = DC_LockDc(hdc)))
40 {
41 EngSetLastError(ERROR_INVALID_HANDLE);
42 return CLR_INVALID;
43 }
44 lBkMode = dc->pdcattr->lBkMode;
45 DC_UnlockDc(dc);
46 return lBkMode;
47 }
48
49 int FASTCALL
50 GreGetMapMode(HDC hdc)
51 {
52 PDC dc;
53 INT iMapMode;
54 if (!(dc = DC_LockDc(hdc)))
55 {
56 EngSetLastError(ERROR_INVALID_HANDLE);
57 return CLR_INVALID;
58 }
59 iMapMode = dc->pdcattr->iMapMode;
60 DC_UnlockDc(dc);
61 return iMapMode;
62 }
63
64 COLORREF FASTCALL
65 GreGetTextColor(HDC hdc)
66 {
67 PDC dc;
68 ULONG ulForegroundClr;
69 if (!(dc = DC_LockDc(hdc)))
70 {
71 EngSetLastError(ERROR_INVALID_HANDLE);
72 return CLR_INVALID;
73 }
74 ulForegroundClr = dc->pdcattr->ulForegroundClr;
75 DC_UnlockDc(dc);
76 return ulForegroundClr;
77 }
78
79 COLORREF FASTCALL
80 IntGdiSetBkColor(HDC hDC, COLORREF color)
81 {
82 COLORREF oldColor;
83 PDC dc;
84 PDC_ATTR pdcattr;
85 HBRUSH hBrush;
86
87 if (!(dc = DC_LockDc(hDC)))
88 {
89 EngSetLastError(ERROR_INVALID_HANDLE);
90 return CLR_INVALID;
91 }
92 pdcattr = dc->pdcattr;
93 oldColor = pdcattr->crBackgroundClr;
94 pdcattr->crBackgroundClr = color;
95 pdcattr->ulBackgroundClr = (ULONG)color;
96 pdcattr->ulDirty_ |= DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL; // Clear Flag if set.
97 hBrush = pdcattr->hbrush;
98 DC_UnlockDc(dc);
99 NtGdiSelectBrush(hDC, hBrush);
100 return oldColor;
101 }
102
103 INT FASTCALL
104 IntGdiSetBkMode(HDC hDC, INT Mode)
105 {
106 COLORREF oldMode;
107 PDC dc;
108 PDC_ATTR pdcattr;
109
110 if (!(dc = DC_LockDc(hDC)))
111 {
112 EngSetLastError(ERROR_INVALID_HANDLE);
113 return CLR_INVALID;
114 }
115 pdcattr = dc->pdcattr;
116 oldMode = pdcattr->lBkMode;
117 pdcattr->jBkMode = Mode;
118 pdcattr->lBkMode = Mode;
119 DC_UnlockDc(dc);
120 return oldMode;
121 }
122
123 UINT
124 FASTCALL
125 IntGdiSetTextAlign(HDC hDC,
126 UINT Mode)
127 {
128 UINT prevAlign;
129 DC *dc;
130 PDC_ATTR pdcattr;
131
132 dc = DC_LockDc(hDC);
133 if (!dc)
134 {
135 EngSetLastError(ERROR_INVALID_HANDLE);
136 return GDI_ERROR;
137 }
138 pdcattr = dc->pdcattr;
139 prevAlign = pdcattr->lTextAlign;
140 pdcattr->lTextAlign = Mode;
141 DC_UnlockDc(dc);
142 return prevAlign;
143 }
144
145 COLORREF
146 FASTCALL
147 IntGdiSetTextColor(HDC hDC,
148 COLORREF color)
149 {
150 COLORREF crOldColor;
151 PDC pdc;
152 PDC_ATTR pdcattr;
153
154 pdc = DC_LockDc(hDC);
155 if (!pdc)
156 {
157 EngSetLastError(ERROR_INVALID_HANDLE);
158 return CLR_INVALID;
159 }
160 pdcattr = pdc->pdcattr;
161
162 // What about ulForegroundClr, like in gdi32?
163 crOldColor = pdcattr->crForegroundClr;
164 pdcattr->crForegroundClr = color;
165 DC_vUpdateTextBrush(pdc);
166
167 DC_UnlockDc(pdc);
168
169 return crOldColor;
170 }
171
172 COLORREF FASTCALL
173 IntSetDCBrushColor(HDC hdc, COLORREF crColor)
174 {
175 COLORREF OldColor = CLR_INVALID;
176 PDC dc;
177 if (!(dc = DC_LockDc(hdc)))
178 {
179 EngSetLastError(ERROR_INVALID_HANDLE);
180 return CLR_INVALID;
181 }
182 else
183 {
184 OldColor = (COLORREF) dc->pdcattr->ulBrushClr;
185 dc->pdcattr->ulBrushClr = (ULONG) crColor;
186
187 if ( dc->pdcattr->crBrushClr != crColor )
188 {
189 dc->pdcattr->ulDirty_ |= DIRTY_FILL;
190 dc->pdcattr->crBrushClr = crColor;
191 }
192 }
193 DC_UnlockDc(dc);
194 return OldColor;
195 }
196
197 COLORREF FASTCALL
198 IntSetDCPenColor(HDC hdc, COLORREF crColor)
199 {
200 COLORREF OldColor;
201 PDC dc;
202 if (!(dc = DC_LockDc(hdc)))
203 {
204 EngSetLastError(ERROR_INVALID_PARAMETER);
205 return CLR_INVALID;
206 }
207
208 OldColor = (COLORREF)dc->pdcattr->ulPenClr;
209 dc->pdcattr->ulPenClr = (ULONG)crColor;
210
211 if (dc->pdcattr->crPenClr != crColor)
212 {
213 dc->pdcattr->ulDirty_ |= DIRTY_LINE;
214 dc->pdcattr->crPenClr = crColor;
215 }
216 DC_UnlockDc(dc);
217 return OldColor;
218 }
219
220 int
221 FASTCALL
222 GreSetStretchBltMode(HDC hDC, int iStretchMode)
223 {
224 PDC pdc;
225 PDC_ATTR pdcattr;
226 INT oSMode = 0;
227
228 pdc = DC_LockDc(hDC);
229 if (pdc)
230 {
231 pdcattr = pdc->pdcattr;
232 oSMode = pdcattr->lStretchBltMode;
233 pdcattr->lStretchBltMode = iStretchMode;
234
235 // Wine returns an error here. We set the default.
236 if ((iStretchMode <= 0) || (iStretchMode > MAXSTRETCHBLTMODE)) iStretchMode = WHITEONBLACK;
237
238 pdcattr->jStretchBltMode = iStretchMode;
239 DC_UnlockDc(pdc);
240 }
241 return oSMode;
242 }
243
244 int FASTCALL
245 GreGetGraphicsMode(HDC hdc)
246 {
247 PDC dc;
248 int GraphicsMode;
249 if (!(dc = DC_LockDc(hdc)))
250 {
251 EngSetLastError(ERROR_INVALID_HANDLE);
252 return CLR_INVALID;
253 }
254 GraphicsMode = dc->pdcattr->iGraphicsMode;;
255 DC_UnlockDc(dc);
256 return GraphicsMode;
257 }
258
259 VOID
260 FASTCALL
261 DCU_SetDcUndeletable(HDC hDC)
262 {
263 PDC dc = DC_LockDc(hDC);
264 if (!dc)
265 {
266 EngSetLastError(ERROR_INVALID_HANDLE);
267 return;
268 }
269
270 dc->fs |= DC_FLAG_PERMANENT;
271 DC_UnlockDc(dc);
272 return;
273 }
274
275 #if 0
276 BOOL FASTCALL
277 IntIsPrimarySurface(SURFOBJ *SurfObj)
278 {
279 if (PrimarySurface.pSurface == NULL)
280 {
281 return FALSE;
282 }
283 return SurfObj->hsurf == PrimarySurface.pSurface; // <- FIXME: WTF?
284 }
285 #endif
286
287 BOOL
288 FASTCALL
289 IntSetDefaultRegion(PDC pdc)
290 {
291 PSURFACE pSurface;
292 PREGION prgn;
293 RECTL rclWnd, rclClip;
294
295 IntGdiReleaseRaoRgn(pdc);
296
297 rclWnd.left = 0;
298 rclWnd.top = 0;
299 rclWnd.right = pdc->dclevel.sizl.cx;
300 rclWnd.bottom = pdc->dclevel.sizl.cy;
301 rclClip = rclWnd;
302
303 //EngAcquireSemaphoreShared(pdc->ppdev->hsemDevLock);
304 if (pdc->ppdev->flFlags & PDEV_META_DEVICE)
305 {
306 pSurface = pdc->dclevel.pSurface;
307 if (pSurface && pSurface->flags & PDEV_SURFACE)
308 {
309 rclClip.left += pdc->ppdev->ptlOrigion.x;
310 rclClip.top += pdc->ppdev->ptlOrigion.y;
311 rclClip.right += pdc->ppdev->ptlOrigion.x;
312 rclClip.bottom += pdc->ppdev->ptlOrigion.y;
313 }
314 }
315 //EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
316
317 prgn = pdc->prgnVis;
318
319 if (prgn && prgn != prgnDefault)
320 {
321 REGION_SetRectRgn( prgn,
322 rclClip.left,
323 rclClip.top,
324 rclClip.right ,
325 rclClip.bottom );
326 }
327 else
328 {
329 prgn = IntSysCreateRectpRgn( rclClip.left,
330 rclClip.top,
331 rclClip.right ,
332 rclClip.bottom );
333 pdc->prgnVis = prgn;
334 }
335
336 if (prgn)
337 {
338 pdc->ptlDCOrig.x = 0;
339 pdc->ptlDCOrig.y = 0;
340 pdc->erclWindow = rclWnd;
341 pdc->erclClip = rclClip;
342 /* Might be an InitDC or DCE... */
343 pdc->ptlFillOrigin.x = pdc->dcattr.VisRectRegion.Rect.right;
344 pdc->ptlFillOrigin.y = pdc->dcattr.VisRectRegion.Rect.bottom;
345 return TRUE;
346 }
347
348 pdc->prgnVis = prgnDefault;
349 return FALSE;
350 }
351
352
353 BOOL APIENTRY
354 NtGdiCancelDC(HDC hDC)
355 {
356 UNIMPLEMENTED;
357 return FALSE;
358 }
359
360
361 WORD APIENTRY
362 IntGdiSetHookFlags(HDC hDC, WORD Flags)
363 {
364 WORD wRet;
365 DC *dc = DC_LockDc(hDC);
366
367 if (NULL == dc)
368 {
369 EngSetLastError(ERROR_INVALID_HANDLE);
370 return 0;
371 }
372
373 wRet = dc->fs & DC_FLAG_DIRTY_RAO; // FIXME: Wrong flag!
374
375 /* Info in "Undocumented Windows" is slightly confusing. */
376 DPRINT("DC %p, Flags %04x\n", hDC, Flags);
377
378 if (Flags & DCHF_INVALIDATEVISRGN)
379 {
380 /* hVisRgn has to be updated */
381 dc->fs |= DC_FLAG_DIRTY_RAO;
382 }
383 else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags)
384 {
385 //dc->fs &= ~DC_FLAG_DIRTY_RAO;
386 }
387
388 DC_UnlockDc(dc);
389
390 return wRet;
391 }
392
393
394 BOOL
395 APIENTRY
396 NtGdiGetDCDword(
397 HDC hDC,
398 UINT u,
399 DWORD *Result)
400 {
401 BOOL Ret = TRUE;
402 PDC pdc;
403 PDC_ATTR pdcattr;
404
405 DWORD SafeResult = 0;
406 NTSTATUS Status = STATUS_SUCCESS;
407
408 if (!Result)
409 {
410 EngSetLastError(ERROR_INVALID_PARAMETER);
411 return FALSE;
412 }
413
414 pdc = DC_LockDc(hDC);
415 if (!pdc)
416 {
417 EngSetLastError(ERROR_INVALID_HANDLE);
418 return FALSE;
419 }
420 pdcattr = pdc->pdcattr;
421
422 switch (u)
423 {
424 case GdiGetJournal:
425 break;
426
427 case GdiGetRelAbs:
428 SafeResult = pdcattr->lRelAbs;
429 break;
430
431 case GdiGetBreakExtra:
432 SafeResult = pdcattr->lBreakExtra;
433 break;
434
435 case GdiGerCharBreak:
436 SafeResult = pdcattr->cBreak;
437 break;
438
439 case GdiGetArcDirection:
440 if (pdcattr->dwLayout & LAYOUT_RTL)
441 SafeResult = AD_CLOCKWISE - ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
442 else
443 SafeResult = ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) + AD_COUNTERCLOCKWISE;
444 break;
445
446 case GdiGetEMFRestorDc:
447 SafeResult = pdc->dclevel.lSaveDepth;
448 break;
449
450 case GdiGetFontLanguageInfo:
451 SafeResult = IntGetFontLanguageInfo(pdc);
452 break;
453
454 case GdiGetIsMemDc:
455 SafeResult = pdc->dctype;
456 break;
457
458 case GdiGetMapMode:
459 SafeResult = pdcattr->iMapMode;
460 break;
461
462 case GdiGetTextCharExtra:
463 SafeResult = pdcattr->lTextExtra;
464 break;
465
466 default:
467 EngSetLastError(ERROR_INVALID_PARAMETER);
468 Ret = FALSE;
469 break;
470 }
471
472 if (Ret)
473 {
474 _SEH2_TRY
475 {
476 ProbeForWrite(Result, sizeof(DWORD), 1);
477 *Result = SafeResult;
478 }
479 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
480 {
481 Status = _SEH2_GetExceptionCode();
482 }
483 _SEH2_END;
484
485 if (!NT_SUCCESS(Status))
486 {
487 SetLastNtError(Status);
488 Ret = FALSE;
489 }
490 }
491
492 DC_UnlockDc(pdc);
493 return Ret;
494 }
495
496 _Success_(return != FALSE)
497 BOOL
498 APIENTRY
499 NtGdiGetAndSetDCDword(
500 _In_ HDC hdc,
501 _In_ UINT u,
502 _In_ DWORD dwIn,
503 _Out_ DWORD *pdwResult)
504 {
505 BOOL Ret = TRUE;
506 PDC pdc;
507 PDC_ATTR pdcattr;
508
509 DWORD SafeResult = 0;
510 NTSTATUS Status = STATUS_SUCCESS;
511
512 if (!pdwResult)
513 {
514 EngSetLastError(ERROR_INVALID_PARAMETER);
515 return FALSE;
516 }
517
518 pdc = DC_LockDc(hdc);
519 if (!pdc)
520 {
521 EngSetLastError(ERROR_INVALID_HANDLE);
522 return FALSE;
523 }
524 pdcattr = pdc->pdcattr;
525
526 switch (u)
527 {
528 case GdiGetSetCopyCount:
529 SafeResult = pdc->ulCopyCount;
530 pdc->ulCopyCount = dwIn;
531 break;
532
533 case GdiGetSetTextAlign:
534 SafeResult = pdcattr->lTextAlign;
535 pdcattr->lTextAlign = dwIn;
536 // pdcattr->flTextAlign = dwIn; // Flags!
537 break;
538
539 case GdiGetSetRelAbs:
540 SafeResult = pdcattr->lRelAbs;
541 pdcattr->lRelAbs = dwIn;
542 break;
543
544 case GdiGetSetTextCharExtra:
545 SafeResult = pdcattr->lTextExtra;
546 pdcattr->lTextExtra = dwIn;
547 break;
548
549 case GdiGetSetSelectFont:
550 break;
551
552 case GdiGetSetMapperFlagsInternal:
553 if (dwIn & ~1)
554 {
555 EngSetLastError(ERROR_INVALID_PARAMETER);
556 Ret = FALSE;
557 break;
558 }
559 SafeResult = pdcattr->flFontMapper;
560 pdcattr->flFontMapper = dwIn;
561 break;
562
563 case GdiGetSetMapMode:
564 SafeResult = IntGdiSetMapMode(pdc, dwIn);
565 break;
566
567 case GdiGetSetArcDirection:
568 if (dwIn != AD_COUNTERCLOCKWISE && dwIn != AD_CLOCKWISE)
569 {
570 EngSetLastError(ERROR_INVALID_PARAMETER);
571 Ret = FALSE;
572 break;
573 }
574 if (pdcattr->dwLayout & LAYOUT_RTL) // Right to Left
575 {
576 SafeResult = AD_CLOCKWISE - ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
577 if (dwIn == AD_CLOCKWISE)
578 {
579 pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
580 break;
581 }
582 pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
583 }
584 else // Left to Right
585 {
586 SafeResult = ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) +
587 AD_COUNTERCLOCKWISE;
588 if (dwIn == AD_COUNTERCLOCKWISE)
589 {
590 pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
591 break;
592 }
593 pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
594 }
595 break;
596
597 default:
598 EngSetLastError(ERROR_INVALID_PARAMETER);
599 Ret = FALSE;
600 break;
601 }
602
603 if (Ret)
604 {
605 _SEH2_TRY
606 {
607 ProbeForWrite(pdwResult, sizeof(DWORD), 1);
608 *pdwResult = SafeResult;
609 }
610 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
611 {
612 Status = _SEH2_GetExceptionCode();
613 }
614 _SEH2_END;
615
616 if (!NT_SUCCESS(Status))
617 {
618 SetLastNtError(Status);
619 Ret = FALSE;
620 }
621 }
622
623 DC_UnlockDc(pdc);
624 return Ret;
625 }
626
627 DWORD
628 APIENTRY
629 NtGdiGetBoundsRect(
630 IN HDC hdc,
631 OUT LPRECT prc,
632 IN DWORD flags)
633 {
634 DWORD ret;
635 PDC pdc;
636
637 /* Lock the DC */
638 if (!(pdc = DC_LockDc(hdc))) return 0;
639
640 /* Get the return value */
641 ret = pdc->fs & DC_ACCUM_APP ? DCB_ENABLE : DCB_DISABLE;
642 ret |= RECTL_bIsEmptyRect(&pdc->erclBoundsApp) ? DCB_RESET : DCB_SET;
643
644 /* Copy the rect to the caller */
645 _SEH2_TRY
646 {
647 ProbeForWrite(prc, sizeof(RECT), 1);
648 *prc = pdc->erclBoundsApp;
649 }
650 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
651 {
652 ret = 0;
653 }
654 _SEH2_END;
655
656 if (flags & DCB_RESET)
657 {
658 RECTL_vSetEmptyRect(&pdc->erclBoundsApp);
659 }
660
661 DC_UnlockDc(pdc);
662 return ret;
663 }
664
665
666 DWORD
667 APIENTRY
668 NtGdiSetBoundsRect(
669 IN HDC hdc,
670 IN LPRECT prc,
671 IN DWORD flags)
672 {
673 DWORD ret;
674 PDC pdc;
675 RECTL rcl;
676
677 /* Verify arguments */
678 if ((flags & DCB_ENABLE) && (flags & DCB_DISABLE)) return 0;
679
680 /* Lock the DC */
681 if (!(pdc = DC_LockDc(hdc))) return 0;
682
683 /* Get the return value */
684 ret = pdc->fs & DC_ACCUM_APP ? DCB_ENABLE : DCB_DISABLE;
685 ret |= RECTL_bIsEmptyRect(&pdc->erclBoundsApp) ? DCB_RESET : DCB_SET;
686
687 if (flags & DCB_RESET)
688 {
689 RECTL_vSetEmptyRect(&pdc->erclBoundsApp);
690 }
691
692 if (flags & DCB_ACCUMULATE)
693 {
694 /* Capture the rect */
695 _SEH2_TRY
696 {
697 ProbeForRead(prc, sizeof(RECT), 1);
698 rcl = *prc;
699 }
700 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
701 {
702 DC_UnlockDc(pdc);
703 _SEH2_YIELD(return 0;)
704 }
705 _SEH2_END;
706
707 RECTL_vMakeWellOrdered(&rcl);
708 RECTL_bUnionRect(&pdc->erclBoundsApp, &pdc->erclBoundsApp, &rcl);
709 }
710
711 if (flags & DCB_ENABLE) pdc->fs |= DC_ACCUM_APP;
712 if (flags & DCB_DISABLE) pdc->fs &= ~DC_ACCUM_APP;
713 DC_UnlockDc(pdc);
714 return ret;
715 }
716
717 /* Translates a COLORREF to the right color in the specified DC color space */
718 ULONG
719 TranslateCOLORREF(PDC pdc, COLORREF crColor)
720 {
721 PSURFACE psurfDC;
722 PPALETTE ppalDC;
723 ULONG index, ulColor, iBitmapFormat;
724 EXLATEOBJ exlo;
725
726 /* Get the DC surface */
727 psurfDC = pdc->dclevel.pSurface;
728
729 /* If no surface is selected, use the default bitmap */
730 if (!psurfDC)
731 psurfDC = psurfDefaultBitmap;
732
733 /* Check what color type this is */
734 switch (crColor >> 24)
735 {
736 case 0x00: /* RGB color */
737 break;
738
739 case 0x01: /* PALETTEINDEX */
740 index = crColor & 0xFFFFFF;
741 ppalDC = pdc->dclevel.ppal;
742 if (index >= ppalDC->NumColors) index = 0;
743
744 /* Get the RGB value */
745 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
746 break;
747
748 case 0x02: /* PALETTERGB */
749
750 if (pdc->dclevel.hpal != StockObjects[DEFAULT_PALETTE])
751 {
752 /* First find the nearest index in the dc palette */
753 ppalDC = pdc->dclevel.ppal;
754 index = PALETTE_ulGetNearestIndex(ppalDC, crColor & 0xFFFFFF);
755
756 /* Get the RGB value */
757 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
758 }
759 else
760 {
761 /* Use the pure color */
762 crColor = crColor & 0x00FFFFFF;
763 }
764 break;
765
766 case 0x10: /* DIBINDEX */
767 /* Mask the value to match the target bpp */
768 iBitmapFormat = psurfDC->SurfObj.iBitmapFormat;
769 if (iBitmapFormat == BMF_1BPP) index = crColor & 0x1;
770 else if (iBitmapFormat == BMF_4BPP) index = crColor & 0xf;
771 else if (iBitmapFormat == BMF_8BPP) index = crColor & 0xFF;
772 else if (iBitmapFormat == BMF_16BPP) index = crColor & 0xFFFF;
773 else index = crColor & 0xFFFFFF;
774 return index;
775
776 default:
777 DPRINT("Unsupported color type %u passed\n", crColor >> 24);
778 crColor &= 0xFFFFFF;
779 }
780
781 /* Initialize an XLATEOBJ from RGB to the target surface */
782 EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurfDC->ppal, 0xFFFFFF, 0, 0);
783
784 /* Translate the color to the target format */
785 ulColor = XLATEOBJ_iXlate(&exlo.xlo, crColor);
786
787 /* Cleanup the XLATEOBJ */
788 EXLATEOBJ_vCleanup(&exlo);
789
790 return ulColor;
791 }
792
793