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