diff --git a/mozilla/gfx/public/nsRegion.h b/mozilla/gfx/public/nsRegion.h index 4cb43f1fc17..34ca0375da3 100644 --- a/mozilla/gfx/public/nsRegion.h +++ b/mozilla/gfx/public/nsRegion.h @@ -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; diff --git a/mozilla/gfx/src/nsRegion.cpp b/mozilla/gfx/src/nsRegion.cpp index 5a271a0b309..41088d6268d 100644 --- a/mozilla/gfx/src/nsRegion.cpp +++ b/mozilla/gfx/src/nsRegion.cpp @@ -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(); +}