Author: tkreuzer
Date: Thu Dec 18 08:12:51 2014
New Revision: 65734

URL: http://svn.reactos.org/svn/reactos?rev=65734&view=rev
Log:
[WIN32K]
Improve REGION_bMakeFrameRegion and REGION_bMakeSimpleFrameRgn

Modified:
    trunk/reactos/win32ss/gdi/ntgdi/region.c

Modified: trunk/reactos/win32ss/gdi/ntgdi/region.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/region.c?rev=65734&r1=65733&r2=65734&view=diff
==============================================================================
--- trunk/reactos/win32ss/gdi/ntgdi/region.c    [iso-8859-1] (original)
+++ trunk/reactos/win32ss/gdi/ntgdi/region.c    [iso-8859-1] Thu Dec 18 
08:12:51 2014
@@ -1759,80 +1759,92 @@
     return REGION_Complexity(prgnDest);
 }
 
+static
 BOOL
-FASTCALL
-REGION_CreateSimpleFrameRgn(
-    PREGION rgn,
-    INT x,
-    INT y)
-{
-    RECTL rc[4];
-    PRECTL prc;
-
-    if ((x != 0) || (y != 0))
-    {
-        prc = rc;
-
-        if ((rgn->rdh.rcBound.bottom - rgn->rdh.rcBound.top > y * 2) &&
-            (rgn->rdh.rcBound.right - rgn->rdh.rcBound.left > x * 2))
-        {
-            if (y != 0)
-            {
-                /* Top rectangle */
-                prc->left = rgn->rdh.rcBound.left;
-                prc->top = rgn->rdh.rcBound.top;
-                prc->right = rgn->rdh.rcBound.right;
-                prc->bottom = prc->top + y;
-                prc++;
-            }
-
-            if (x != 0)
-            {
-                /* Left rectangle */
-                prc->left = rgn->rdh.rcBound.left;
-                prc->top = rgn->rdh.rcBound.top + y;
-                prc->right = prc->left + x;
-                prc->bottom = rgn->rdh.rcBound.bottom - y;
-                prc++;
-
-                /* Right rectangle */
-                prc->left = rgn->rdh.rcBound.right - x;
-                prc->top = rgn->rdh.rcBound.top + y;
-                prc->right = rgn->rdh.rcBound.right;
-                prc->bottom = rgn->rdh.rcBound.bottom - y;
-                prc++;
-            }
-
-            if (y != 0)
-            {
-                /* Bottom rectangle */
-                prc->left = rgn->rdh.rcBound.left;
-                prc->top = rgn->rdh.rcBound.bottom - y;
-                prc->right = rgn->rdh.rcBound.right;
-                prc->bottom = rgn->rdh.rcBound.bottom;
-                prc++;
-            }
-        }
-
-        if (prc != rc)
-        {
-            /* The frame results in a complex region. rcBounds remains
-               the same, though. */
-            rgn->rdh.nCount = (DWORD)(prc - rc);
-            ASSERT(rgn->rdh.nCount > 1);
-            rgn->rdh.nRgnSize = rgn->rdh.nCount * sizeof(RECT);
-            rgn->Buffer = ExAllocatePoolWithTag(PagedPool,
-                                                rgn->rdh.nRgnSize,
-                                                TAG_REGION);
-            if (rgn->Buffer == NULL)
-            {
-                rgn->rdh.nRgnSize = 0;
-                return FALSE;
-            }
-
-            _PRAGMA_WARNING_SUPPRESS(__WARNING_MAYBE_UNINIT_VAR) // rc is 
initialized
-            COPY_RECTS(rgn->Buffer, rc, rgn->rdh.nCount);
-        }
+REGION_bMakeSimpleFrameRgn(
+    _Inout_ PREGION prgn,
+    _In_ PRECTL prclSrc,
+    _In_ INT cx,
+    _In_ INT cy)
+{
+    RECTL arcl[4];
+    UINT i;
+
+    NT_ASSERT((cx >= 0) && (cy >= 0));
+    NT_ASSERT((prclSrc->bottom > prclSrc->top) &&
+              (prclSrc->right > prclSrc->left));
+
+    /* Start with an empty region */
+    EMPTY_REGION(prgn);
+
+    /* Check for the case where the frame covers the whole rect */
+    if (((prclSrc->bottom - prclSrc->top) <= cy * 2) ||
+        ((prclSrc->right - prclSrc->left) <= cx * 2))
+    {
+        prgn->rdh.rcBound = *prclSrc;
+        prgn->Buffer[0] = *prclSrc;
+        prgn->rdh.nCount = 1;
+        return TRUE;
+    }
+
+    i = 0;
+
+    if (cy != 0)
+    {
+        /* Top rectangle */
+        arcl[i].left = prclSrc->left;
+        arcl[i].top = prclSrc->top;
+        arcl[i].right = prclSrc->right;
+        arcl[i].bottom = prclSrc->top + cy;
+        i++;
+    }
+
+    if (cx != 0)
+    {
+        /* Left rectangle */
+        arcl[i].left = prclSrc->left;
+        arcl[i].top = prclSrc->top + cy;
+        arcl[i].right = prclSrc->left + cx;
+        arcl[i].bottom = prclSrc->bottom - cy;
+        i++;
+
+        /* Right rectangle */
+        arcl[i].left = prclSrc->right - cx;
+        arcl[i].top = prclSrc->top + cy;
+        arcl[i].right = prclSrc->right;
+        arcl[i].bottom = prclSrc->bottom - cy;
+        i++;
+    }
+
+    if (cy != 0)
+    {
+        /* Bottom rectangle */
+        arcl[i].left = prclSrc->left;
+        arcl[i].top = prclSrc->bottom - cy;
+        arcl[i].right = prclSrc->right;
+        arcl[i].bottom = prclSrc->bottom;
+        i++;
+    }
+
+    if (i != 0)
+    {
+        /* The frame results in a complex region. rcBounds remains
+           the same, though. */
+        prgn->rdh.nCount = i;
+        NT_ASSERT(prgn->rdh.nCount > 1);
+        prgn->rdh.nRgnSize = prgn->rdh.nCount * sizeof(RECT);
+        NT_ASSERT(prgn->Buffer == &prgn->rdh.rcBound);
+        prgn->Buffer = ExAllocatePoolWithTag(PagedPool,
+                                            prgn->rdh.nRgnSize,
+                                            TAG_REGION);
+        if (prgn->Buffer == NULL)
+        {
+            prgn->rdh.nRgnSize = 0;
+            return FALSE;
+        }
+
+        _PRAGMA_WARNING_SUPPRESS(__WARNING_MAYBE_UNINIT_VAR) // arcl is 
initialized
+        COPY_RECTS(prgn->Buffer, arcl, prgn->rdh.nCount);
     }
 
     return TRUE;
@@ -1842,60 +1854,83 @@
 BOOL
 REGION_bMakeFrameRegion(
     _Inout_ PREGION prgnDest,
-    _In_ PREGION prgnSrc,
+    _Inout_ PREGION prgnSrc,
     _In_ INT cx,
     _In_ INT cy)
 {
-
+    /* Handle negative cx / cy */
+    cx = abs(cx);
+    cy = abs(cy);
+
+    /* Check border size (the cast is necessary to catch cx/cy == INT_MIN!) */
+    if (((UINT)cx > MAX_COORD) || ((UINT)cy > MAX_COORD))
+    {
+        return FALSE;
+    }
+
+    /* Fail on empty source region */
     if (!REGION_NOT_EMPTY(prgnSrc))
     {
         return FALSE;
     }
 
+    /* Handle trivial case */
+    if ((cx == 0) && (cy == 0))
+    {
+        EMPTY_REGION(prgnDest);
+        return TRUE;
+    }
+
+    /* Handle simple source region */
+    if (REGION_Complexity(prgnSrc) == SIMPLEREGION)
+    {
+        return REGION_bMakeSimpleFrameRgn(prgnDest, &prgnSrc->rdh.rcBound, cx, 
cy);
+    }
+
+    /* Check if we can move the region to create the frame region */
+    if ((prgnSrc->rdh.rcBound.left < (MIN_COORD + cx)) ||
+        (prgnSrc->rdh.rcBound.top < (MIN_COORD + cy)) ||
+        (prgnSrc->rdh.rcBound.right > (MAX_COORD - cx)) ||
+        (prgnSrc->rdh.rcBound.bottom > (MAX_COORD - cy)))
+    {
+        return FALSE;
+    }
+
+    /* Copy the source region */
     if (!REGION_CopyRegion(prgnDest, prgnSrc))
     {
         return FALSE;
     }
 
-    if (REGION_Complexity(prgnSrc) == SIMPLEREGION)
-    {
-        if (!REGION_CreateSimpleFrameRgn(prgnDest, cx, cy))
-        {
-            return FALSE;
-        }
-    }
-    else
-    {
-        /* Move the source region to the bottom-right */
-        REGION_bOffsetRgn(prgnSrc, cx, cy);
-
-        /* Intersect with the source region (this crops the top-left frame) */
-        REGION_IntersectRegion(prgnDest, prgnDest, prgnSrc);
-
-        /* Move the source region to the bottom-left */
-        REGION_bOffsetRgn(prgnSrc, -2 * cx, 0);
-
-        /* Intersect with the source region (this crops the top-right frame) */
-        REGION_IntersectRegion(prgnDest, prgnDest, prgnSrc);
-
-        /* Move the source region to the top-left */
-        REGION_bOffsetRgn(prgnSrc, 0, -2 * cy);
-
-        /* Intersect with the source region (this crops the bottom-right 
frame) */
-        REGION_IntersectRegion(prgnDest, prgnDest, prgnSrc);
-
-        /* Move the source region to the top-right  */
-        REGION_bOffsetRgn(prgnSrc, 2 * cx, 0);
-
-        /* Intersect with the source region (this crops the bottom-left frame) 
*/
-        REGION_IntersectRegion(prgnDest, prgnDest, prgnSrc);
-
-        /* Move the source region back to the original position */
-        REGION_bOffsetRgn(prgnSrc, -cx, cy);
-
-        /* Finally subtract the cropped region from the source */
-        REGION_SubtractRegion(prgnDest, prgnSrc, prgnDest);
-    }
+    /* Move the source region to the bottom-right */
+    NT_VERIFY(REGION_bOffsetRgn(prgnSrc, cx, cy));
+
+    /* Intersect with the source region (this crops the top-left frame) */
+    REGION_IntersectRegion(prgnDest, prgnDest, prgnSrc);
+
+    /* Move the source region to the bottom-left */
+    NT_VERIFY(REGION_bOffsetRgn(prgnSrc, -2 * cx, 0));
+
+    /* Intersect with the source region (this crops the top-right frame) */
+    REGION_IntersectRegion(prgnDest, prgnDest, prgnSrc);
+
+    /* Move the source region to the top-left */
+    NT_VERIFY(REGION_bOffsetRgn(prgnSrc, 0, -2 * cy));
+
+    /* Intersect with the source region (this crops the bottom-right frame) */
+    REGION_IntersectRegion(prgnDest, prgnDest, prgnSrc);
+
+    /* Move the source region to the top-right  */
+    NT_VERIFY(REGION_bOffsetRgn(prgnSrc, 2 * cx, 0));
+
+    /* Intersect with the source region (this crops the bottom-left frame) */
+    REGION_IntersectRegion(prgnDest, prgnDest, prgnSrc);
+
+    /* Move the source region back to the original position */
+    NT_VERIFY(REGION_bOffsetRgn(prgnSrc, -cx, cy));
+
+    /* Finally subtract the cropped region from the source */
+    REGION_SubtractRegion(prgnDest, prgnSrc, prgnDest);
 
     return TRUE;
 }


Reply via email to