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