Author: weiden Date: Sun Oct 28 23:07:28 2007 New Revision: 29938
URL: http://svn.reactos.org/svn/reactos?rev=29938&view=rev Log: optimize FrameRgn for simple rectangular regions
Modified: trunk/reactos/subsystems/win32/win32k/objects/region.c
Modified: trunk/reactos/subsystems/win32/win32k/objects/region.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/obj... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/objects/region.c (original) +++ trunk/reactos/subsystems/win32/win32k/objects/region.c Sun Oct 28 23:07:28 2007 @@ -1755,6 +1755,77 @@ REGION_UnionRegion(rgn, rgn, ®ion); }
+BOOL FASTCALL REGION_CreateSimpleFrameRgn(PROSRGNDATA rgn, INT x, INT y) +{ + RECT rc[4]; + PRECT 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) + { + rgn->rdh.nRgnSize = 0; + return FALSE; + } + + COPY_RECTS(rgn->Buffer, rc, rgn->rdh.nCount); + } + } + + return TRUE; +} + BOOL FASTCALL REGION_CreateFrameRgn(HRGN hDest, HRGN hSrc, INT x, INT y) { PROSRGNDATA srcObj, destObj; @@ -1784,57 +1855,70 @@ return FALSE; }
- /* Original region moved to right */ - rc = (PRECT)srcObj->Buffer; - for (i = 0; i < srcObj->rdh.nCount; i++) + if (srcObj->rdh.iType == SIMPLEREGION) { - rc->left += x; - rc->right += x; - rc++; + if (!REGION_CreateSimpleFrameRgn(destObj, x, y)) + { + EMPTY_REGION(destObj); + RGNDATA_UnlockRgn(destObj); + RGNDATA_UnlockRgn(srcObj); + return FALSE; + } } - REGION_IntersectRegion(destObj, destObj, srcObj); - - /* Original region moved to left */ - rc = (PRECT)srcObj->Buffer; - for (i = 0; i < srcObj->rdh.nCount; i++) + else { - rc->left -= 2 * x; - rc->right -= 2 * x; - rc++; + /* Original region moved to right */ + rc = (PRECT)srcObj->Buffer; + for (i = 0; i < srcObj->rdh.nCount; i++) + { + rc->left += x; + rc->right += x; + rc++; + } + REGION_IntersectRegion(destObj, destObj, srcObj); + + /* Original region moved to left */ + rc = (PRECT)srcObj->Buffer; + for (i = 0; i < srcObj->rdh.nCount; i++) + { + rc->left -= 2 * x; + rc->right -= 2 * x; + rc++; + } + REGION_IntersectRegion(destObj, destObj, srcObj); + + /* Original region moved down */ + rc = (PRECT)srcObj->Buffer; + for (i = 0; i < srcObj->rdh.nCount; i++) + { + rc->left += x; + rc->right += x; + rc->top += y; + rc->bottom += y; + rc++; + } + REGION_IntersectRegion(destObj, destObj, srcObj); + + /* Original region moved up */ + rc = (PRECT)srcObj->Buffer; + for (i = 0; i < srcObj->rdh.nCount; i++) + { + rc->top -= 2 * y; + rc->bottom -= 2 * y; + rc++; + } + REGION_IntersectRegion(destObj, destObj, srcObj); + + /* Restore the original region */ + rc = (PRECT)srcObj->Buffer; + for (i = 0; i < srcObj->rdh.nCount; i++) + { + rc->top += y; + rc->bottom += y; + rc++; + } + REGION_SubtractRegion(destObj, srcObj, destObj); } - REGION_IntersectRegion(destObj, destObj, srcObj); - - /* Original region moved down */ - rc = (PRECT)srcObj->Buffer; - for (i = 0; i < srcObj->rdh.nCount; i++) - { - rc->left += x; - rc->right += x; - rc->top += y; - rc->bottom += y; - rc++; - } - REGION_IntersectRegion(destObj, destObj, srcObj); - - /* Original region moved up */ - rc = (PRECT)srcObj->Buffer; - for (i = 0; i < srcObj->rdh.nCount; i++) - { - rc->top -= 2 * y; - rc->bottom -= 2 * y; - rc++; - } - REGION_IntersectRegion(destObj, destObj, srcObj); - - /* Restore the original region */ - rc = (PRECT)srcObj->Buffer; - for (i = 0; i < srcObj->rdh.nCount; i++) - { - rc->top += y; - rc->bottom += y; - rc++; - } - REGION_SubtractRegion(destObj, srcObj, destObj);
RGNDATA_UnlockRgn(destObj); RGNDATA_UnlockRgn(srcObj);