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?... ============================================================================== --- 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; }