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