xref: /reactos/win32ss/gdi/ntgdi/dcutil.c (revision 5e93daa9)
1 #include <win32k.h>
2 
3 #define NDEBUG
4 #include <debug.h>
5 
6 BOOL FASTCALL
GreDPtoLP(HDC hdc,LPPOINT lpPoints,INT nCount)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
GreLPtoDP(HDC hdc,LPPOINT lpPoints,INT nCount)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
GreGetBkMode(HDC hdc)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
GreGetBkColor(HDC hdc)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
GreGetMapMode(HDC hdc)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
GreGetTextColor(HDC hdc)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
IntGdiSetBkColor(HDC hDC,COLORREF color)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
IntGdiSetBkMode(HDC hDC,INT Mode)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
IntGdiSetTextAlign(HDC hDC,UINT Mode)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
IntGdiSetTextColor(HDC hDC,COLORREF color)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
IntSetDCBrushColor(HDC hdc,COLORREF crColor)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
GreSetBrushOrg(HDC hdc,INT x,INT y,LPPOINT pptOut)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
IntSetDCPenColor(HDC hdc,COLORREF crColor)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
GreSetStretchBltMode(HDC hDC,int iStretchMode)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
GreGetGraphicsMode(HDC hdc)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
DCU_SetDcUndeletable(HDC hDC)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_PERMANANT;
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
IntSetDefaultRegion(PDC pdc)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
NtGdiCancelDC(HDC hDC)414 NtGdiCancelDC(HDC  hDC)
415 {
416     UNIMPLEMENTED;
417     return FALSE;
418 }
419 
420 
421 WORD APIENTRY
IntGdiSetHookFlags(HDC hDC,WORD Flags)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_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_DIRTY_RAO;
442     }
443     else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags)
444     {
445         //dc->fs &= ~DC_DIRTY_RAO;
446     }
447 
448     DC_UnlockDc(dc);
449 
450     return wRet;
451 }
452 
453 
454 BOOL
455 APIENTRY
NtGdiGetDCDword(HDC hDC,UINT u,DWORD * Result)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 GdiGetCharBreak:
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
NtGdiGetAndSetDCDword(_In_ HDC hdc,_In_ UINT u,_In_ DWORD dwIn,_Out_ DWORD * pdwResult)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 GdiGetSetEPSPrintingEscape:
589             SafeResult = pdc->fs & DC_EPSPRINTINGESCAPE;
590             pdc->fs &= ~DC_EPSPRINTINGESCAPE;
591             break;
592 
593         case GdiGetSetCopyCount:
594             SafeResult = pdc->ulCopyCount;
595             pdc->ulCopyCount = dwIn;
596             break;
597 
598         case GdiGetSetTextAlign:
599             SafeResult = pdcattr->lTextAlign;
600             pdcattr->lTextAlign = dwIn;
601             // pdcattr->flTextAlign = dwIn; // Flags!
602             break;
603 
604         case GdiGetSetRelAbs:
605             SafeResult = pdcattr->lRelAbs;
606             pdcattr->lRelAbs = dwIn;
607             break;
608 
609         case GdiGetSetTextCharExtra:
610             SafeResult = pdcattr->lTextExtra;
611             pdcattr->lTextExtra = dwIn;
612             break;
613 
614         case GdiGetSetSelectFont:
615             break;
616 
617         case GdiGetSetMapperFlagsInternal:
618             if (dwIn & ~1)
619             {
620                 EngSetLastError(ERROR_INVALID_PARAMETER);
621                 Ret = FALSE;
622                 break;
623             }
624             SafeResult = pdcattr->flFontMapper;
625             pdcattr->flFontMapper = dwIn;
626             break;
627 
628         case GdiGetSetMapMode:
629             SafeResult = IntGdiSetMapMode(pdc, dwIn);
630             break;
631 
632         case GdiGetSetArcDirection:
633             if (dwIn != AD_COUNTERCLOCKWISE && dwIn != AD_CLOCKWISE)
634             {
635                 EngSetLastError(ERROR_INVALID_PARAMETER);
636                 Ret = FALSE;
637                 break;
638             }
639             if (pdcattr->dwLayout & LAYOUT_RTL) // Right to Left
640             {
641                 SafeResult = AD_CLOCKWISE - ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
642                 if (dwIn == AD_CLOCKWISE)
643                 {
644                     pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
645                     break;
646                 }
647                 pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
648             }
649             else // Left to Right
650             {
651                 SafeResult = ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) +
652                              AD_COUNTERCLOCKWISE;
653                 if (dwIn == AD_COUNTERCLOCKWISE)
654                 {
655                     pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
656                     break;
657                 }
658                 pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
659             }
660             break;
661 
662         default:
663             EngSetLastError(ERROR_INVALID_PARAMETER);
664             Ret = FALSE;
665             break;
666     }
667 
668     if (Ret)
669     {
670         _SEH2_TRY
671         {
672             ProbeForWrite(pdwResult, sizeof(DWORD), 1);
673             *pdwResult = SafeResult;
674         }
675         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
676         {
677             Status = _SEH2_GetExceptionCode();
678         }
679         _SEH2_END;
680 
681         if (!NT_SUCCESS(Status))
682         {
683             SetLastNtError(Status);
684             Ret = FALSE;
685         }
686     }
687 
688     DC_UnlockDc(pdc);
689     return Ret;
690 }
691 
692 VOID
693 FASTCALL
IntUpdateBoundsRect(PDC pdc,PRECTL pRect)694 IntUpdateBoundsRect(PDC pdc, PRECTL pRect)
695 {
696    if (pdc->fs & DC_ACCUM_APP)
697    {
698       RECTL_bUnionRect(&pdc->erclBoundsApp, &pdc->erclBoundsApp, pRect);
699    }
700    if (pdc->fs & DC_ACCUM_WMGR)
701    {
702       RECTL_bUnionRect(&pdc->erclBounds, &pdc->erclBounds, pRect);
703    }
704 }
705 
706 DWORD
707 APIENTRY
NtGdiGetBoundsRect(IN HDC hdc,OUT LPRECT prc,IN DWORD flags)708 NtGdiGetBoundsRect(
709     IN HDC hdc,
710     OUT LPRECT prc,
711     IN DWORD flags)
712 {
713     DWORD ret;
714     PDC pdc;
715     RECT rc;
716 
717     /* Lock the DC */
718     if (!(pdc = DC_LockDc(hdc))) return 0;
719 
720     if (!(flags & DCB_WINDOWMGR))
721     {
722        rc = pdc->erclBoundsApp;
723 
724        if (RECTL_bIsEmptyRect(&rc))
725        {
726           rc.left = rc.top = rc.right = rc.bottom = 0;
727           ret = DCB_RESET;
728        }
729        else
730        {
731           RECTL rcRgn;
732           if (pdc->fs & DC_DIRTY_RAO) CLIPPING_UpdateGCRegion(pdc);
733           if(!REGION_GetRgnBox(pdc->prgnRao, &rcRgn))
734           {
735              REGION_GetRgnBox(pdc->prgnVis, &rcRgn);
736           }
737           rc.left   = max( rc.left, 0 );
738           rc.top    = max( rc.top, 0 );
739           rc.right  = min( rc.right,  rcRgn.right - rcRgn.left );
740           rc.bottom = min( rc.bottom, rcRgn.bottom - rcRgn.top );
741           DPRINT("Rao dc %p r %d b %d\n",pdc,rcRgn.right - rcRgn.left, rcRgn.bottom - rcRgn.top);
742           DPRINT("rc  l %d t %d\n",rc.left,rc.top);
743           DPRINT("    r %d b %d\n",rc.right,rc.bottom);
744           ret = DCB_SET;
745        }
746        IntDPtoLP(pdc, (PPOINTL)&rc, 2);
747        DPRINT("rc1 l %d t %d\n",rc.left,rc.top);
748        DPRINT("    r %d b %d\n",rc.right,rc.bottom);
749     }
750     else
751     {
752        rc = pdc->erclBounds;
753        ret = DCB_SET;
754     }
755 
756     /* Copy the rect to the caller */
757     _SEH2_TRY
758     {
759         ProbeForWrite(prc, sizeof(RECT), 1);
760         *prc = rc;
761     }
762     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
763     {
764         ret = 0;
765     }
766     _SEH2_END;
767 
768     if (flags & DCB_RESET)
769     {
770         if (!(flags & DCB_WINDOWMGR))
771         {
772            pdc->erclBoundsApp.left = pdc->erclBoundsApp.top = INT_MAX;
773            pdc->erclBoundsApp.right = pdc->erclBoundsApp.bottom = INT_MIN;
774         }
775         else
776         {
777            pdc->erclBounds.left = pdc->erclBounds.top = INT_MAX;
778            pdc->erclBounds.right = pdc->erclBounds.bottom = INT_MIN;
779         }
780     }
781 
782     DC_UnlockDc(pdc);
783     return ret;
784 }
785 
786 DWORD
787 APIENTRY
NtGdiSetBoundsRect(IN HDC hdc,IN LPRECT prc,IN DWORD flags)788 NtGdiSetBoundsRect(
789     IN HDC hdc,
790     IN LPRECT prc,
791     IN DWORD flags)
792 {
793     DWORD ret;
794     PDC pdc;
795     RECTL rcl;
796 
797     /* Verify arguments */
798     if ((flags & DCB_ENABLE) && (flags & DCB_DISABLE)) return 0;
799 
800     /* Lock the DC */
801     if (!(pdc = DC_LockDc(hdc))) return 0;
802 
803     /* Get the return value */
804     ret = DCB_RESET; /* we don't have device-specific bounds */
805     ret = (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR) ? DCB_ENABLE : DCB_DISABLE) |
806           (RECTL_bIsEmptyRect(&pdc->erclBoundsApp) ? ret & DCB_SET : DCB_SET );
807     ret |= (flags & DCB_WINDOWMGR);
808 
809     if (flags & DCB_RESET)
810     {
811         if (!(flags & DCB_WINDOWMGR))
812         {
813            pdc->erclBoundsApp.left = pdc->erclBoundsApp.top = INT_MAX;
814            pdc->erclBoundsApp.right = pdc->erclBoundsApp.bottom = INT_MIN;
815         }
816         else
817         {
818            pdc->erclBounds.left = pdc->erclBounds.top = INT_MAX;
819            pdc->erclBounds.right = pdc->erclBounds.bottom = INT_MIN;
820         }
821     }
822 
823     if (flags & DCB_ACCUMULATE && prc != NULL)
824     {
825         /* Capture the rect */
826         _SEH2_TRY
827         {
828             ProbeForRead(prc, sizeof(RECT), 1);
829             rcl = *prc;
830         }
831         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
832         {
833             DC_UnlockDc(pdc);
834             _SEH2_YIELD(return 0;)
835         }
836         _SEH2_END;
837 
838         RECTL_vMakeWellOrdered(&rcl);
839 
840         if (!(flags & DCB_WINDOWMGR))
841         {
842            IntLPtoDP( pdc, (POINT *)&rcl, 2 );
843            RECTL_bUnionRect(&pdc->erclBoundsApp, &pdc->erclBoundsApp, &rcl);
844         }
845         else
846            RECTL_bUnionRect(&pdc->erclBounds, &pdc->erclBounds, &rcl);
847     }
848 
849     if (flags & DCB_ENABLE)
850     {
851        if (!(flags & DCB_WINDOWMGR))
852           pdc->fs |= DC_ACCUM_APP;
853        else
854           pdc->fs |= DC_ACCUM_WMGR;
855     }
856     if (flags & DCB_DISABLE)
857     {
858        if (!(flags & DCB_WINDOWMGR))
859           pdc->fs &= ~DC_ACCUM_APP;
860        else
861           pdc->fs &= ~DC_ACCUM_WMGR;
862     }
863     DC_UnlockDc(pdc);
864     return ret;
865 }
866 
867 /* Translates a COLORREF to the right color in the specified DC color space */
868 ULONG
TranslateCOLORREF(PDC pdc,COLORREF crColor)869 TranslateCOLORREF(PDC pdc, COLORREF crColor)
870 {
871     PSURFACE psurfDC;
872     PPALETTE ppalDC;
873     ULONG index, ulColor, iBitmapFormat;
874     EXLATEOBJ exlo;
875 
876     /* Get the DC surface */
877     psurfDC = pdc->dclevel.pSurface;
878 
879     /* If no surface is selected, use the default bitmap */
880     if (!psurfDC)
881         psurfDC = psurfDefaultBitmap;
882 
883     /* Check what color type this is */
884     switch (crColor >> 24)
885     {
886         case 0x00: /* RGB color */
887             break;
888 
889         case 0x01: /* PALETTEINDEX */
890             index = crColor & 0xFFFFFF;
891             ppalDC = pdc->dclevel.ppal;
892             if (index >= ppalDC->NumColors) index = 0;
893 
894             /* Get the RGB value */
895             crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
896             break;
897 
898         case 0x02: /* PALETTERGB */
899 
900             if (pdc->dclevel.hpal != StockObjects[DEFAULT_PALETTE])
901             {
902                 /* First find the nearest index in the dc palette */
903                 ppalDC = pdc->dclevel.ppal;
904                 index = PALETTE_ulGetNearestIndex(ppalDC, crColor & 0xFFFFFF);
905 
906                 /* Get the RGB value */
907                 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
908             }
909             else
910             {
911                 /* Use the pure color */
912                 crColor = crColor & 0x00FFFFFF;
913             }
914             break;
915 
916         case 0x10: /* DIBINDEX */
917             /* Mask the value to match the target bpp */
918             iBitmapFormat = psurfDC->SurfObj.iBitmapFormat;
919             if (iBitmapFormat == BMF_1BPP) index = crColor & 0x1;
920             else if (iBitmapFormat == BMF_4BPP) index = crColor & 0xf;
921             else if (iBitmapFormat == BMF_8BPP) index = crColor & 0xFF;
922             else if (iBitmapFormat == BMF_16BPP) index = crColor & 0xFFFF;
923             else index = crColor & 0xFFFFFF;
924             return index;
925 
926         default:
927             DPRINT("Unsupported color type %u passed\n", crColor >> 24);
928             crColor &= 0xFFFFFF;
929     }
930 
931     /* Initialize an XLATEOBJ from RGB to the target surface */
932     EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurfDC->ppal, 0xFFFFFF, 0, 0);
933 
934     /* Translate the color to the target format */
935     ulColor = XLATEOBJ_iXlate(&exlo.xlo, crColor);
936 
937     /* Cleanup the XLATEOBJ */
938     EXLATEOBJ_vCleanup(&exlo);
939 
940     return ulColor;
941 }
942 
943 
944