Bug 317514. Add nsRegion::SimpleSubtract, Contains(aRect) and Intersects(aRect). r=dainis_jonitis, sr=bzbarsky

This commit is contained in:
roc+%cs.cmu.edu 2005-11-24 01:05:18 +00:00
parent ca5d4d3999
commit cb35d5fe9e
2 changed files with 93 additions and 13 deletions

View File

@ -154,6 +154,8 @@ public:
return Sub (*this, aRect2);
}
PRBool Contains (const nsRect& aRect) const;
PRBool Intersects (const nsRect& aRect) const;
void MoveBy (PRInt32 aXOffset, PRInt32 aYOffset)
{
@ -185,6 +187,23 @@ public:
* original region.
*/
void SimplifyInward (PRUint32 aMaxRects);
/**
* Efficiently try to remove a rectangle from this region. The actual
* area removed could be some sub-area contained by the rectangle
* (even possibly nothing at all).
*
* We remove all rectangles that are contained by aRect.
*/
void SimpleSubtract (const nsRect& aRect);
/**
* Efficiently try to remove a region from this region. The actual
* area removed could be some sub-area contained by aRegion
* (even possibly nothing at all).
*
* We remove all rectangles of this region that are contained by
* a rectangle of aRegion.
*/
void SimpleSubtract (const nsRegion& aRegion);
private:
PRUint32 mRectCount;

View File

@ -38,11 +38,6 @@
#include "nsRegion.h"
#include "nsISupportsImpl.h"
#define MIN_INT32 (-PR_INT32 (0x7FFFFFFF) - 1)
#define MAX_INT32 (PR_INT32 (0x7FFFFFFF))
// Fast inline analogues of nsRect methods for nsRegion::nsRectFast.
// Check for emptiness is not required - it is guaranteed by caller.
@ -344,7 +339,7 @@ void nsRegion::InsertInPlace (RgnRect* aRect, PRBool aOptimizeOnFly)
{
if (aRect->y > mCurRect->y)
{
mRectListHead.y = MAX_INT32;
mRectListHead.y = PR_INT32_MAX;
while (aRect->y > mCurRect->next->y)
mCurRect = mCurRect->next;
@ -356,7 +351,7 @@ void nsRegion::InsertInPlace (RgnRect* aRect, PRBool aOptimizeOnFly)
} else
if (aRect->y < mCurRect->y)
{
mRectListHead.y = MIN_INT32;
mRectListHead.y = PR_INT32_MIN;
while (aRect->y < mCurRect->prev->y)
mCurRect = mCurRect->prev;
@ -369,7 +364,7 @@ void nsRegion::InsertInPlace (RgnRect* aRect, PRBool aOptimizeOnFly)
{
if (aRect->x > mCurRect->x)
{
mRectListHead.y = MAX_INT32;
mRectListHead.y = PR_INT32_MAX;
while (aRect->y == mCurRect->next->y && aRect->x > mCurRect->next->x)
mCurRect = mCurRect->next;
@ -377,7 +372,7 @@ void nsRegion::InsertInPlace (RgnRect* aRect, PRBool aOptimizeOnFly)
InsertAfter (aRect, mCurRect);
} else
{
mRectListHead.y = MIN_INT32;
mRectListHead.y = PR_INT32_MIN;
while (aRect->y == mCurRect->prev->y && aRect->x < mCurRect->prev->x)
mCurRect = mCurRect->prev;
@ -666,8 +661,8 @@ nsRegion& nsRegion::And (const nsRegion& aRgn1, const nsRegion& aRgn2)
SetToElements (0);
pSrcRgn2->SaveLinkChain ();
pSrcRgn1->mRectListHead.y = MAX_INT32;
pSrcRgn2->mRectListHead.y = MAX_INT32;
pSrcRgn1->mRectListHead.y = PR_INT32_MAX;
pSrcRgn2->mRectListHead.y = PR_INT32_MAX;
for (RgnRect* pSrcRect1 = pSrcRgn1->mRectListHead.next ;
pSrcRect1->y < pSrcRgn2->mBoundRect.YMost () ; pSrcRect1 = pSrcRect1->next)
@ -746,7 +741,7 @@ nsRegion& nsRegion::And (const nsRegion& aRegion, const nsRect& aRect)
}
SetToElements (0);
pSrcRegion->mRectListHead.y = MAX_INT32;
pSrcRegion->mRectListHead.y = PR_INT32_MAX;
for (const RgnRect* pSrcRect = pSrcRegion->mRectListHead.next ;
pSrcRect->y < aRectFast.YMost () ; pSrcRect = pSrcRect->next)
@ -979,6 +974,34 @@ nsRegion& nsRegion::Sub (const nsRegion& aRegion, const nsRect& aRect)
return *this;
}
PRBool nsRegion::Contains (const nsRect& aRect) const
{
if (aRect.IsEmpty())
return PR_TRUE;
if (IsEmpty())
return PR_FALSE;
if (!IsComplex())
return mBoundRect.Contains (aRect);
nsRegion tmpRgn;
tmpRgn.Sub(aRect, *this);
return tmpRgn.IsEmpty();
}
PRBool nsRegion::Intersects (const nsRect& aRect) const
{
if (aRect.IsEmpty() || IsEmpty())
return PR_FALSE;
const RgnRect* r = mRectListHead.next;
while (r != &mRectListHead)
{
if (r->Intersects(aRect))
return PR_TRUE;
r = r->next;
}
return PR_FALSE;
}
// Subtract region from current region.
// Both regions are non-empty and they intersect each other.
@ -1043,7 +1066,7 @@ void nsRegion::SubRect (const nsRectFast& aRect, nsRegion& aResult, nsRegion& aC
aResult.SetToElements (0);
(NS_CONST_CAST (nsRegion*, pSrcRegion))->mRectListHead.y = MAX_INT32;
(NS_CONST_CAST (nsRegion*, pSrcRegion))->mRectListHead.y = PR_INT32_MAX;
const RgnRect* pSrcRect = pSrcRegion->mRectListHead.next;
for ( ; pSrcRect->y < aRect.YMost () ; pSrcRect = pSrcRect->next)
@ -1260,3 +1283,41 @@ void nsRegion::SimplifyInward (PRUint32 aMaxRects)
SetEmpty();
}
void nsRegion::SimpleSubtract (const nsRect& aRect)
{
if (aRect.IsEmpty())
return;
RgnRect* r = mRectListHead.next;
while (r != &mRectListHead)
{
RgnRect* next = r->next;
if (aRect.Contains(*r)) {
delete Remove(r);
}
r = next;
}
Optimize();
}
void nsRegion::SimpleSubtract (const nsRegion& aRegion)
{
if (aRegion.IsEmpty())
return;
if (&aRegion == this) {
SetEmpty();
return;
}
const RgnRect* r = aRegion.mRectListHead.next;
while (r != &aRegion.mRectListHead)
{
SimpleSubtract(*r);
r = r->next;
}
Optimize();
}