[WIN32K]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Wed, 24 Sep 2014 21:23:03 +0000 (21:23 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Wed, 24 Sep 2014 21:23:03 +0000 (21:23 +0000)
- Implement REGION_SubtractRectFromRgn
- Rewrite NtGdiExcludeClipRect, fixing a number of gdi32 apitests

svn path=/trunk/; revision=64260

reactos/win32ss/gdi/ntgdi/cliprgn.c
reactos/win32ss/gdi/ntgdi/region.c
reactos/win32ss/gdi/ntgdi/region.h

index 9c96225..09f36e1 100644 (file)
@@ -190,55 +190,79 @@ NtGdiGetAppClipBox(
     return iComplexity;
 }
 
-int APIENTRY NtGdiExcludeClipRect(HDC  hDC,
-                         int  LeftRect,
-                         int  TopRect,
-                         int  RightRect,
-                         int  BottomRect)
+INT
+APIENTRY
+NtGdiExcludeClipRect(
+    _In_ HDC hdc,
+    _In_ INT xLeft,
+    _In_ INT yTop,
+    _In_ INT xRight,
+    _In_ INT yBottom)
 {
-    INT Result;
-    RECTL Rect;
-    PREGION prgnNew;
-    PDC dc = DC_LockDc(hDC);
+    INT iComplexity;
+    RECTL rect;
+    PDC pdc;
 
-    if (!dc)
+    /* Lock the DC */
+    pdc = DC_LockDc(hdc);
+    if (pdc == NULL)
     {
         EngSetLastError(ERROR_INVALID_HANDLE);
         return ERROR;
     }
 
-    Rect.left = LeftRect;
-    Rect.top = TopRect;
-    Rect.right = RightRect;
-    Rect.bottom = BottomRect;
-
-    IntLPtoDP(dc, (LPPOINT)&Rect, 2);
+    /* Convert coordinates to device space */
+    rect.left = xLeft;
+    rect.top = yTop;
+    rect.right = xRight;
+    rect.bottom = yBottom;
+    RECTL_vMakeWellOrdered(&rect);
+    IntLPtoDP(pdc, (LPPOINT)&rect, 2);
 
-    prgnNew = IntSysCreateRectpRgnIndirect(&Rect);
-    if (!prgnNew)
+    /* Check if we already have a clip region */
+    if (pdc->dclevel.prgnClip != NULL)
     {
-        Result = ERROR;
+        /* We have a region, subtract the rect */
+        iComplexity = REGION_SubtractRectFromRgn(pdc->dclevel.prgnClip,
+                                                 pdc->dclevel.prgnClip,
+                                                 &rect);
+
+        /* Emulate Windows behavior */
+        if (iComplexity == SIMPLEREGION)
+            iComplexity = COMPLEXREGION;
     }
     else
     {
-        if (!dc->dclevel.prgnClip)
+        /* Check if the rect intersects with the window rect */
+        if (RECTL_bIntersectRect(&rect, &rect, &pdc->erclWindow))
         {
-            dc->dclevel.prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0);
-            IntGdiCombineRgn(dc->dclevel.prgnClip, dc->prgnVis, prgnNew, RGN_DIFF);
-            Result = SIMPLEREGION;
+            /* It does. In this case create an empty region */
+            pdc->dclevel.prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0);
+            iComplexity = NULLREGION;
         }
         else
         {
-            Result = IntGdiCombineRgn(dc->dclevel.prgnClip, dc->dclevel.prgnClip, prgnNew, RGN_DIFF);
+            /* Otherwise, emulate strange Windows behavior... */
+            pdc->dclevel.prgnClip = IntSysCreateRectpRgn(0, 0, 1, 1);
+            iComplexity = COMPLEXREGION;
+        }
+
+        /* Check if creating the region failed */
+        if (pdc->dclevel.prgnClip == NULL)
+        {
+            /* Return error code */
+            iComplexity = ERROR;
         }
-        REGION_Delete(prgnNew);
     }
-    if (Result != ERROR)
-        dc->fs |= DC_FLAG_DIRTY_RAO;
 
-    DC_UnlockDc(dc);
+    /* If we succeeded, mark the RAO region as dirty */
+    if (iComplexity != ERROR)
+        pdc->fs |= DC_FLAG_DIRTY_RAO;
 
-    return Result;
+    /* Unlock the DC */
+    DC_UnlockDc(pdc);
+
+    return iComplexity;
 }
 
 INT
index 0c20aff..4032c79 100644 (file)
@@ -1773,6 +1773,23 @@ REGION_UnionRectWithRgn(
     REGION_UnionRegion(rgn, rgn, &region);
 }
 
+INT
+FASTCALL
+REGION_SubtractRectFromRgn(
+    PREGION prgnDest,
+    PREGION prgnSrc,
+    const RECTL *prcl)
+{
+    REGION rgnLocal;
+
+    rgnLocal.Buffer = &rgnLocal.rdh.rcBound;
+    rgnLocal.rdh.nCount = 1;
+    rgnLocal.rdh.nRgnSize = sizeof(RECT);
+    rgnLocal.rdh.rcBound = *prcl;
+    REGION_SubtractRegion(prgnDest, prgnSrc, &rgnLocal);
+    return REGION_Complexity(prgnDest);
+}
+
 BOOL FASTCALL
 REGION_CreateSimpleFrameRgn(
     PROSRGNDATA rgn,
index e735b15..73bf85a 100644 (file)
@@ -25,6 +25,7 @@ typedef struct _ROSRGNDATA
 PROSRGNDATA FASTCALL REGION_AllocRgnWithHandle(INT n);
 PROSRGNDATA FASTCALL REGION_AllocUserRgnWithHandle(INT n);
 VOID FASTCALL REGION_UnionRectWithRgn(ROSRGNDATA *rgn, const RECTL *rect);
+INT FASTCALL REGION_SubtractRectFromRgn(PREGION prgnDest, PREGION prgnSrc, const RECTL *prcl);
 INT FASTCALL REGION_GetRgnBox(PROSRGNDATA Rgn, RECTL *pRect);
 BOOL FASTCALL REGION_RectInRegion(PROSRGNDATA Rgn, const RECTL *rc);
 BOOL FASTCALL REGION_PtInRegion(PREGION, INT, INT);