mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
r=mkaply, a=blizzard More optimization for XP Region code - OS/2 only
This commit is contained in:
parent
d4a3aa7de7
commit
d8e94e7b47
@ -22,6 +22,10 @@
|
||||
#include "nsRegion.h"
|
||||
|
||||
|
||||
#define MIN_INT32 (-PR_INT32 (0x7FFFFFFF) - 1)
|
||||
#define MAX_INT32 (PR_INT32 (0x7FFFFFFF))
|
||||
|
||||
|
||||
// Custom memory allocator for nsRegion::RgnRect structures.
|
||||
// Entries are allocated from global memory pool.
|
||||
// Memory pool can grow in size, but it can't shrink.
|
||||
@ -64,8 +68,8 @@ public:
|
||||
RgnRectMemoryAllocator (PRUint32 aNumOfEntries);
|
||||
~RgnRectMemoryAllocator ();
|
||||
|
||||
inline nsRegion::RgnRect* Alloc ();
|
||||
inline void Free (nsRegion::RgnRect* aRect);
|
||||
nsRegion::RgnRect* Alloc ();
|
||||
void Free (nsRegion::RgnRect* aRect);
|
||||
};
|
||||
|
||||
|
||||
@ -89,7 +93,7 @@ RgnRectMemoryAllocator::~RgnRectMemoryAllocator ()
|
||||
PR_DestroyLock (mLock);
|
||||
}
|
||||
|
||||
inline nsRegion::RgnRect* RgnRectMemoryAllocator::Alloc ()
|
||||
nsRegion::RgnRect* RgnRectMemoryAllocator::Alloc ()
|
||||
{
|
||||
Lock ();
|
||||
|
||||
@ -108,7 +112,7 @@ inline nsRegion::RgnRect* RgnRectMemoryAllocator::Alloc ()
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline void RgnRectMemoryAllocator::Free (nsRegion::RgnRect* aRect)
|
||||
void RgnRectMemoryAllocator::Free (nsRegion::RgnRect* aRect)
|
||||
{
|
||||
Lock ();
|
||||
mFreeEntries++;
|
||||
@ -122,12 +126,12 @@ inline void RgnRectMemoryAllocator::Free (nsRegion::RgnRect* aRect)
|
||||
static RgnRectMemoryAllocator gRectPool (INIT_MEM_CHUNK_ENTRIES);
|
||||
|
||||
|
||||
void* nsRegion::RgnRect::operator new (size_t)
|
||||
inline void* nsRegion::RgnRect::operator new (size_t)
|
||||
{
|
||||
return gRectPool.Alloc ();
|
||||
}
|
||||
|
||||
void nsRegion::RgnRect::operator delete (void* aRect, size_t)
|
||||
inline void nsRegion::RgnRect::operator delete (void* aRect, size_t)
|
||||
{
|
||||
gRectPool.Free (NS_STATIC_CAST (RgnRect*, aRect));
|
||||
}
|
||||
@ -138,7 +142,6 @@ void nsRegion::RgnRect::operator delete (void* aRect, size_t)
|
||||
nsRegion::nsRegion ()
|
||||
{
|
||||
mRectListHead.prev = mRectListHead.next = &mRectListHead;
|
||||
mRectListHead.width = mRectListHead.height = -100; // This is dummy marker node
|
||||
mCurRect = &mRectListHead;
|
||||
mRectCount = 0;
|
||||
mBoundRect.SetRect (0, 0, 0, 0);
|
||||
@ -187,6 +190,40 @@ void nsRegion::SetToElements (PRUint32 aCount)
|
||||
}
|
||||
|
||||
|
||||
// Save the entire chain of linked elements in 'prev' field of the RgnRect structure.
|
||||
// After that forward-only iterations using 'next' field could still be used.
|
||||
// Some elements from forward-only chain could be temporarily removed to optimize inner loops.
|
||||
// The original double linked state could be restored by call to RestoreLinkChain ().
|
||||
|
||||
void nsRegion::SaveLinkChain ()
|
||||
{
|
||||
RgnRect* pRect = &mRectListHead;
|
||||
|
||||
do
|
||||
{
|
||||
pRect->prev = pRect->next;
|
||||
pRect = pRect->next;
|
||||
} while (pRect != &mRectListHead);
|
||||
}
|
||||
|
||||
|
||||
void nsRegion::RestoreLinkChain ()
|
||||
{
|
||||
RgnRect* pPrev = &mRectListHead;
|
||||
RgnRect* pRect = mRectListHead.next = mRectListHead.prev;
|
||||
|
||||
while (pRect != &mRectListHead)
|
||||
{
|
||||
pRect->next = pRect->prev;
|
||||
pRect->prev = pPrev;
|
||||
pPrev = pRect;
|
||||
pRect = pRect->next;
|
||||
}
|
||||
|
||||
mRectListHead.prev = pPrev;
|
||||
}
|
||||
|
||||
|
||||
// Insert node in right place of sorted list
|
||||
// If necessary then bounding rectangle could be updated and rectangle combined
|
||||
// with neighbour rectangles. This is usually done in Optimize ()
|
||||
@ -199,7 +236,7 @@ void nsRegion::InsertInPlace (RgnRect* aRect, PRBool aOptimizeOnFly)
|
||||
{
|
||||
if (aRect->y > mCurRect->y)
|
||||
{
|
||||
mRectListHead.y = 2147483647;
|
||||
mRectListHead.y = MAX_INT32;
|
||||
|
||||
while (aRect->y > mCurRect->next->y)
|
||||
mCurRect = mCurRect->next;
|
||||
@ -211,7 +248,7 @@ void nsRegion::InsertInPlace (RgnRect* aRect, PRBool aOptimizeOnFly)
|
||||
} else
|
||||
if (aRect->y < mCurRect->y)
|
||||
{
|
||||
mRectListHead.y = -2147483647;
|
||||
mRectListHead.y = MIN_INT32;
|
||||
|
||||
while (aRect->y < mCurRect->prev->y)
|
||||
mCurRect = mCurRect->prev;
|
||||
@ -224,7 +261,7 @@ void nsRegion::InsertInPlace (RgnRect* aRect, PRBool aOptimizeOnFly)
|
||||
{
|
||||
if (aRect->x > mCurRect->x)
|
||||
{
|
||||
mRectListHead.y = 2147483647;
|
||||
mRectListHead.y = MAX_INT32;
|
||||
|
||||
while (aRect->y == mCurRect->next->y && aRect->x > mCurRect->next->x)
|
||||
mCurRect = mCurRect->next;
|
||||
@ -232,7 +269,7 @@ void nsRegion::InsertInPlace (RgnRect* aRect, PRBool aOptimizeOnFly)
|
||||
InsertAfter (aRect, mCurRect);
|
||||
} else
|
||||
{
|
||||
mRectListHead.y = -2147483647;
|
||||
mRectListHead.y = MIN_INT32;
|
||||
|
||||
while (aRect->y == mCurRect->prev->y && aRect->x < mCurRect->prev->x)
|
||||
mCurRect = mCurRect->prev;
|
||||
@ -297,30 +334,69 @@ nsRegion::RgnRect* nsRegion::Remove (RgnRect* aRect)
|
||||
|
||||
void nsRegion::Optimize ()
|
||||
{
|
||||
mBoundRect.SetRect (0, 0, 0, 0);
|
||||
RgnRect* pRect = mRectListHead.next;
|
||||
if (mRectCount == 0)
|
||||
mBoundRect.SetRect (0, 0, 0, 0);
|
||||
else
|
||||
{
|
||||
RgnRect* pRect = mRectListHead.next;
|
||||
PRInt32 xmost = mRectListHead.prev->XMost ();
|
||||
PRInt32 ymost = mRectListHead.prev->YMost ();
|
||||
mBoundRect.x = mRectListHead.next->x;
|
||||
mBoundRect.y = mRectListHead.next->y;
|
||||
|
||||
while (pRect != &mRectListHead)
|
||||
{
|
||||
// Try to combine with rectangle on right side
|
||||
while (pRect->y == pRect->next->y && pRect->height == pRect->next->height &&
|
||||
pRect->XMost () == pRect->next->x)
|
||||
{
|
||||
pRect->width += pRect->next->width;
|
||||
delete Remove (pRect->next);
|
||||
}
|
||||
|
||||
// Try to combine with rectangle under this one
|
||||
while (pRect->x == pRect->next->x && pRect->width == pRect->next->width &&
|
||||
pRect->YMost () == pRect->next->y)
|
||||
{
|
||||
pRect->height += pRect->next->height;
|
||||
delete Remove (pRect->next);
|
||||
}
|
||||
|
||||
// Determine bound rectangle. Use fact that rectangles are sorted.
|
||||
if (pRect->x < mBoundRect.x) mBoundRect.x = pRect->x;
|
||||
if (pRect->XMost () > xmost) xmost = pRect->XMost ();
|
||||
if (pRect->YMost () > ymost) ymost = pRect->YMost ();
|
||||
|
||||
pRect = pRect->next;
|
||||
}
|
||||
|
||||
mBoundRect.width = xmost - mBoundRect.x;
|
||||
mBoundRect.height = ymost - mBoundRect.y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Move rectangles starting from 'aStartRect' till end of the list to the destionation region.
|
||||
// Important for temporary objects - instead of copying rectangles with Merge () and then
|
||||
// emptying region in destructor they could be moved to destination region in one step.
|
||||
|
||||
void nsRegion::MoveInto (nsRegion& aDestRegion, const RgnRect* aStartRect)
|
||||
{
|
||||
RgnRect* pRect = NS_STATIC_CAST (RgnRect*, aStartRect);
|
||||
RgnRect* pPrev = pRect->prev;
|
||||
|
||||
while (pRect != &mRectListHead)
|
||||
{
|
||||
// Try to combine with rectangle on right side
|
||||
while (pRect->y == pRect->next->y && pRect->height == pRect->next->height &&
|
||||
pRect->XMost () == pRect->next->x)
|
||||
{
|
||||
pRect->width += pRect->next->width;
|
||||
delete Remove (pRect->next);
|
||||
}
|
||||
RgnRect* next = pRect->next;
|
||||
aDestRegion.InsertInPlace (pRect);
|
||||
|
||||
// Try to combine with rectangle under this one
|
||||
while (pRect->x == pRect->next->x && pRect->width == pRect->next->width &&
|
||||
pRect->YMost () == pRect->next->y)
|
||||
{
|
||||
pRect->height += pRect->next->height;
|
||||
delete Remove (pRect->next);
|
||||
}
|
||||
|
||||
mBoundRect.UnionRect (mBoundRect, *pRect);
|
||||
pRect = pRect->next;
|
||||
mRectCount--;
|
||||
pRect = next;
|
||||
}
|
||||
|
||||
pPrev->next = &mRectListHead;
|
||||
mRectListHead.prev = pPrev;
|
||||
mCurRect = mRectListHead.next;
|
||||
}
|
||||
|
||||
|
||||
@ -409,7 +485,7 @@ nsRegion& nsRegion::Copy (const nsRegion& aRegion)
|
||||
}
|
||||
|
||||
|
||||
nsRegion& nsRegion::Copy (const nsRect& aRect)
|
||||
nsRegion& nsRegion::Copy (const nsRectFast& aRect)
|
||||
{
|
||||
if (aRect.IsEmpty ())
|
||||
Empty ();
|
||||
@ -433,7 +509,7 @@ nsRegion& nsRegion::And (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
||||
Empty ();
|
||||
else
|
||||
{
|
||||
nsRect TmpRect;
|
||||
nsRectFast TmpRect;
|
||||
|
||||
if (aRgn1.mRectCount == 1 && aRgn2.mRectCount == 1) // Intersect rectangle with rectangle
|
||||
{
|
||||
@ -455,8 +531,8 @@ nsRegion& nsRegion::And (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
||||
else
|
||||
{
|
||||
nsRegion TmpRegion;
|
||||
const nsRegion* pSrcRgn1 = &aRgn1;
|
||||
const nsRegion* pSrcRgn2 = &aRgn2;
|
||||
nsRegion* pSrcRgn1 = NS_CONST_CAST (nsRegion*, &aRgn1);
|
||||
nsRegion* pSrcRgn2 = NS_CONST_CAST (nsRegion*, &aRgn2);
|
||||
|
||||
if (&aRgn1 == this) // Copy region if it is both source and result
|
||||
{
|
||||
@ -470,31 +546,54 @@ nsRegion& nsRegion::And (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
||||
pSrcRgn2 = &TmpRegion;
|
||||
}
|
||||
|
||||
// For outer loop prefer region for which at least one rectangle is below other's bound rectangle
|
||||
if (pSrcRgn2->mRectListHead.prev->y >= pSrcRgn1->mBoundRect.YMost ())
|
||||
{
|
||||
nsRegion* Tmp = pSrcRgn1;
|
||||
pSrcRgn1 = pSrcRgn2;
|
||||
pSrcRgn2 = Tmp;
|
||||
}
|
||||
|
||||
|
||||
SetToElements (0);
|
||||
const RgnRect* pSrcRect1 = pSrcRgn1->mRectListHead.next;
|
||||
pSrcRgn2->SaveLinkChain ();
|
||||
|
||||
pSrcRgn1->mRectListHead.y = MAX_INT32;
|
||||
pSrcRgn2->mRectListHead.y = MAX_INT32;
|
||||
|
||||
while (pSrcRect1 != &pSrcRgn1->mRectListHead)
|
||||
for (RgnRect* pSrcRect1 = pSrcRgn1->mRectListHead.next ;
|
||||
pSrcRect1->y < pSrcRgn2->mBoundRect.YMost () ; pSrcRect1 = pSrcRect1->next)
|
||||
{
|
||||
if (pSrcRect1->Intersects (pSrcRgn2->mBoundRect)) // Rectangle intersects region. Process each rectangle
|
||||
{
|
||||
const RgnRect* pSrcRect2 = pSrcRgn2->mRectListHead.next;
|
||||
RgnRect* pPrev2 = &pSrcRgn2->mRectListHead;
|
||||
|
||||
while (pSrcRect2 != &pSrcRgn2->mRectListHead)
|
||||
for (RgnRect* pSrcRect2 = pSrcRgn2->mRectListHead.next ;
|
||||
pSrcRect2->y < pSrcRect1->YMost () ; pSrcRect2 = pSrcRect2->next)
|
||||
{
|
||||
// Vertically sorted rectangles in SrcRgn2 are below the SrcRect1 - won't intersect
|
||||
if (pSrcRect2->y >= pSrcRect1->YMost ())
|
||||
break;
|
||||
if (pSrcRect2->YMost () <= pSrcRect1->y) // Rect2's bottom is above the top of Rect1.
|
||||
{ // No successive rectangles in Rgn1 can intersect it.
|
||||
pPrev2->next = pSrcRect2->next; // Remove Rect2 from Rgn2's checklist
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pSrcRect1->Contains (*pSrcRect2)) // Rect1 fully overlays Rect2.
|
||||
{ // No any other rectangle in Rgn1 can intersect it.
|
||||
pPrev2->next = pSrcRect2->next; // Remove Rect2 from Rgn2's checklist
|
||||
InsertInPlace (new RgnRect (*pSrcRect2));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (TmpRect.IntersectRect (*pSrcRect1, *pSrcRect2))
|
||||
InsertInPlace (new RgnRect (TmpRect));
|
||||
|
||||
pSrcRect2 = pSrcRect2->next;
|
||||
pPrev2 = pSrcRect2;
|
||||
}
|
||||
}
|
||||
|
||||
pSrcRect1 = pSrcRect1->next;
|
||||
}
|
||||
|
||||
pSrcRgn2->RestoreLinkChain ();
|
||||
Optimize ();
|
||||
}
|
||||
}
|
||||
@ -505,14 +604,14 @@ nsRegion& nsRegion::And (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
||||
}
|
||||
|
||||
|
||||
nsRegion& nsRegion::And (const nsRegion& aRegion, const nsRect& aRect)
|
||||
nsRegion& nsRegion::And (const nsRegion& aRegion, const nsRectFast& aRect)
|
||||
{
|
||||
// If either region or rectangle is empty then result is empty
|
||||
if (aRegion.mRectCount == 0 || aRect.IsEmpty ())
|
||||
Empty ();
|
||||
else // Intersect region with rectangle
|
||||
{
|
||||
nsRect TmpRect;
|
||||
nsRectFast TmpRect;
|
||||
|
||||
if (aRegion.mRectCount == 1) // Intersect rectangle with rectangle
|
||||
{
|
||||
@ -529,7 +628,7 @@ nsRegion& nsRegion::And (const nsRegion& aRegion, const nsRect& aRect)
|
||||
else
|
||||
{
|
||||
nsRegion TmpRegion;
|
||||
const nsRegion* pSrcRegion = &aRegion;
|
||||
nsRegion* pSrcRegion = NS_CONST_CAST (nsRegion*, &aRegion);
|
||||
|
||||
if (&aRegion == this) // Copy region if it is both source and result
|
||||
{
|
||||
@ -538,18 +637,13 @@ nsRegion& nsRegion::And (const nsRegion& aRegion, const nsRect& aRect)
|
||||
}
|
||||
|
||||
SetToElements (0);
|
||||
const RgnRect* pSrcRect = pSrcRegion->mRectListHead.next;
|
||||
pSrcRegion->mRectListHead.y = MAX_INT32;
|
||||
|
||||
while (pSrcRect != &pSrcRegion->mRectListHead)
|
||||
for (const RgnRect* pSrcRect = pSrcRegion->mRectListHead.next ;
|
||||
pSrcRect->y < aRect.YMost () ; pSrcRect = pSrcRect->next)
|
||||
{
|
||||
// Vertically sorted rectangles in SrcRegion are below the aRect - won't intersect
|
||||
if (pSrcRect->y >= aRect.YMost ())
|
||||
break;
|
||||
|
||||
if (TmpRect.IntersectRect (*pSrcRect, aRect))
|
||||
InsertInPlace (new RgnRect (TmpRect));
|
||||
|
||||
pSrcRect = pSrcRect->next;
|
||||
}
|
||||
|
||||
Optimize ();
|
||||
@ -588,8 +682,10 @@ nsRegion& nsRegion::Or (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
||||
else
|
||||
{
|
||||
nsRegion TmpRegion;
|
||||
TmpRegion.SubRegionFromRegion (aRgn1, aRgn2); // Get only parts of region which not overlap the other region
|
||||
Merge (TmpRegion, aRgn2);
|
||||
aRgn1.SubRegion (aRgn2, TmpRegion); // Get only parts of region which not overlap the other region
|
||||
Copy (aRgn2);
|
||||
TmpRegion.MoveInto (*this);
|
||||
Optimize ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -598,7 +694,7 @@ nsRegion& nsRegion::Or (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
||||
}
|
||||
|
||||
|
||||
nsRegion& nsRegion::Or (const nsRegion& aRegion, const nsRect& aRect)
|
||||
nsRegion& nsRegion::Or (const nsRegion& aRegion, const nsRectFast& aRect)
|
||||
{
|
||||
if (aRegion.mRectCount == 0) // Region empty. Result is equal to rectangle
|
||||
Copy (aRect);
|
||||
@ -621,7 +717,7 @@ nsRegion& nsRegion::Or (const nsRegion& aRegion, const nsRect& aRect)
|
||||
Copy (aRect);
|
||||
else
|
||||
{
|
||||
SubRectFromRegion (aRegion, aRect); // Exclude from region parts that overlap the rectangle
|
||||
aRegion.SubRect (aRect, *this); // Exclude from region parts that overlap the rectangle
|
||||
InsertInPlace (new RgnRect (aRect));
|
||||
Optimize ();
|
||||
}
|
||||
@ -651,21 +747,21 @@ nsRegion& nsRegion::Xor (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
||||
// Region is simple rectangle and it fully overlays other region
|
||||
if (aRgn1.mRectCount == 1 && aRgn1.mBoundRect.Contains (aRgn2.mBoundRect))
|
||||
{
|
||||
SubRegionFromRegion (aRgn1, aRgn2);
|
||||
aRgn1.SubRegion (aRgn2, *this);
|
||||
Optimize ();
|
||||
} else
|
||||
// Region is simple rectangle and it fully overlays other region
|
||||
if (aRgn2.mRectCount == 1 && aRgn2.mBoundRect.Contains (aRgn1.mBoundRect))
|
||||
{
|
||||
SubRegionFromRegion (aRgn2, aRgn1);
|
||||
aRgn2.SubRegion (aRgn1, *this);
|
||||
Optimize ();
|
||||
} else
|
||||
{
|
||||
nsRegion TmpRegion1, TmpRegion2;
|
||||
TmpRegion2.And (aRgn1, aRgn2); // Overlay
|
||||
TmpRegion1.SubRegionFromRegion (aRgn1, TmpRegion2); // aRgn1 - Overlay
|
||||
TmpRegion2.SubRegionFromRegion (aRgn2, TmpRegion2); // aRgn2 - Overlay
|
||||
Merge (TmpRegion1, TmpRegion2);
|
||||
nsRegion TmpRegion;
|
||||
aRgn1.SubRegion (aRgn2, TmpRegion);
|
||||
aRgn2.SubRegion (aRgn1, *this);
|
||||
TmpRegion.MoveInto (*this);
|
||||
Optimize ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -674,7 +770,7 @@ nsRegion& nsRegion::Xor (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
||||
}
|
||||
|
||||
|
||||
nsRegion& nsRegion::Xor (const nsRegion& aRegion, const nsRect& aRect)
|
||||
nsRegion& nsRegion::Xor (const nsRegion& aRegion, const nsRectFast& aRect)
|
||||
{
|
||||
if (aRegion.mRectCount == 0) // Region empty. Result is equal to rectangle
|
||||
Copy (aRect);
|
||||
@ -692,23 +788,23 @@ nsRegion& nsRegion::Xor (const nsRegion& aRegion, const nsRect& aRect)
|
||||
// Region is simple rectangle and it fully overlays rectangle
|
||||
if (aRegion.mRectCount == 1 && aRegion.mBoundRect.Contains (aRect))
|
||||
{
|
||||
SubRectFromRegion (aRegion, aRect);
|
||||
aRegion.SubRect (aRect, *this);
|
||||
Optimize ();
|
||||
} else
|
||||
if (aRect.Contains (aRegion.mBoundRect)) // Rectangle fully overlays region
|
||||
{
|
||||
nsRegion TmpRegion;
|
||||
TmpRegion.Copy (aRect);
|
||||
SubRegionFromRegion (TmpRegion, aRegion);
|
||||
TmpRegion.SubRegion (aRegion, *this);
|
||||
Optimize ();
|
||||
} else
|
||||
{
|
||||
nsRegion TmpRegion1, TmpRegion2, TmpRegion3;
|
||||
TmpRegion3.Copy (aRect);
|
||||
TmpRegion2.And (aRegion, aRect); // Overlay
|
||||
TmpRegion1.SubRegionFromRegion (aRegion, TmpRegion2); // aRegion - Overlay
|
||||
TmpRegion2.SubRegionFromRegion (TmpRegion3, TmpRegion2); // aRect - Overlay
|
||||
Merge (TmpRegion1, TmpRegion2);
|
||||
nsRegion TmpRegion;
|
||||
TmpRegion.Copy (aRect);
|
||||
TmpRegion.SubRegion (aRegion, TmpRegion);
|
||||
aRegion.SubRect (aRect, *this);
|
||||
TmpRegion.MoveInto (*this);
|
||||
Optimize ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -733,7 +829,7 @@ nsRegion& nsRegion::Sub (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
||||
Copy (aRgn1);
|
||||
else
|
||||
{
|
||||
SubRegionFromRegion (aRgn1, aRgn2);
|
||||
aRgn1.SubRegion (aRgn2, *this);
|
||||
Optimize ();
|
||||
}
|
||||
}
|
||||
@ -742,7 +838,7 @@ nsRegion& nsRegion::Sub (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
||||
}
|
||||
|
||||
|
||||
nsRegion& nsRegion::Sub (const nsRegion& aRegion, const nsRect& aRect)
|
||||
nsRegion& nsRegion::Sub (const nsRegion& aRegion, const nsRectFast& aRect)
|
||||
{
|
||||
if (aRegion.mRectCount == 0) // If source is empty then result is empty, too
|
||||
Empty ();
|
||||
@ -759,7 +855,7 @@ nsRegion& nsRegion::Sub (const nsRegion& aRegion, const nsRect& aRect)
|
||||
Empty ();
|
||||
else
|
||||
{
|
||||
SubRectFromRegion (aRegion, aRect);
|
||||
aRegion.SubRect (aRect, *this);
|
||||
Optimize ();
|
||||
}
|
||||
}
|
||||
@ -769,186 +865,221 @@ nsRegion& nsRegion::Sub (const nsRegion& aRegion, const nsRect& aRect)
|
||||
}
|
||||
|
||||
|
||||
// Subtract one region from another.
|
||||
// Subtract region from current region.
|
||||
// Both regions are non-empty and they intersect each other.
|
||||
// Result could be empty if aRgn2 is rectangle that fully overlays aRgn1.
|
||||
// Optimize () is not called (bound rectangle is not updated).
|
||||
// Result could be empty region if aRgn2 is rectangle that fully overlays aRgn1.
|
||||
// Optimize () is not called on exit (bound rectangle is not updated).
|
||||
|
||||
void nsRegion::SubRegionFromRegion (const nsRegion& aRgn1, const nsRegion& aRgn2)
|
||||
void nsRegion::SubRegion (const nsRegion& aRegion, nsRegion& aResult) const
|
||||
{
|
||||
if (aRgn2.mRectCount == 1) // Subtract simple rectangle
|
||||
SubRectFromRegion (aRgn1, *aRgn2.mRectListHead.next);
|
||||
else
|
||||
if (aRegion.mRectCount == 1) // Subtract simple rectangle
|
||||
{
|
||||
nsRegion TmpRegion;
|
||||
const nsRegion* pSrcRgn2 = &aRgn2;
|
||||
if (aRegion.mBoundRect.Contains (mBoundRect))
|
||||
aResult.Empty ();
|
||||
else
|
||||
SubRect (*aRegion.mRectListHead.next, aResult);
|
||||
} else
|
||||
{
|
||||
nsRegion TmpRegion, CompletedRegion;
|
||||
const nsRegion* pSubRgn = &aRegion;
|
||||
|
||||
if (&aRgn2 == this) // Copy region if it is both source and result
|
||||
if (&aResult == &aRegion) // Copy region if it is both source and result
|
||||
{
|
||||
TmpRegion.Copy (aRgn2);
|
||||
pSrcRgn2 = &TmpRegion;
|
||||
TmpRegion.Copy (aRegion);
|
||||
pSubRgn = &TmpRegion;
|
||||
}
|
||||
|
||||
const RgnRect* pRect = pSrcRgn2->mRectListHead.next;
|
||||
const RgnRect* pSubRect = pSubRgn->mRectListHead.next;
|
||||
|
||||
SubRectFromRegion (aRgn1, *pRect);
|
||||
pRect = pRect->next;
|
||||
SubRect (*pSubRect, aResult, CompletedRegion);
|
||||
pSubRect = pSubRect->next;
|
||||
|
||||
while (pRect != &pSrcRgn2->mRectListHead)
|
||||
while (pSubRect != &pSubRgn->mRectListHead)
|
||||
{
|
||||
SubRectFromRegion (*this, *pRect);
|
||||
pRect = pRect->next;
|
||||
aResult.SubRect (*pSubRect, aResult, CompletedRegion);
|
||||
pSubRect = pSubRect->next;
|
||||
}
|
||||
|
||||
CompletedRegion.MoveInto (aResult);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Subtract rectangle from region.
|
||||
// Subtract rectangle from current region.
|
||||
// Both region and rectangle are non-empty and they intersect each other.
|
||||
// Result could be empty if aRect fully overlays aRegion.
|
||||
// Optimize () is not called (bound rectangle is not updated).
|
||||
// Result could be empty region if aRect fully overlays aRegion.
|
||||
// Could be called repeatedly with 'this' as input and result - bound rectangle is not known.
|
||||
// Optimize () is not called on exit (bound rectangle is not updated).
|
||||
//
|
||||
// aCompleted is filled with rectangles which are already checked and could be safely
|
||||
// removed from further examination in case aRect rectangles come from ordered list.
|
||||
// aCompleted is not automatically emptied. aCompleted and aResult could be the same region.
|
||||
|
||||
void nsRegion::SubRectFromRegion (const nsRegion& aRegion, const nsRect& aRect)
|
||||
void nsRegion::SubRect (const nsRectFast& aRect, nsRegion& aResult, nsRegion& aCompleted) const
|
||||
{
|
||||
if (aRect.Contains (aRegion.mBoundRect))
|
||||
Empty ();
|
||||
else
|
||||
nsRegion TmpRegion;
|
||||
const nsRegion* pSrcRegion = this;
|
||||
|
||||
if (&aResult == this) // Copy region if it is both source and result
|
||||
{
|
||||
nsRegion TmpRegion;
|
||||
const nsRegion* pSrcRegion = &aRegion;
|
||||
TmpRegion.Copy (*this);
|
||||
pSrcRegion = &TmpRegion;
|
||||
}
|
||||
|
||||
aResult.SetToElements (0);
|
||||
|
||||
(NS_CONST_CAST (nsRegion*, pSrcRegion))->mRectListHead.y = MAX_INT32;
|
||||
const RgnRect* pSrcRect = pSrcRegion->mRectListHead.next;
|
||||
|
||||
if (&aRegion == this) // Copy region if it is both source and result
|
||||
for ( ; pSrcRect->y < aRect.YMost () ; pSrcRect = pSrcRect->next)
|
||||
{
|
||||
nsRectFast TmpRect;
|
||||
|
||||
// If bottom of current rectangle is above the top of aRect then this rectangle
|
||||
// could be moved to aCompleted region. Successive aRect rectangles from ordered
|
||||
// list do not have to check this rectangle again.
|
||||
if (pSrcRect->YMost () <= aRect.y)
|
||||
{
|
||||
TmpRegion.Copy (aRegion);
|
||||
pSrcRegion = &TmpRegion;
|
||||
aCompleted.InsertInPlace (new RgnRect (*pSrcRect));
|
||||
continue;
|
||||
}
|
||||
|
||||
SetToElements (0);
|
||||
const RgnRect* pSrcRect = pSrcRegion->mRectListHead.next;
|
||||
|
||||
while (pSrcRect != &pSrcRegion->mRectListHead)
|
||||
|
||||
if (!TmpRect.IntersectRect (*pSrcRect, aRect))
|
||||
aResult.InsertInPlace (new RgnRect (*pSrcRect));
|
||||
else
|
||||
{
|
||||
nsRect TmpRect;
|
||||
// Rectangle A. Subtract from this rectangle B
|
||||
const nscoord ax = pSrcRect->x;
|
||||
const nscoord axm = pSrcRect->XMost ();
|
||||
const nscoord aw = pSrcRect->width;
|
||||
const nscoord ay = pSrcRect->y;
|
||||
const nscoord aym = pSrcRect->YMost ();
|
||||
const nscoord ah = pSrcRect->height;
|
||||
// Rectangle B. Subtract this from rectangle A
|
||||
const nscoord bx = aRect.x;
|
||||
const nscoord bxm = aRect.XMost ();
|
||||
const nscoord bw = aRect.width;
|
||||
const nscoord by = aRect.y;
|
||||
const nscoord bym = aRect.YMost ();
|
||||
const nscoord bh = aRect.height;
|
||||
// Rectangle I. Area where rectangles A and B intersect
|
||||
const nscoord ix = TmpRect.x;
|
||||
const nscoord ixm = TmpRect.XMost ();
|
||||
const nscoord iw = TmpRect.width;
|
||||
const nscoord iy = TmpRect.y;
|
||||
const nscoord iym = TmpRect.YMost ();
|
||||
const nscoord ih = TmpRect.height;
|
||||
|
||||
if (!TmpRect.IntersectRect (*pSrcRect, aRect))
|
||||
InsertInPlace (new RgnRect (*pSrcRect));
|
||||
else
|
||||
// There are 16 combinations how rectangles could intersect
|
||||
|
||||
if (bx <= ax && by <= ay)
|
||||
{
|
||||
// Rectangle A. Subtract from this rectangle B
|
||||
const nscoord ax = pSrcRect->x;
|
||||
const nscoord axm = pSrcRect->XMost ();
|
||||
const nscoord aw = pSrcRect->width;
|
||||
const nscoord ay = pSrcRect->y;
|
||||
const nscoord aym = pSrcRect->YMost ();
|
||||
const nscoord ah = pSrcRect->height;
|
||||
// Rectangle B. Subtract this from rectangle A
|
||||
const nscoord bx = aRect.x;
|
||||
const nscoord bxm = aRect.XMost ();
|
||||
const nscoord bw = aRect.width;
|
||||
const nscoord by = aRect.y;
|
||||
const nscoord bym = aRect.YMost ();
|
||||
const nscoord bh = aRect.height;
|
||||
// Rectangle I. Area where rectangles A and B intersect
|
||||
const nscoord ix = TmpRect.x;
|
||||
const nscoord ixm = TmpRect.XMost ();
|
||||
const nscoord iw = TmpRect.width;
|
||||
const nscoord iy = TmpRect.y;
|
||||
const nscoord iym = TmpRect.YMost ();
|
||||
const nscoord ih = TmpRect.height;
|
||||
if (bxm < axm && bym < aym) // 1.
|
||||
{
|
||||
aResult.InsertInPlace (new RgnRect (ixm, ay, axm - ixm, ih));
|
||||
aResult.InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bxm >= axm && bym < aym) // 2.
|
||||
{
|
||||
aResult.InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bxm < axm && bym >= aym) // 3.
|
||||
{
|
||||
aResult.InsertInPlace (new RgnRect (ixm, ay, axm - ixm, ah));
|
||||
} else
|
||||
if (*pSrcRect == aRect) // 4. subset
|
||||
{ // Current rectangle is equal to aRect
|
||||
break; // No any other rectangle in region can intersect it
|
||||
}
|
||||
} else
|
||||
if (bx > ax && by <= ay)
|
||||
{
|
||||
if (bxm < axm && bym < aym) // 5.
|
||||
{
|
||||
aResult.InsertInPlace (new RgnRect (ax, ay, ix - ax, ih));
|
||||
aResult.InsertInPlace (new RgnRect (ixm, ay, axm - ixm, ih));
|
||||
aResult.InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bxm >= axm && bym < aym) // 6.
|
||||
{
|
||||
aResult.InsertInPlace (new RgnRect (ax, ay, ix - ax, ih));
|
||||
aResult.InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bxm < axm && bym >= aym) // 7.
|
||||
{
|
||||
aResult.InsertInPlace (new RgnRect (ax, ay, ix - ax, ah));
|
||||
aResult.InsertInPlace (new RgnRect (ixm, ay, axm - ixm, ah));
|
||||
} else
|
||||
if (bxm >= axm && bym >= aym) // 8.
|
||||
{
|
||||
aResult.InsertInPlace (new RgnRect (ax, ay, ix - ax, ah));
|
||||
}
|
||||
} else
|
||||
if (bx <= ax && by > ay)
|
||||
{
|
||||
if (bxm < axm && bym < aym) // 9.
|
||||
{
|
||||
aResult.InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
aResult.InsertInPlace (new RgnRect (ixm, iy, axm - ixm, ih));
|
||||
aResult.InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bxm >= axm && bym < aym) // 10.
|
||||
{
|
||||
aResult.InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
aResult.InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bxm < axm && bym >= aym) // 11.
|
||||
{
|
||||
aResult.InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
aResult.InsertInPlace (new RgnRect (ixm, iy, axm - ixm, ih));
|
||||
} else
|
||||
if (bxm >= axm && bym >= aym) // 12.
|
||||
{
|
||||
aResult.InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
}
|
||||
} else
|
||||
if (bx > ax && by > ay)
|
||||
{
|
||||
if (bxm < axm && bym < aym) // 13.
|
||||
{
|
||||
aResult.InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
aResult.InsertInPlace (new RgnRect (ax, iy, ix - ax, ih));
|
||||
aResult.InsertInPlace (new RgnRect (ixm, iy, axm - ixm, ih));
|
||||
aResult.InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
|
||||
// There are 16 combinations how rectangles could intersect
|
||||
|
||||
if (bx <= ax && by <= ay)
|
||||
{
|
||||
if (bxm < axm && bym < aym) // 1.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ixm, ay, axm - ixm, ih));
|
||||
InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bxm >= axm && bym < aym) // 2.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bxm < axm && bym >= aym) // 3.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ixm, ay, axm - ixm, ah));
|
||||
}
|
||||
// Current rectangle fully overlays aRect. No any other rectangle can intersect it.
|
||||
break;
|
||||
} else
|
||||
if (bx > ax && by <= ay)
|
||||
if (bxm >= axm && bym < aym) // 14.
|
||||
{
|
||||
if (bxm < axm && bym < aym) // 5.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ax, ay, ix - ax, ih));
|
||||
InsertInPlace (new RgnRect (ixm, ay, axm - ixm, ih));
|
||||
InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bxm >= axm && bym < aym) // 6.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ax, ay, ix - ax, ih));
|
||||
InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bxm < axm && bym >= aym) // 7.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ax, ay, ix - ax, ah));
|
||||
InsertInPlace (new RgnRect (ixm, ay, axm - ixm, ah));
|
||||
} else
|
||||
if (bxm >= axm && bym >= aym) // 8.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ax, ay, ix - ax, ah));
|
||||
}
|
||||
aResult.InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
aResult.InsertInPlace (new RgnRect (ax, iy, ix - ax, ih));
|
||||
aResult.InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bx <= ax && by > ay)
|
||||
if (bxm < axm && bym >= aym) // 15.
|
||||
{
|
||||
if (bxm < axm && bym < aym) // 9.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
InsertInPlace (new RgnRect (ixm, iy, axm - ixm, ih));
|
||||
InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bxm >= axm && bym < aym) // 10.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bxm < axm && bym >= aym) // 11.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
InsertInPlace (new RgnRect (ixm, iy, axm - ixm, ih));
|
||||
} else
|
||||
if (bxm >= axm && bym >= aym) // 12.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
}
|
||||
aResult.InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
aResult.InsertInPlace (new RgnRect (ax, iy, ix - ax, ih));
|
||||
aResult.InsertInPlace (new RgnRect (ixm, iy, axm - ixm, ih));
|
||||
} else
|
||||
if (bx > ax && by > ay)
|
||||
if (bxm >= axm && bym >= aym) // 16.
|
||||
{
|
||||
if (bxm < axm && bym < aym) // 13.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
InsertInPlace (new RgnRect (ax, iy, ix - ax, ih));
|
||||
InsertInPlace (new RgnRect (ixm, iy, axm - ixm, ih));
|
||||
InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bxm >= axm && bym < aym) // 14.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
InsertInPlace (new RgnRect (ax, iy, ix - ax, ih));
|
||||
InsertInPlace (new RgnRect (ax, iym, aw, aym - iym));
|
||||
} else
|
||||
if (bxm < axm && bym >= aym) // 15.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
InsertInPlace (new RgnRect (ax, iy, ix - ax, ih));
|
||||
InsertInPlace (new RgnRect (ixm, iy, axm - ixm, ih));
|
||||
} else
|
||||
if (bxm >= axm && bym >= aym) // 16.
|
||||
{
|
||||
InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
InsertInPlace (new RgnRect (ax, iy, ix - ax, ih));
|
||||
}
|
||||
aResult.InsertInPlace (new RgnRect (ax, ay, aw, iy - ay));
|
||||
aResult.InsertInPlace (new RgnRect (ax, iy, ix - ax, ih));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Just copy remaining rectangles in region which are below aRect and can't intersect it.
|
||||
// If rectangles are in temporary region then they could be moved.
|
||||
if (pSrcRegion == &TmpRegion)
|
||||
TmpRegion.MoveInto (aResult, pSrcRect);
|
||||
else
|
||||
{
|
||||
while (pSrcRect != &pSrcRegion->mRectListHead)
|
||||
{
|
||||
aResult.InsertInPlace (new RgnRect (*pSrcRect));
|
||||
pSrcRect = pSrcRect->next;
|
||||
}
|
||||
}
|
||||
|
@ -30,79 +30,76 @@
|
||||
#include "nsRect.h"
|
||||
|
||||
|
||||
// Special version of nsRect structure for speed optimizations in nsRegion code.
|
||||
// Most important functions could be made inline and be sure that passed rectangles
|
||||
// will always be non-empty.
|
||||
|
||||
struct nsRectFast : public nsRect
|
||||
{
|
||||
nsRectFast () {} // No need to call parent constructor to set default values
|
||||
nsRectFast (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) : nsRect (aX, aY, aWidth, aHeight) {}
|
||||
nsRectFast (const nsRect& aRect) : nsRect (aRect) {}
|
||||
operator nsRect () { return *NS_STATIC_CAST (nsRect*, this); }
|
||||
|
||||
|
||||
#if 1 // Override nsRect methods to make them inline. Do not check for emptiness.
|
||||
PRBool Contains (const nsRectFast &aRect) const
|
||||
{
|
||||
return (PRBool) ((aRect.x >= x) && (aRect.y >= y) &&
|
||||
(aRect.XMost() <= XMost()) && (aRect.YMost() <= YMost()));
|
||||
}
|
||||
|
||||
PRBool Intersects (const nsRectFast &aRect) const
|
||||
{
|
||||
return (PRBool) ((x < aRect.XMost()) && (y < aRect.YMost()) &&
|
||||
(aRect.x < XMost()) && (aRect.y < YMost()));
|
||||
}
|
||||
|
||||
PRBool IntersectRect (const nsRectFast &aRect1, const nsRectFast &aRect2)
|
||||
{
|
||||
const nscoord xmost = PR_MIN (aRect1.XMost(), aRect2.XMost());
|
||||
x = PR_MAX (aRect1.x, aRect2.x);
|
||||
width = xmost - x;
|
||||
if (width <= 0) return PR_FALSE;
|
||||
|
||||
const nscoord ymost = PR_MIN (aRect1.YMost(), aRect2.YMost());
|
||||
y = PR_MAX (aRect1.y, aRect2.y);
|
||||
height = ymost - y;
|
||||
if (height <= 0) return PR_FALSE;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void UnionRect (const nsRectFast &aRect1, const nsRectFast &aRect2)
|
||||
{
|
||||
const nscoord xmost = PR_MAX (aRect1.XMost(), aRect2.XMost());
|
||||
const nscoord ymost = PR_MAX (aRect1.YMost(), aRect2.YMost());
|
||||
x = PR_MIN (aRect1.x, aRect2.x);
|
||||
y = PR_MIN (aRect1.y, aRect2.y);
|
||||
width = xmost - x;
|
||||
height = ymost - y;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
class nsRegion
|
||||
{
|
||||
friend class nsRegionRectIterator;
|
||||
friend class RgnRectMemoryAllocator;
|
||||
|
||||
struct RgnRect : public nsRect
|
||||
struct RgnRect : public nsRectFast
|
||||
{
|
||||
RgnRect* prev;
|
||||
RgnRect* next;
|
||||
|
||||
RgnRect () {} // No need to call parent constructor to set default values
|
||||
RgnRect (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) : nsRect (aX, aY, aWidth, aHeight) {}
|
||||
RgnRect (const nsRect& aRect) : nsRect (aRect) {}
|
||||
RgnRect (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) : nsRectFast (aX, aY, aWidth, aHeight) {}
|
||||
RgnRect (const nsRectFast& aRect) : nsRectFast (aRect) {}
|
||||
|
||||
#if 1 // Override nsRect methods to make them inline. These are very important to nsRegion
|
||||
#ifdef MIN
|
||||
#undef MIN
|
||||
#endif
|
||||
|
||||
#ifdef MAX
|
||||
#undef MAX
|
||||
#endif
|
||||
|
||||
#define MIN(a,b)\
|
||||
((a) < (b) ? (a) : (b))
|
||||
#define MAX(a,b)\
|
||||
((a) > (b) ? (a) : (b))
|
||||
|
||||
PRBool Contains (const nsRect &aRect) const
|
||||
{
|
||||
return (PRBool) ((aRect.x >= x) && (aRect.y >= y) &&
|
||||
(aRect.XMost() <= XMost()) && (aRect.YMost() <= YMost()));
|
||||
}
|
||||
|
||||
PRBool Intersects (const nsRect &aRect) const
|
||||
{
|
||||
return (PRBool) ((x < aRect.XMost()) && (y < aRect.YMost()) &&
|
||||
(aRect.x < XMost()) && (aRect.y < YMost()));
|
||||
}
|
||||
|
||||
PRBool IntersectRect (const nsRect &aRect1, const nsRect &aRect2)
|
||||
{
|
||||
x = MAX (aRect1.x, aRect2.x);
|
||||
|
||||
// Compute the destination width
|
||||
const nscoord tmpX = MIN (aRect1.XMost(), aRect2.XMost());
|
||||
if (tmpX <= x)
|
||||
return PR_FALSE;
|
||||
|
||||
y = MAX (aRect1.y, aRect2.y);
|
||||
|
||||
// Compute the destination height
|
||||
const nscoord tmpY = MIN (aRect1.YMost(), aRect2.YMost());
|
||||
if (tmpY <= y)
|
||||
return PR_FALSE;
|
||||
|
||||
width = tmpX - x;
|
||||
height = tmpY - y;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void UnionRect (const nsRect &aRect1, const nsRect &aRect2)
|
||||
{
|
||||
x = MIN (aRect1.x, aRect2.x);
|
||||
y = MIN (aRect1.y, aRect2.y);
|
||||
width = MAX (aRect1.XMost(), aRect2.XMost()) - x;
|
||||
height = MAX (aRect1.YMost(), aRect2.YMost()) - y;
|
||||
}
|
||||
#endif
|
||||
|
||||
void* operator new (size_t);
|
||||
void operator delete (void* aRect, size_t);
|
||||
inline void* operator new (size_t);
|
||||
inline void operator delete (void* aRect, size_t);
|
||||
operator = (const RgnRect& aRect) // Do not overwrite prev/next pointers
|
||||
{
|
||||
x = aRect.x;
|
||||
@ -115,59 +112,61 @@ class nsRegion
|
||||
|
||||
public:
|
||||
nsRegion ();
|
||||
~nsRegion () { SetToElements (0); }
|
||||
~nsRegion () { SetToElements (0); }
|
||||
|
||||
nsRegion& Copy (const nsRegion& aRegion);
|
||||
nsRegion& Copy (const nsRect& aRect);
|
||||
nsRegion& Copy (const nsRectFast& aRect);
|
||||
|
||||
nsRegion& And (const nsRegion& aRgn1, const nsRegion& aRgn2);
|
||||
nsRegion& And (const nsRegion& aRegion, const nsRect& aRect);
|
||||
nsRegion& And (const nsRect& aRect, const nsRegion& aRegion)
|
||||
nsRegion& And (const nsRegion& aRgn1, const nsRegion& aRgn2);
|
||||
nsRegion& And (const nsRegion& aRegion, const nsRectFast& aRect);
|
||||
nsRegion& And (const nsRectFast& aRect, const nsRegion& aRegion)
|
||||
{
|
||||
return And (aRegion, aRect);
|
||||
}
|
||||
nsRegion& And (const nsRect& aRect1, const nsRect& aRect2)
|
||||
nsRegion& And (const nsRectFast& aRect1, const nsRectFast& aRect2)
|
||||
{
|
||||
nsRect TmpRect;
|
||||
TmpRect.IntersectRect (aRect1, aRect2);
|
||||
nsRectFast TmpRect;
|
||||
|
||||
// Force generic nsRect::IntersectRect to handle empty rectangles!
|
||||
TmpRect.nsRect::IntersectRect (aRect1, aRect2);
|
||||
return Copy (TmpRect);
|
||||
}
|
||||
|
||||
nsRegion& Or (const nsRegion& aRgn1, const nsRegion& aRgn2);
|
||||
nsRegion& Or (const nsRegion& aRegion, const nsRect& aRect);
|
||||
nsRegion& Or (const nsRect& aRect, const nsRegion& aRegion)
|
||||
nsRegion& Or (const nsRegion& aRgn1, const nsRegion& aRgn2);
|
||||
nsRegion& Or (const nsRegion& aRegion, const nsRectFast& aRect);
|
||||
nsRegion& Or (const nsRectFast& aRect, const nsRegion& aRegion)
|
||||
{
|
||||
return Or (aRegion, aRect);
|
||||
}
|
||||
nsRegion& Or (const nsRect& aRect1, const nsRect& aRect2)
|
||||
nsRegion& Or (const nsRectFast& aRect1, const nsRectFast& aRect2)
|
||||
{
|
||||
nsRegion TmpRegion;
|
||||
TmpRegion.Copy (aRect1);
|
||||
return Or (TmpRegion, aRect2);
|
||||
}
|
||||
|
||||
nsRegion& Xor (const nsRegion& aRgn1, const nsRegion& aRgn2);
|
||||
nsRegion& Xor (const nsRegion& aRegion, const nsRect& aRect);
|
||||
nsRegion& Xor (const nsRect& aRect, const nsRegion& aRegion)
|
||||
nsRegion& Xor (const nsRegion& aRgn1, const nsRegion& aRgn2);
|
||||
nsRegion& Xor (const nsRegion& aRegion, const nsRectFast& aRect);
|
||||
nsRegion& Xor (const nsRectFast& aRect, const nsRegion& aRegion)
|
||||
{
|
||||
return Xor (aRegion, aRect);
|
||||
}
|
||||
nsRegion& Xor (const nsRect& aRect1, const nsRect& aRect2)
|
||||
nsRegion& Xor (const nsRectFast& aRect1, const nsRectFast& aRect2)
|
||||
{
|
||||
nsRegion TmpRegion;
|
||||
TmpRegion.Copy (aRect1);
|
||||
return Xor (TmpRegion, aRect2);
|
||||
}
|
||||
|
||||
nsRegion& Sub (const nsRegion& aRgn1, const nsRegion& aRgn2);
|
||||
nsRegion& Sub (const nsRegion& aRegion, const nsRect& aRect);
|
||||
nsRegion& Sub (const nsRect& aRect, const nsRegion& aRegion)
|
||||
nsRegion& Sub (const nsRegion& aRgn1, const nsRegion& aRgn2);
|
||||
nsRegion& Sub (const nsRegion& aRegion, const nsRectFast& aRect);
|
||||
nsRegion& Sub (const nsRectFast& aRect, const nsRegion& aRegion)
|
||||
{
|
||||
nsRegion TmpRegion;
|
||||
TmpRegion.Copy (aRect);
|
||||
return Sub (TmpRegion, aRegion);
|
||||
}
|
||||
nsRegion& Sub (const nsRect& aRect1, const nsRect& aRect2)
|
||||
nsRegion& Sub (const nsRectFast& aRect1, const nsRectFast& aRect2)
|
||||
{
|
||||
nsRegion TmpRegion;
|
||||
TmpRegion.Copy (aRect1);
|
||||
@ -175,9 +174,9 @@ public:
|
||||
}
|
||||
|
||||
|
||||
PRBool GetBoundRect (nsRect* aBound) const
|
||||
PRBool GetBoundRect (nsRect& aBound) const
|
||||
{
|
||||
*aBound = mBoundRect;
|
||||
aBound = mBoundRect;
|
||||
return !mBoundRect.IsEmpty ();
|
||||
}
|
||||
|
||||
@ -197,7 +196,7 @@ private:
|
||||
PRUint32 mRectCount;
|
||||
RgnRect* mCurRect;
|
||||
RgnRect mRectListHead;
|
||||
nsRect mBoundRect;
|
||||
nsRectFast mBoundRect;
|
||||
|
||||
void InsertBefore (RgnRect* aNewRect, RgnRect* aRelativeRect)
|
||||
{
|
||||
@ -222,11 +221,18 @@ private:
|
||||
void SetToElements (PRUint32 aCount);
|
||||
RgnRect* Remove (RgnRect* aRect);
|
||||
void InsertInPlace (RgnRect* aRect, PRBool aOptimizeOnFly = PR_FALSE);
|
||||
void SaveLinkChain ();
|
||||
void RestoreLinkChain ();
|
||||
void Optimize ();
|
||||
void SubRectFromRegion (const nsRegion& aRegion, const nsRect& aRect);
|
||||
void SubRegionFromRegion (const nsRegion& aRgn1, const nsRegion& aRgn2);
|
||||
void SubRegion (const nsRegion& aRegion, nsRegion& aResult) const;
|
||||
void SubRect (const nsRectFast& aRect, nsRegion& aResult, nsRegion& aCompleted) const;
|
||||
void SubRect (const nsRectFast& aRect, nsRegion& aResult) const
|
||||
{ SubRect (aRect, aResult, aResult); }
|
||||
void Merge (const nsRegion& aRgn1, const nsRegion& aRgn2);
|
||||
|
||||
void MoveInto (nsRegion& aDestRegion, const RgnRect* aStartRect);
|
||||
void MoveInto (nsRegion& aDestRegion)
|
||||
{ MoveInto (aDestRegion, mRectListHead.next); }
|
||||
|
||||
nsRegion (const nsRegion& aRegion); // Prevent copying of regions
|
||||
operator = (const nsRegion& aRegion);
|
||||
};
|
||||
@ -247,13 +253,13 @@ public:
|
||||
mCurPtr = &aRegion.mRectListHead;
|
||||
}
|
||||
|
||||
const nsRect* Next ()
|
||||
const nsRectFast* Next ()
|
||||
{
|
||||
mCurPtr = mCurPtr->next;
|
||||
return (mCurPtr != &mRegion->mRectListHead) ? mCurPtr : nsnull;
|
||||
}
|
||||
|
||||
const nsRect* Prev ()
|
||||
const nsRectFast* Prev ()
|
||||
{
|
||||
mCurPtr = mCurPtr->prev;
|
||||
return (mCurPtr != &mRegion->mRectListHead) ? mCurPtr : nsnull;
|
||||
@ -266,5 +272,4 @@ public:
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -86,7 +86,7 @@ PRBool nsRegionImpl::IsEqual (const nsIRegion &aRegion)
|
||||
void nsRegionImpl::GetBoundingBox (PRInt32 *aX, PRInt32 *aY, PRInt32 *aWidth, PRInt32 *aHeight)
|
||||
{
|
||||
nsRect BoundRect;
|
||||
mRegion.GetBoundRect (&BoundRect);
|
||||
mRegion.GetBoundRect (BoundRect);
|
||||
*aX = BoundRect.x;
|
||||
*aY = BoundRect.y;
|
||||
*aWidth = BoundRect.width;
|
||||
|
Loading…
Reference in New Issue
Block a user