Bug 641426. Part 5: Avoid operator== where possible to distinguish between 'equal edges' and 'equal areas' for rectangles. r=dbaron,sr=cjones
authorRobert O'Callahan <robert@ocallahan.org>
Tue, 19 Apr 2011 15:07:23 +1200
changeset 68280 90e46b3e8e6f973a78280d340b64f8ed4d831624
parent 68279 964231489ddee5f540f1a5ecc0de526d764df7e0
child 68281 91e75937d34ab641eb593651be6f110f3539c181
push idunknown
push userunknown
push dateunknown
reviewersdbaron, cjones
bugs641426
milestone6.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 641426. Part 5: Avoid operator== where possible to distinguish between 'equal edges' and 'equal areas' for rectangles. r=dbaron,sr=cjones
docshell/base/nsDocShell.cpp
dom/base/nsDOMWindowUtils.cpp
gfx/layers/Layers.h
gfx/layers/ThebesLayerBuffer.cpp
gfx/layers/basic/BasicLayers.cpp
gfx/layers/d3d10/ThebesLayerD3D10.cpp
gfx/layers/d3d9/ThebesLayerD3D9.cpp
gfx/layers/opengl/ThebesLayerOGL.cpp
gfx/src/nsRect.cpp
gfx/src/nsRect.h
gfx/src/nsRegion.cpp
gfx/tests/TestRegion.cpp
gfx/thebes/GLContext.h
gfx/thebes/gfxBlur.cpp
gfx/thebes/gfxImageSurface.cpp
gfx/thebes/gfxRect.h
gfx/thebes/gfxUtils.cpp
gfx/thebes/gfxXlibNativeRenderer.cpp
layout/base/FrameLayerBuilder.cpp
layout/base/FrameLayerBuilder.h
layout/base/crashtests/crashtests.list
layout/base/nsDisplayList.cpp
layout/base/nsImageLoader.cpp
layout/base/nsPresContext.h
layout/base/nsPresShell.cpp
layout/generic/crashtests/crashtests.list
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockReflowState.cpp
layout/generic/nsContainerFrame.cpp
layout/generic/nsFloatManager.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrameUtil.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsHTMLReflowMetrics.h
layout/generic/nsImageFrame.cpp
layout/generic/nsLineBox.cpp
layout/generic/nsObjectFrame.cpp
layout/generic/nsSelection.cpp
layout/style/nsStyleStruct.cpp
layout/svg/base/src/nsSVGOuterSVGFrame.cpp
layout/xul/base/src/nsSliderFrame.cpp
layout/xul/base/src/nsSprocketLayout.cpp
layout/xul/base/src/nsStackLayout.cpp
layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
modules/libpr0n/src/RasterImage.cpp
modules/libpr0n/src/imgFrame.cpp
view/src/nsViewManager.cpp
widget/src/os2/nsWindow.cpp
widget/src/windows/nsWindow.cpp
widget/src/xpwidgets/PuppetWidget.cpp
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -7284,17 +7284,17 @@ nsDocShell::RestoreFromHistory()
     // presentation to that smaller size.  However, firing the locationchanged
     // event will hide the infobar, which will immediately resize the window
     // back to the larger size.  A future optimization might be to restore
     // the presentation at the "wrong" size, then fire the locationchanged
     // event and check whether the docshell's new size is the same as the
     // cached viewer size (skipping the resize if they are equal).
 
     if (newRootView) {
-        if (!newBounds.IsEmpty() && newBounds != oldBounds) {
+        if (!newBounds.IsEmpty() && !newBounds.IsEqualEdges(oldBounds)) {
 #ifdef DEBUG_PAGE_CACHE
             printf("resize widget(%d, %d, %d, %d)\n", newBounds.x,
                    newBounds.y, newBounds.width, newBounds.height);
 #endif
             mContentViewer->SetBounds(newBounds);
         } else {
             nsIScrollableFrame *rootScrollFrame =
               shell->GetRootScrollFrameAsScrollableExternal();
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -295,17 +295,17 @@ nsDOMWindowUtils::SetDisplayPortForEleme
   nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
 
   if (!content) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsRect lastDisplayPort;
   if (nsLayoutUtils::GetDisplayPort(content, &lastDisplayPort) &&
-      displayport == lastDisplayPort) {
+      displayport.IsEqualInterior(lastDisplayPort)) {
     return NS_OK;
   }
 
   content->SetProperty(nsGkAtoms::DisplayPort, new nsRect(displayport),
                        DestroyNsRect);
 
   nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
   if (rootScrollFrame) {
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -103,19 +103,19 @@ public:
     , mViewportScrollOffset(0, 0)
     , mScrollId(NULL_SCROLL_ID)
   {}
 
   // Default copy ctor and operator= are fine
 
   PRBool operator==(const FrameMetrics& aOther) const
   {
-    return (mViewport == aOther.mViewport &&
+    return (mViewport.IsEqualEdges(aOther.mViewport) &&
             mViewportScrollOffset == aOther.mViewportScrollOffset &&
-            mDisplayPort == aOther.mDisplayPort &&
+            mDisplayPort.IsEqualEdges(aOther.mDisplayPort) &&
             mScrollId == aOther.mScrollId);
   }
 
   PRBool IsDefault() const
   {
     return (FrameMetrics() == *this);
   }
 
--- a/gfx/layers/ThebesLayerBuffer.cpp
+++ b/gfx/layers/ThebesLayerBuffer.cpp
@@ -260,17 +260,17 @@ ThebesLayerBuffer::BeginPaint(ThebesLaye
       } else {
         destBufferRect = neededRegion.GetBounds();
       }
     } else {
       destBufferRect = neededRegion.GetBounds();
     }
 
     if ((aFlags & PAINT_WILL_RESAMPLE) &&
-        (neededRegion.GetBounds() != destBufferRect ||
+        (!neededRegion.GetBounds().IsEqualInterior(destBufferRect) ||
          neededRegion.GetNumRects() > 1)) {
       // The area we add to neededRegion might not be painted opaquely
       contentType = gfxASurface::CONTENT_COLOR_ALPHA;
 
       // We need to validate the entire buffer, to make sure that only valid
       // pixels are sampled
       neededRegion = destBufferRect;
       destBufferDims = ScaledSize(neededRegion.GetBounds().Size(),
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -462,17 +462,17 @@ ClipToContain(gfxContext* aContext, cons
 
   gfxMatrix currentMatrix = aContext->CurrentMatrix();
   aContext->IdentityMatrix();
   aContext->NewPath();
   aContext->Rectangle(deviceRect);
   aContext->Clip();
   aContext->SetMatrix(currentMatrix);
 
-  return aContext->DeviceToUser(deviceRect) == userRect;
+  return aContext->DeviceToUser(deviceRect).IsEqualInterior(userRect);
 }
 
 static nsIntRegion
 IntersectWithClip(const nsIntRegion& aRegion, gfxContext* aContext)
 {
   gfxRect clip = aContext->GetClipExtents();
   clip.RoundOut();
   nsIntRect r(clip.X(), clip.Y(), clip.Width(), clip.Height());
--- a/gfx/layers/d3d10/ThebesLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ThebesLayerD3D10.cpp
@@ -189,17 +189,17 @@ ThebesLayerD3D10::Validate(ReadbackProce
     mode = SURFACE_SINGLE_CHANNEL_ALPHA;
   }
   // If we have a transform that requires resampling of our texture, then
   // we need to make sure we don't sample pixels that haven't been drawn.
   // We clamp sample coordinates to the texture rect, but when the visible region
   // doesn't fill the entire texture rect we need to make sure we draw all the
   // pixels in the texture rect anyway in case they get sampled.
   nsIntRegion neededRegion = mVisibleRegion;
-  if (neededRegion.GetBounds() != newTextureRect ||
+  if (!neededRegion.GetBounds().IsEqualInterior(newTextureRect) ||
       neededRegion.GetNumRects() > 1) {
     gfxMatrix transform2d;
     if (!GetEffectiveTransform().Is2D(&transform2d) ||
         transform2d.HasNonIntegerTranslation()) {
       neededRegion = newTextureRect;
       if (mode == SURFACE_OPAQUE) {
         // We're going to paint outside the visible region, but layout hasn't
         // promised that it will paint opaquely there, so we'll have to
@@ -223,17 +223,17 @@ ThebesLayerD3D10::Validate(ReadbackProce
 
   nsTArray<ReadbackProcessor::Update> readbackUpdates;
   nsIntRegion readbackRegion;
   if (aReadback && UsedForReadback()) {
     aReadback->GetThebesLayerUpdates(this, &readbackUpdates, &readbackRegion);
   }
 
   if (mTexture) {
-    if (mTextureRect != newTextureRect) {
+    if (!mTextureRect.IsEqualInterior(newTextureRect)) {
       nsRefPtr<ID3D10Texture2D> oldTexture = mTexture;
       mTexture = nsnull;
       nsRefPtr<ID3D10Texture2D> oldTextureOnWhite = mTextureOnWhite;
       mTextureOnWhite = nsnull;
 
       nsIntRegion retainRegion = mTextureRect;
       // Old visible region will become the region that is covered by both the
       // old and the new visible region.
--- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp
@@ -133,17 +133,17 @@ ThebesLayerD3D9::UpdateTextures(SurfaceM
 
   // If our resolution changed, we need new sized textures, delete the old ones.
   if (ResolutionChanged(xres, yres)) {
       mTexture = nsnull;
       mTextureOnWhite = nsnull;
   }
 
   if (HaveTextures(aMode)) {
-    if (mTextureRect != visibleRect) {
+    if (!mTextureRect.IsEqualInterior(visibleRect)) {
       nsRefPtr<IDirect3DTexture9> oldTexture = mTexture;
       nsRefPtr<IDirect3DTexture9> oldTextureOnWhite = mTextureOnWhite;
 
       NS_ASSERTION(mTextureRect.Contains(mValidRegion.GetBounds()),
                    "How can we have valid data outside the texture?");
       nsIntRegion retainRegion;
       // The region we want to retain is the valid data that is inside
       // the new visible region
@@ -216,17 +216,17 @@ ThebesLayerD3D9::RenderThebesLayer(Readb
     mode = SURFACE_SINGLE_CHANNEL_ALPHA;
   }
   // If we have a transform that requires resampling of our texture, then
   // we need to make sure we don't sample pixels that haven't been drawn.
   // We clamp sample coordinates to the texture rect, but when the visible region
   // doesn't fill the entire texture rect we need to make sure we draw all the
   // pixels in the texture rect anyway in case they get sampled.
   nsIntRegion neededRegion = mVisibleRegion;
-  if (neededRegion.GetBounds() != newTextureRect ||
+  if (!neededRegion.GetBounds().IsEqualInterior(newTextureRect) ||
       neededRegion.GetNumRects() > 1) {
     gfxMatrix transform2d;
     if (!GetEffectiveTransform().Is2D(&transform2d) ||
         transform2d.HasNonIntegerTranslation()) {
       neededRegion = newTextureRect;
       if (mode == SURFACE_OPAQUE) {
         // We're going to paint outside the visible region, but layout hasn't
         // promised that it will paint opaquely there, so we'll have to
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -480,17 +480,17 @@ BasicBufferOGL::BeginPaint(ContentType a
         mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA;
       } else {
         contentType = gfxASurface::CONTENT_COLOR;
       }
  #endif
     }
  
     if ((aFlags & PAINT_WILL_RESAMPLE) &&
-        (neededRegion.GetBounds() != destBufferRect ||
+        (!neededRegion.GetBounds().IsEqualInterior(destBufferRect) ||
          neededRegion.GetNumRects() > 1)) {
       // The area we add to neededRegion might not be painted opaquely
       if (mode == Layer::SURFACE_OPAQUE) {
         contentType = gfxASurface::CONTENT_COLOR_ALPHA;
         mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA;
       }
       // For component alpha layers, we leave contentType as CONTENT_COLOR.
 
--- a/gfx/src/nsRect.cpp
+++ b/gfx/src/nsRect.cpp
@@ -119,23 +119,23 @@ PRBool nsRect::UnionRect(const nsRect &a
     } else {
       // aRect1 is empty so set the result to aRect2
       *this = aRect2;
     }
   } else if (aRect2.IsEmpty()) {
     // aRect2 is empty so set the result to aRect1
     *this = aRect1;
   } else {
-    UnionRectIncludeEmpty(aRect1, aRect2);
+    UnionRectEdges(aRect1, aRect2);
   }
 
   return result;
 }
 
-void nsRect::UnionRectIncludeEmpty(const nsRect &aRect1, const nsRect &aRect2)
+void nsRect::UnionRectEdges(const nsRect &aRect1, const nsRect &aRect2)
 {
   nscoord xmost1 = aRect1.XMost();
   nscoord xmost2 = aRect2.XMost();
   nscoord ymost1 = aRect1.YMost();
   nscoord ymost2 = aRect2.YMost();
 
   // Compute the origin
   x = PR_MIN(aRect1.x, aRect2.x);
--- a/gfx/src/nsRect.h
+++ b/gfx/src/nsRect.h
@@ -80,47 +80,52 @@ struct NS_GFX nsRect {
   
   // Emptiness. An empty rect is one that has no area, i.e. its height or width
   // is <= 0
   PRBool IsEmpty() const {
     return (PRBool) ((height <= 0) || (width <= 0));
   }
   void   Empty() {width = height = 0;}
 
-  // Containment
+  // Returns true if this rectangle contains the interior of aRect. Always
+  // returns true if aRect is empty, and always returns false is aRect is
+  // nonempty but this rect is empty.
   PRBool Contains(const nsRect& aRect) const;
+  // Returns true if this rectangle contains the given point; if the point
+  // is on the edge of the rectangle, this returns true.
   PRBool Contains(nscoord aX, nscoord aY) const;
   PRBool Contains(const nsPoint& aPoint) const {return Contains(aPoint.x, aPoint.y);}
 
-  // Intersection. Returns TRUE if the receiver overlaps aRect and
-  // FALSE otherwise
+  // Intersection. Returns TRUE if the receiver's area has non-empty
+  // intersection with aRect's area, and FALSE otherwise.
+  // Always returns false if aRect is empty or 'this' is empty.
   PRBool Intersects(const nsRect& aRect) const;
 
-  // Computes the area in which aRect1 and aRect2 overlap, and fills 'this' with
-  // the result. Returns FALSE if the rectangles don't intersect, and sets 'this'
-  // rect to be an empty rect.
+  // Sets 'this' to be a rectangle containing the intersection of the points
+  // (including edges) of aRect1 and aRect2, or 0,0,0,0 if that intersection is
+  // empty. Returns false if the resulting rectangle is empty.
   //
   // 'this' can be the same object as either aRect1 or aRect2
   PRBool IntersectRect(const nsRect& aRect1, const nsRect& aRect2);
 
-  // Computes the smallest rectangle that contains both aRect1 and aRect2 and
-  // fills 'this' with the result, ignoring empty input rectangles.
+  // Computes the smallest rectangle that contains both the area of both
+  // aRect1 and aRect2, and fills 'this' with the result.
+  // Thus, empty input rectangles are ignored.
   // Returns FALSE and sets 'this' rect to be an empty rect if both aRect1
   // and aRect2 are empty.
   //
   // 'this' can be the same object as either aRect1 or aRect2
   PRBool UnionRect(const nsRect& aRect1, const nsRect& aRect2);
 
-  // Computes the smallest rectangle that contains both aRect1 and aRect2,
-  // where empty input rectangles are allowed to affect the result; the
-  // top-left of an empty input rectangle will be inside or on the edge of
-  // the result.
+  // Computes the smallest rectangle that contains both the points (including
+  // edges) of both aRect1 and aRect2.
+  // Thus, empty input rectangles are allowed to affect the result.
   //
   // 'this' can be the same object as either aRect1 or aRect2
-  void UnionRectIncludeEmpty(const nsRect& aRect1, const nsRect& aRect2);
+  void UnionRectEdges(const nsRect& aRect1, const nsRect& aRect2);
   
   // Accessors
   void SetRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight) {
     x = aX; y = aY; width = aWidth; height = aHeight;
   }
   void SetRect(const nsPoint& aPt, const nsSize& aSize) {
     SetRect(aPt.x, aPt.y, aSize.width, aSize.height);
   }
@@ -138,33 +143,29 @@ struct NS_GFX nsRect {
   void Inflate(const nsSize& aSize) {Inflate(aSize.width, aSize.height);}
   void Inflate(const nsMargin& aMargin);
 
   // Deflate the rect by the specified width/height or margin
   void Deflate(nscoord aDx, nscoord aDy);
   void Deflate(const nsSize& aSize) {Deflate(aSize.width, aSize.height);}
   void Deflate(const nsMargin& aMargin);
 
-  // Overloaded operators. Note that '=' isn't defined so we'll get the
-  // compiler generated default assignment operator.
-  PRBool  operator==(const nsRect& aRect) const {
-    return (PRBool) ((IsEmpty() && aRect.IsEmpty()) ||
-                     ((x == aRect.x) && (y == aRect.y) &&
-                      (width == aRect.width) && (height == aRect.height)));
-  }
-  PRBool  operator!=(const nsRect& aRect) const {
-    return (PRBool) !operator==(aRect);
-  }
-
-  // Useful when we care about the exact x/y/width/height values being
-  // equal (i.e. we care about differences in empty rectangles)
-  PRBool IsExactEqual(const nsRect& aRect) const {
+  // Return true if the rectangles contain the same set of points, including
+  // points on the edges.
+  // Use when we care about the exact x/y/width/height values being
+  // equal (i.e. we care about differences in empty rectangles).
+  PRBool IsEqualEdges(const nsRect& aRect) const {
     return x == aRect.x && y == aRect.y &&
            width == aRect.width && height == aRect.height;
   }
+  // Return true if the rectangles contain the same area of the plane.
+  // Use when we do not care about differences in empty rectangles.
+  PRBool IsEqualInterior(const nsRect& aRect) const {
+    return IsEqualEdges(aRect) || (IsEmpty() && aRect.IsEmpty());
+  }
 
   // Arithmetic with nsPoints
   nsRect  operator+(const nsPoint& aPoint) const {
     return nsRect(x + aPoint.x, y + aPoint.y, width, height);
   }
   nsRect  operator-(const nsPoint& aPoint) const {
     return nsRect(x - aPoint.x, y - aPoint.y, width, height);
   }
@@ -260,22 +261,31 @@ struct NS_GFX nsIntRect {
     y += aMargin.top;
     width -= (aMargin.left + aMargin.right);
     height -= (aMargin.top + aMargin.bottom);
   }
 
   // Overloaded operators. Note that '=' isn't defined so we'll get the
   // compiler generated default assignment operator.
   PRBool operator==(const nsIntRect& aRect) const {
-    return (PRBool) ((IsEmpty() && aRect.IsEmpty()) ||
-                     ((x == aRect.x) && (y == aRect.y) &&
-                      (width == aRect.width) && (height == aRect.height)));
+    return IsEqualEdges(aRect);
   }
-  PRBool  operator!=(const nsIntRect& aRect) const {
-    return (PRBool) !operator==(aRect);
+
+  // Return true if the rectangles contain the same set of points, including
+  // points on the edges.
+  // Use when we care about the exact x/y/width/height values being
+  // equal (i.e. we care about differences in empty rectangles).
+  PRBool IsEqualEdges(const nsIntRect& aRect) const {
+    return x == aRect.x && y == aRect.y &&
+           width == aRect.width && height == aRect.height;
+  }
+  // Return true if the rectangles contain the same area of the plane.
+  // Use when we do not care about differences in empty rectangles.
+  PRBool IsEqualInterior(const nsIntRect& aRect) const {
+    return IsEqualEdges(aRect) || (IsEmpty() && aRect.IsEmpty());
   }
 
   nsIntRect  operator+(const nsIntPoint& aPoint) const {
     return nsIntRect(x + aPoint.x, y + aPoint.y, width, height);
   }
   nsIntRect  operator-(const nsIntPoint& aPoint) const {
     return nsIntRect(x - aPoint.x, y - aPoint.y, width, height);
   }
--- a/gfx/src/nsRegion.cpp
+++ b/gfx/src/nsRegion.cpp
@@ -1146,17 +1146,17 @@ void nsRegion::SubRect (const nsRectFast
         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
+        if (pSrcRect->IsEqualInterior(aRect)) // 4. subset
         {                               // Current rectangle is equal to aRect
           pSrcRect = pSrcRect->next;    // don't add this one to the result, it's removed
           break;                        // No any other rectangle in region can intersect it
         }
       } else
       if (bx > ax && by <= ay)
       {
         if (bxm < axm && bym < aym)     // 5.
@@ -1256,20 +1256,20 @@ PRBool nsRegion::IsEqual (const nsRegion
 {
   if (mRectCount == 0)
     return (aRegion.mRectCount == 0) ? PR_TRUE : PR_FALSE;
 
   if (aRegion.mRectCount == 0)
     return (mRectCount == 0) ? PR_TRUE : PR_FALSE;
 
   if (mRectCount == 1 && aRegion.mRectCount == 1) // Both regions are simple rectangles
-    return (*mRectListHead.next == *aRegion.mRectListHead.next);
+    return (mRectListHead.next->IsEqualInterior(*aRegion.mRectListHead.next));
   else                                            // At least one is complex region.
   {
-    if (mBoundRect != aRegion.mBoundRect)         // If regions are equal then bounding rectangles should match
+    if (!mBoundRect.IsEqualInterior(aRegion.mBoundRect)) // If regions are equal then bounding rectangles should match
       return PR_FALSE;
     else
     {
       nsRegion TmpRegion;
       TmpRegion.Xor (*this, aRegion);             // Get difference between two regions
 
       return (TmpRegion.mRectCount == 0);
     }
--- a/gfx/tests/TestRegion.cpp
+++ b/gfx/tests/TestRegion.cpp
@@ -36,17 +36,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "TestHarness.h"
 #include "nsRegion.h"
 
 class TestLargestRegion {
   static PRBool TestSingleRect(nsRect r) {
     nsRegion region(r);
-    if (region.GetLargestRectangle() != r) {
+    if (!region.GetLargestRectangle().IsEqualInterior(r)) {
       fail("largest rect of singleton %d %d %d %d", r.x, r.y, r.width, r.height);
       return PR_FALSE;
     }
     return PR_TRUE;
   }
   // Construct a rectangle, remove part of it, then check the remainder
   static PRBool TestNonRectangular() {
     nsRegion r(nsRect(0, 0, 30, 30));
@@ -129,26 +129,26 @@ class TestLargestRegion {
         success = PR_FALSE;
       }
     }
     return success;
   }
   static PRBool TestContainsSpecifiedRect() {
     nsRegion r(nsRect(0, 0, 100, 100));
     r.Or(r, nsRect(0, 300, 50, 50));
-    if (r.GetLargestRectangle(nsRect(0, 300, 10, 10)) != nsRect(0, 300, 50, 50)) {
+    if (!r.GetLargestRectangle(nsRect(0, 300, 10, 10)).IsEqualInterior(nsRect(0, 300, 50, 50))) {
       fail("Chose wrong rectangle");
       return PR_FALSE;
     }
     return PR_TRUE;
   }
   static PRBool TestContainsSpecifiedOverflowingRect() {
     nsRegion r(nsRect(0, 0, 100, 100));
     r.Or(r, nsRect(0, 300, 50, 50));
-    if (r.GetLargestRectangle(nsRect(0, 290, 10, 20)) != nsRect(0, 300, 50, 50)) {
+    if (!r.GetLargestRectangle(nsRect(0, 290, 10, 20)).IsEqualInterior(nsRect(0, 300, 50, 50))) {
       fail("Chose wrong rectangle");
       return PR_FALSE;
     }
     return PR_TRUE;
   }
 public:
   static PRBool Test() {
     if (!TestSingleRect(nsRect(0, 52, 720, 480)) ||
--- a/gfx/thebes/GLContext.h
+++ b/gfx/thebes/GLContext.h
@@ -1142,17 +1142,17 @@ public:
     void PopScissorRect() {
         if (mScissorStack.Length() < 2) {
             NS_WARNING("PopScissorRect with Length < 2!");
             return;
         }
 
         nsIntRect thisRect = ScissorRect();
         mScissorStack.TruncateLength(mScissorStack.Length() - 1);
-        if (thisRect != ScissorRect()) {
+        if (!thisRect.IsEqualInterior(ScissorRect())) {
             raw_fScissor(ScissorRect().x, ScissorRect().y,
                               ScissorRect().width, ScissorRect().height);
         }
     }
 
     /*** Viewport functions ***/
 
 protected:
@@ -1193,17 +1193,17 @@ public:
     void PopViewportRect() {
         if (mViewportStack.Length() < 2) {
             NS_WARNING("PopViewportRect with Length < 2!");
             return;
         }
 
         nsIntRect thisRect = ViewportRect();
         mViewportStack.TruncateLength(mViewportStack.Length() - 1);
-        if (thisRect != ViewportRect()) {
+        if (!thisRect.IsEqualInterior(ViewportRect())) {
             raw_fViewport(ViewportRect().x, ViewportRect().y,
                           ViewportRect().width, ViewportRect().height);
         }
     }
 
     /*** other GL functions ***/
 
     void fActiveTexture(GLenum texture) {
--- a/gfx/thebes/gfxBlur.cpp
+++ b/gfx/thebes/gfxBlur.cpp
@@ -90,17 +90,17 @@ gfxAlphaBoxBlur::Init(const gfxRect& aRe
         // expensive int<->float conversions if we were to use gfxRect instead.
         gfxRect skipRect = *aSkipRect;
         skipRect.RoundIn();
         skipRect.Inset(aBlurRadius + aSpreadRadius);
         gfxUtils::GfxRectToIntRect(skipRect, &mSkipRect);
         nsIntRect shadowIntRect;
         gfxUtils::GfxRectToIntRect(rect, &shadowIntRect);
         mSkipRect.IntersectRect(mSkipRect, shadowIntRect);
-        if (mSkipRect == shadowIntRect)
+        if (mSkipRect.IsEqualInterior(shadowIntRect))
           return nsnull;
 
         mSkipRect -= shadowIntRect.TopLeft();
     } else {
         mSkipRect = nsIntRect(0, 0, 0, 0);
     }
 
     // Make an alpha-only surface to draw on. We will play with the data after
--- a/gfx/thebes/gfxImageSurface.cpp
+++ b/gfx/thebes/gfxImageSurface.cpp
@@ -270,17 +270,17 @@ gfxImageSurface::MovePixels(const nsIntR
     // NB: this relies on IntersectRect() and operator+/- preserving
     // x/y for empty rectangles
     NS_ABORT_IF_FALSE(bounds.Contains(dest) && bounds.Contains(source) &&
                       aSourceRect.Contains(source) &&
                       nsIntRect(aDestTopLeft, aSourceRect.Size()).Contains(dest) &&
                       source.Size() == dest.Size() &&
                       offset == (dest.TopLeft() - source.TopLeft()),
                       "Messed up clipping, crash or corruption will follow");
-    if (source.IsEmpty() || source == dest) {
+    if (source.IsEmpty() || source.IsEqualInterior(dest)) {
         return;
     }
 
     long naturalStride = ComputeStride(mSize, mFormat);
     if (mStride == naturalStride && dest.width == bounds.width) {
         // Fast path: this is a vertical shift of some rows in a
         // "normal" image surface.  We can directly memmove and
         // hopefully stay in SIMD land.
--- a/gfx/thebes/gfxRect.h
+++ b/gfx/thebes/gfxRect.h
@@ -82,18 +82,24 @@ struct THEBES_API gfxRect
     gfxRect(const gfxPoint& _pos, const gfxSize& _size) :
         x(_pos.x), y(_pos.y), width(_size.width), height(_size.height) {}
     gfxRect(gfxFloat _x, gfxFloat _y, gfxFloat _width, gfxFloat _height) :
         x(_x), y(_y), width(_width), height(_height) {}
 
     int operator==(const gfxRect& s) const {
         return x == s.x && y == s.y && width == s.width && height == s.height;
     }
-    int operator!=(const gfxRect& s) const {
-        return !(*this == s);
+    PRBool IsEqualEdges(const gfxRect& aRect) const {
+      return x == aRect.x && y == aRect.y &&
+             width == aRect.width && height == aRect.height;
+    }
+    // Return true if the rectangles contain the same area of the plane.
+    // Use when we do not care about differences in empty rectangles.
+    PRBool IsEqualInterior(const gfxRect& aRect) const {
+      return IsEqualEdges(aRect) || (IsEmpty() && aRect.IsEmpty());
     }
 
     void MoveTo(const gfxPoint& aPt) { x = aPt.x; y = aPt.y; }
     const gfxRect& MoveBy(const gfxPoint& aPt) {
         x += aPt.x;
         y += aPt.y;
         return *this;
     }
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -509,11 +509,11 @@ gfxUtils::PathFromRegionSnapped(gfxConte
 }
 
 
 PRBool
 gfxUtils::GfxRectToIntRect(const gfxRect& aIn, nsIntRect* aOut)
 {
   *aOut = nsIntRect(PRInt32(aIn.X()), PRInt32(aIn.Y()),
   PRInt32(aIn.Width()), PRInt32(aIn.Height()));
-  return gfxRect(aOut->x, aOut->y, aOut->width, aOut->height) == aIn;
+  return gfxRect(aOut->x, aOut->y, aOut->width, aOut->height).IsEqualEdges(aIn);
 }
 
--- a/gfx/thebes/gfxXlibNativeRenderer.cpp
+++ b/gfx/thebes/gfxXlibNativeRenderer.cpp
@@ -125,17 +125,17 @@ static PRBool
             !_convert_coord_to_int (clips[i].width, &rect.width) ||
             !_convert_coord_to_int (clips[i].height, &rect.height))
         {
             retval = PR_FALSE;
             NATIVE_DRAWING_NOTE("FALLBACK: non-integer clip");
             goto FINISH;
         }
 
-        if (rect == bounds) {
+        if (rect.IsEqualInterior(bounds)) {
             /* the bounds are entirely inside the clip region so we don't need to clip. */
             *need_clip = PR_FALSE;
             goto FINISH;
         }            
 
         NS_ASSERTION(bounds.Contains(rect),
                      "Was expecting to be clipped to bounds");
 
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -1646,17 +1646,17 @@ FrameLayerBuilder::BuildContainerLayerFo
 
   // Set CONTENT_COMPONENT_ALPHA if any of our children have it.
   // This is suboptimal ... a child could have text that's over transparent
   // pixels in its own layer, but over opaque parts of previous siblings.
   PRUint32 flags;
   state.Finish(&flags);
 
   nsRect bounds = state.GetChildrenBounds();
-  NS_ASSERTION(bounds == aChildren.GetBounds(aBuilder), "Wrong bounds");
+  NS_ASSERTION(bounds.IsEqualInterior(aChildren.GetBounds(aBuilder)), "Wrong bounds");
   nsIntRect pixBounds = bounds.ToOutsidePixels(appUnitsPerDevPixel);
   containerLayer->SetVisibleRegion(pixBounds);
   // Make sure that rounding the visible region out didn't add any area
   // we won't paint
   if (aChildren.IsOpaque() && !aChildren.NeedsTransparentSurface() &&
       bounds.Contains(pixBounds.ToAppUnits(appUnitsPerDevPixel))) {
     // Clear CONTENT_COMPONENT_ALPHA
     flags = Layer::CONTENT_OPAQUE;
--- a/layout/base/FrameLayerBuilder.h
+++ b/layout/base/FrameLayerBuilder.h
@@ -302,17 +302,17 @@ public:
    */
   struct Clip {
     struct RoundedRect {
       nsRect mRect;
       // Indices into mRadii are the NS_CORNER_* constants in nsStyleConsts.h
       nscoord mRadii[8];
 
       bool operator==(const RoundedRect& aOther) const {
-        if (mRect != aOther.mRect) {
+        if (!mRect.IsEqualInterior(aOther.mRect)) {
           return false;
         }
 
         NS_FOR_CSS_HALF_CORNERS(corner) {
           if (mRadii[corner] != aOther.mRadii[corner]) {
             return false;
           }
         }
@@ -349,17 +349,17 @@ public:
     // Intersection of all rects in this clip ignoring any rounded corners.
     nsRect NonRoundedIntersection() const;
 
     // Gets rid of any rounded corners in this clip.
     void RemoveRoundedCorners();
 
     bool operator==(const Clip& aOther) const {
       return mHaveClipRect == aOther.mHaveClipRect &&
-             (!mHaveClipRect || mClipRect == aOther.mClipRect) &&
+             (!mHaveClipRect || mClipRect.IsEqualInterior(aOther.mClipRect)) &&
              mRoundedClipRects == aOther.mRoundedClipRects;
     }
     bool operator!=(const Clip& aOther) const {
       return !(*this == aOther);
     }
   };
 
 protected:
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -33,17 +33,17 @@ load 241300-1.html
 load 243159-1.html
 load 243159-2.xhtml
 asserts(1) load 243519-1.html # bug 536692
 load 244490-1.html
 load 254367-1.html
 load 265027-1.html
 load 265736-1.html
 load 265736-2.html
-asserts(4) load 265899-1.html # bug 575011
+asserts(2) load 265899-1.html # bug 575011
 load 265973-1.html
 asserts(8-12) load 265986-1.html # Bug 512405
 asserts(4) load 265999-1.html # bug 575011
 load 266222-1.html
 asserts(5-7) load 266360-1.html # bug 575011 / bug 576358
 asserts(4) load 266445-1.html # Bug 575011
 load 268157-1.html
 load 269566-1.html
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -438,17 +438,17 @@ PRBool
 nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
                                            nsRegion* aVisibleRegion,
                                            const nsRect& aListVisibleBounds,
                                            const nsRect& aAllowVisibleRegionExpansion,
                                            PRBool& aContainsRootContentDocBG) {
 #ifdef DEBUG
   nsRegion r;
   r.And(*aVisibleRegion, GetBounds(aBuilder));
-  NS_ASSERTION(r.GetBounds() == aListVisibleBounds,
+  NS_ASSERTION(r.GetBounds().IsEqualInterior(aListVisibleBounds),
                "bad aListVisibleBounds");
 #endif
   mVisibleRect = aListVisibleBounds;
   PRBool anyVisible = PR_FALSE;
 
   nsAutoTArray<nsDisplayItem*, 512> elements;
   FlattenTo(&elements);
 
@@ -1914,17 +1914,17 @@ PRBool nsDisplayClip::ComputeVisibility(
   return anyVisible;
 }
 
 PRBool nsDisplayClip::TryMerge(nsDisplayListBuilder* aBuilder,
                                nsDisplayItem* aItem) {
   if (aItem->GetType() != TYPE_CLIP)
     return PR_FALSE;
   nsDisplayClip* other = static_cast<nsDisplayClip*>(aItem);
-  if (other->mClip != mClip)
+  if (!other->mClip.IsEqualInterior(mClip))
     return PR_FALSE;
   mList.AppendToBottom(&other->mList);
   return PR_TRUE;
 }
 
 nsDisplayWrapList* nsDisplayClip::WrapWithClone(nsDisplayListBuilder* aBuilder,
                                                 nsDisplayItem* aItem) {
   return new (aBuilder)
@@ -2010,17 +2010,17 @@ PRBool nsDisplayClipRoundedRect::Compute
 }
 
 PRBool nsDisplayClipRoundedRect::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem)
 {
   if (aItem->GetType() != TYPE_CLIP_ROUNDED_RECT)
     return PR_FALSE;
   nsDisplayClipRoundedRect* other =
     static_cast<nsDisplayClipRoundedRect*>(aItem);
-  if (mClip != other->mClip ||
+  if (!mClip.IsEqualInterior(other->mClip) ||
       memcmp(mRadii, other->mRadii, sizeof(mRadii)) != 0)
     return PR_FALSE;
   mList.AppendToBottom(&other->mList);
   return PR_TRUE;
 }
 
 nsDisplayZoom::nsDisplayZoom(nsDisplayListBuilder* aBuilder,
                              nsIFrame* aFrame, nsDisplayList* aList,
--- a/layout/base/nsImageLoader.cpp
+++ b/layout/base/nsImageLoader.cpp
@@ -199,17 +199,17 @@ NS_IMETHODIMP nsImageLoader::FrameChange
   if (!mFrame)
     return NS_ERROR_FAILURE;
 
   if (!mRequest) {
     // We're in the middle of a paint anyway
     return NS_OK;
   }
 
-  nsRect r = (*aDirtyRect == nsIntRect::GetMaxSizedIntRect()) ?
+  nsRect r = aDirtyRect->IsEqualInterior(nsIntRect::GetMaxSizedIntRect()) ?
     nsRect(nsPoint(0, 0), mFrame->GetSize()) :
     aDirtyRect->ToAppUnits(nsPresContext::AppUnitsPerCSSPixel());
 
   DoRedraw(&r);
 
   return NS_OK;
 }
 
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -478,17 +478,17 @@ public:
    */
   nsRect GetVisibleArea() { return mVisibleArea; }
 
   /**
    * Set the currently visible area. The units for r are standard
    * nscoord units (as scaled by the device context).
    */
   void SetVisibleArea(const nsRect& r) {
-    if (!r.IsExactEqual(mVisibleArea)) {
+    if (!r.IsEqualEdges(mVisibleArea)) {
       mVisibleArea = r;
       // Visible area does not affect media queries when paginated.
       if (!IsPaginated() && HasCachedStyleData())
         PostMediaFeatureValuesChangedEvent();
     }
   }
 
   /**
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -4021,17 +4021,17 @@ AccumulateFrameBounds(nsIFrame* aContain
       }
     }
   }
 
   if (aHaveRect) {
     // We can't use nsRect::UnionRect since it drops empty rects on
     // the floor, and we need to include them.  (Thus we need
     // aHaveRect to know when to drop the initial value on the floor.)
-    aRect.UnionRectIncludeEmpty(aRect, frameBounds);
+    aRect.UnionRectEdges(aRect, frameBounds);
   } else {
     aHaveRect = PR_TRUE;
     aRect = frameBounds;
   }
 }
 
 /**
  * This function takes a scrollable frame, a rect in the coordinate system
@@ -7718,23 +7718,23 @@ PresShell::DoReflow(nsIFrame* target, PR
   // root frame, then its desired size had better not change!  If it's
   // initiated at the root, then the size better not change unless its
   // height was unconstrained to start with.
   NS_ASSERTION((target == rootFrame && size.height == NS_UNCONSTRAINEDSIZE) ||
                (desiredSize.width == size.width &&
                 desiredSize.height == size.height),
                "non-root frame's desired size changed during an "
                "incremental reflow");
-  NS_ASSERTION(desiredSize.VisualOverflow() ==
+  NS_ASSERTION(desiredSize.VisualOverflow().IsEqualInterior(
                  nsRect(nsPoint(0, 0),
-                        nsSize(desiredSize.width, desiredSize.height)),
+                        nsSize(desiredSize.width, desiredSize.height))),
                "reflow roots must not have visible overflow");
-  NS_ASSERTION(desiredSize.ScrollableOverflow() ==
+  NS_ASSERTION(desiredSize.ScrollableOverflow().IsEqualEdges(
                  nsRect(nsPoint(0, 0),
-                        nsSize(desiredSize.width, desiredSize.height)),
+                        nsSize(desiredSize.width, desiredSize.height))),
                "reflow roots must not have scrollable overflow");
   NS_ASSERTION(status == NS_FRAME_COMPLETE,
                "reflow roots should never split");
 
   target->SetSize(nsSize(desiredSize.width, desiredSize.height));
 
   nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, target,
                                              target->GetView(),
@@ -8188,48 +8188,48 @@ CompareTrees(nsPresContext* aFirstPresCo
       if (((nsnull == k1) && (nsnull != k2)) ||
           ((nsnull != k1) && (nsnull == k2))) {
         ok = PR_FALSE;
         LogVerifyMessage(k1, k2, "child lists are different\n");
         break;
       }
       else if (nsnull != k1) {
         // Verify that the frames are the same size
-        if (k1->GetRect() != k2->GetRect()) {
+        if (!k1->GetRect().IsEqualInterior(k2->GetRect())) {
           ok = PR_FALSE;
           LogVerifyMessage(k1, k2, "(frame rects)", k1->GetRect(), k2->GetRect());
         }
 
         // Make sure either both have views or neither have views; if they
         // do have views, make sure the views are the same size. If the
         // views have widgets, make sure they both do or neither does. If
         // they do, make sure the widgets are the same size.
         v1 = k1->GetView();
         v2 = k2->GetView();
         if (((nsnull == v1) && (nsnull != v2)) ||
             ((nsnull != v1) && (nsnull == v2))) {
           ok = PR_FALSE;
           LogVerifyMessage(k1, k2, "child views are not matched\n");
         }
         else if (nsnull != v1) {
-          if (v1->GetBounds() != v2->GetBounds()) {
+          if (!v1->GetBounds().IsEqualInterior(v2->GetBounds())) {
             LogVerifyMessage(k1, k2, "(view rects)", v1->GetBounds(), v2->GetBounds());
           }
 
           nsIWidget* w1 = v1->GetWidget();
           nsIWidget* w2 = v2->GetWidget();
           if (((nsnull == w1) && (nsnull != w2)) ||
               ((nsnull != w1) && (nsnull == w2))) {
             ok = PR_FALSE;
             LogVerifyMessage(k1, k2, "child widgets are not matched\n");
           }
           else if (nsnull != w1) {
             w1->GetBounds(r1);
             w2->GetBounds(r2);
-            if (r1 != r2) {
+            if (!r1.IsEqualEdges(r2)) {
               LogVerifyMessage(k1, k2, "(widget rects)", r1, r2);
             }
           }
         }
         if (!ok && (0 == (VERIFY_REFLOW_ALL & gVerifyReflowFlags))) {
           break;
         }
 
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -249,17 +249,17 @@ load 455171-3.html
 load 455643-1.xhtml
 load 457375.html
 load 457380-1.html
 load 460910-1.xml
 load 461294-1.html
 load 463350-1.html
 load 463350-2.html
 load 463350-3.html
-asserts(6-8) load 463741-1.html # Bug 575011
+load 463741-1.html
 load 465651-1.html
 load 467137-1.html
 load 467213-1.html
 load 467487-1.html
 load 467493-1.html
 load 467493-2.html
 load 467875-1.xhtml
 load 467914-1.html
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -5912,17 +5912,17 @@ nsBlockFrame::ReflowPushedFloats(nsBlock
       nsRect oldRect = f->GetRect();
       nsRect oldOverflow = f->GetVisualOverflowRect();
 
       // Reflow
       aState.FlowAndPlaceFloat(f);
 
       // Invalidate if there was a position or size change
       nsRect rect = f->GetRect();
-      if (rect != oldRect) {
+      if (!rect.IsEqualInterior(oldRect)) {
         nsRect dirtyRect = oldOverflow;
         dirtyRect.MoveBy(oldRect.x, oldRect.y);
         Invalidate(dirtyRect);
 
         dirtyRect = f->GetVisualOverflowRect();
         dirtyRect.MoveBy(rect.x, rect.y);
         Invalidate(dirtyRect);
       }
--- a/layout/generic/nsBlockReflowState.cpp
+++ b/layout/generic/nsBlockReflowState.cpp
@@ -881,17 +881,17 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
   mFloatManager->AddFloat(aFloat, region);
   NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "bad float placement");
   // store region
   rv = nsFloatManager::StoreRegionFor(aFloat, region);
   NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "float region storage failed");
 
   // If the float's dimensions have changed, note the damage in the
   // float manager.
-  if (region != oldRegion) {
+  if (!region.IsEqualEdges(oldRegion)) {
     // XXXwaterson conservative: we could probably get away with noting
     // less damage; e.g., if only height has changed, then only note the
     // area into which the float has grown or from which the float has
     // shrunk.
     nscoord top = NS_MIN(region.y, oldRegion.y);
     nscoord bottom = NS_MAX(region.YMost(), oldRegion.YMost());
     mFloatManager->IncludeInDamage(top, bottom);
   }
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -936,17 +936,17 @@ nsContainerFrame::ReflowOverflowContaine
       //XXXfr Do we need to override any shrinkwrap effects here?
       // e.g. desiredSize.width = prevRect.width;
       rv = FinishReflowChild(frame, aPresContext, &frameState, desiredSize,
                              prevRect.x, 0, aFlags);
       NS_ENSURE_SUCCESS(rv, rv);
 
       // Invalidate if there was a position or size change
       nsRect rect = frame->GetRect();
-      if (rect != oldRect) {
+      if (!rect.IsEqualInterior(oldRect)) {
         nsRect dirtyRect = oldOverflow;
         dirtyRect.MoveBy(oldRect.x, oldRect.y);
         Invalidate(dirtyRect);
 
         dirtyRect = frame->GetVisualOverflowRect();
         dirtyRect.MoveBy(rect.x, rect.y);
         Invalidate(dirtyRect);
       }
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -340,17 +340,17 @@ nsFloatManager::GetRegionFor(nsIFrame* a
 
 nsresult
 nsFloatManager::StoreRegionFor(nsIFrame* aFloat,
                                nsRect&   aRegion)
 {
   nsresult rv = NS_OK;
   nsRect rect = aFloat->GetRect();
   FrameProperties props = aFloat->Properties();
-  if (aRegion == rect) {
+  if (aRegion.IsEqualEdges(rect)) {
     props.Delete(FloatRegionProperty());
   }
   else {
     nsMargin* storedMargin = static_cast<nsMargin*>
       (props.Get(FloatRegionProperty()));
     if (!storedMargin) {
       storedMargin = new nsMargin();
       props.Set(FloatRegionProperty(), storedMargin);
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -6122,17 +6122,17 @@ nsIFrame::SetOverflowAreas(const nsOverf
     return;
   }
 
   const nsRect& vis = aOverflowAreas.VisualOverflow();
   PRUint32 l = -vis.x, // left edge: positive delta is leftwards
            t = -vis.y, // top: positive is upwards
            r = vis.XMost() - mRect.width, // right: positive is rightwards
            b = vis.YMost() - mRect.height; // bottom: positive is downwards
-  if (aOverflowAreas.ScrollableOverflow() == nsRect(nsPoint(0, 0), GetSize()) &&
+  if (aOverflowAreas.ScrollableOverflow().IsEqualEdges(nsRect(nsPoint(0, 0), GetSize())) &&
       l <= NS_FRAME_OVERFLOW_DELTA_MAX &&
       t <= NS_FRAME_OVERFLOW_DELTA_MAX &&
       r <= NS_FRAME_OVERFLOW_DELTA_MAX &&
       b <= NS_FRAME_OVERFLOW_DELTA_MAX &&
       // we have to check these against zero because we *never* want to
       // set a frame as having no overflow in this function.  This is
       // because FinishAndStoreOverflow calls this function prior to
       // SetRect based on whether the overflow areas match aNewSize.
@@ -6197,31 +6197,31 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
 
   // Overflow area must always include the frame's top-left and bottom-right,
   // even if the frame rect is empty.
   // Pending a real fix for bug 426879, don't do this for inline frames
   // with zero width.
   if (aNewSize.width != 0 || !IsInlineFrame(this)) {
     NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
       nsRect& o = aOverflowAreas.Overflow(otype);
-      o.UnionRectIncludeEmpty(o, bounds);
+      o.UnionRectEdges(o, bounds);
     }
   }
 
   // Note that NS_STYLE_OVERFLOW_CLIP doesn't clip the frame background,
   // so we add theme background overflow here so it's not clipped.
   if (!IsBoxWrapped() && IsThemed(disp)) {
     nsRect r(bounds);
     nsPresContext *presContext = PresContext();
     if (presContext->GetTheme()->
           GetWidgetOverflow(presContext->DeviceContext(), this,
                             disp->mAppearance, &r)) {
       NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
         nsRect& o = aOverflowAreas.Overflow(otype);
-        o.UnionRectIncludeEmpty(o, r);
+        o.UnionRectEdges(o, r);
       }
     }
   }
 
   // Nothing in here should affect scrollable overflow.
   PRBool hasOutlineOrEffects;
   aOverflowAreas.VisualOverflow() =
     ComputeOutlineAndEffectsRect(this, &hasOutlineOrEffects,
@@ -6255,17 +6255,17 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
     // Transform affects both overflow areas.
     NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
       nsRect& o = aOverflowAreas.Overflow(otype);
       o = nsDisplayTransform::TransformRect(o, this, nsPoint(0, 0), &newBounds);
     }
   }
 
   PRBool visualOverflowChanged =
-    GetVisualOverflowRect() != aOverflowAreas.VisualOverflow();
+    !GetVisualOverflowRect().IsEqualInterior(aOverflowAreas.VisualOverflow());
 
   if (aOverflowAreas != nsOverflowAreas(bounds, bounds)) {
     SetOverflowAreas(aOverflowAreas);
   } else {
     ClearOverflowRects();
   }
 
   if (visualOverflowChanged) {
--- a/layout/generic/nsFrameUtil.cpp
+++ b/layout/generic/nsFrameUtil.cpp
@@ -601,17 +601,17 @@ nsFrameUtil::CompareTrees(Node* tree1, N
       printf("frame state mismatch: 0x%x vs. 0x%x\n",
              tree1->state, tree2->state);
       printf("Node 1:\n");
       DumpNode(tree1, stdout, 1);
       printf("Node 2:\n");
       DumpNode(tree2, stdout, 1);
       result = PR_FALSE; // we have a non-critical failure, so remember that but continue
     }
-    if (tree1->bbox != tree2->bbox) {
+    if (tree1->bbox.IsEqualInterior(tree2->bbox)) {
       printf("frame bbox mismatch: %d,%d,%d,%d vs. %d,%d,%d,%d\n",
              tree1->bbox.x, tree1->bbox.y,
              tree1->bbox.width, tree1->bbox.height,
              tree2->bbox.x, tree2->bbox.y,
              tree2->bbox.width, tree2->bbox.height);
       printf("Node 1:\n");
       DumpNode(tree1, stdout, 1);
       printf("Node 2:\n");
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -214,17 +214,17 @@ nsHTMLScrollFrame::InvalidateInternal(co
         // damage is now in our coordinate system, which means it was
         // translated using the current scroll position. Adjust it to
         // reflect the scroll position at last paint, since that's what
         // the ThebesLayers are currently set up for.
         // This should not be clipped to the scrollport since ThebesLayers
         // can contain content outside the scrollport that may need to be
         // invalidated.
         nsRect thebesLayerDamage = damage + GetScrollPosition() - mInner.mScrollPosAtLastPaint;
-        if (parentDamage == thebesLayerDamage) {
+        if (parentDamage.IsEqualInterior(thebesLayerDamage)) {
           // This single call will take care of both rects
           nsHTMLContainerFrame::InvalidateInternal(parentDamage, 0, 0, aForChild, aFlags);
         } else {
           // Invalidate rects separately
           if (!(aFlags & INVALIDATE_NO_THEBES_LAYERS)) {
             nsHTMLContainerFrame::InvalidateInternal(thebesLayerDamage, 0, 0, aForChild,
                                                      aFlags | INVALIDATE_ONLY_THEBES_LAYERS);
           }
@@ -234,17 +234,17 @@ nsHTMLScrollFrame::InvalidateInternal(co
           }
         }
       } else {
         if (!parentDamage.IsEmpty()) {
           nsHTMLContainerFrame::InvalidateInternal(parentDamage, 0, 0, aForChild, aFlags);
         }
       }
 
-      if (mInner.mIsRoot && parentDamage != damage) {
+      if (mInner.mIsRoot && !parentDamage.IsEqualInterior(damage)) {
         // Make sure we notify our prescontext about invalidations outside
         // viewport clipping.
         // This is important for things that are snapshotting the viewport,
         // possibly outside the scrolled bounds.
         // We don't need to propagate this any further up, though. Anyone who
         // cares about scrolled-out-of-view invalidates had better be listening
         // to our window directly.
         PresContext()->NotifyInvalidation(damage, aFlags);
@@ -714,18 +714,18 @@ nsHTMLScrollFrame::PlaceScrollArea(const
   nsIFrame *scrolledFrame = mInner.mScrolledFrame;
   // Set the x,y of the scrolled frame to the correct value
   scrolledFrame->SetPosition(mInner.mScrollPort.TopLeft() - aScrollPosition);
 
   nsRect scrolledArea;
   // Preserve the width or height of empty rects
   nsSize portSize = mInner.mScrollPort.Size();
   nsRect scrolledRect = mInner.GetScrolledRectInternal(aState.mContentsOverflowArea, portSize);
-  scrolledArea.UnionRectIncludeEmpty(scrolledRect,
-                                     nsRect(nsPoint(0,0), portSize));
+  scrolledArea.UnionRectEdges(scrolledRect,
+                              nsRect(nsPoint(0,0), portSize));
 
   // Store the new overflow area. Note that this changes where an outline
   // of the scrolled frame would be painted, but scrolled frames can't have
   // outlines (the outline would go on this scrollframe instead).
   // Using FinishAndStoreOverflow is needed so the overflow rect
   // gets set correctly.  It also messes with the overflow rect in the
   // -moz-hidden-unscrollable case, but scrolled frames can't have
   // 'overflow' either.
@@ -897,18 +897,18 @@ nsHTMLScrollFrame::Reflow(nsPresContext*
   nsRect newScrollAreaBounds = mInner.mScrollPort;
   nsRect newScrolledAreaBounds =
     mInner.mScrolledFrame->GetScrollableOverflowRectRelativeToParent();
   if (mInner.mSkippedScrollbarLayout ||
       reflowHScrollbar || reflowVScrollbar || reflowScrollCorner ||
       (GetStateBits() & NS_FRAME_IS_DIRTY) ||
       didHaveHScrollbar != state.mShowHScrollbar ||
       didHaveVScrollbar != state.mShowVScrollbar ||
-      oldScrollAreaBounds != newScrollAreaBounds ||
-      oldScrolledAreaBounds != newScrolledAreaBounds) {
+      !oldScrollAreaBounds.IsEqualEdges(newScrollAreaBounds) ||
+      !oldScrolledAreaBounds.IsEqualEdges(newScrolledAreaBounds)) {
     if (!mInner.mSupppressScrollbarUpdate) {
       mInner.mSkippedScrollbarLayout = PR_FALSE;
       mInner.SetScrollbarVisibility(mInner.mHScrollbarBox, state.mShowHScrollbar);
       mInner.SetScrollbarVisibility(mInner.mVScrollbarBox, state.mShowVScrollbar);
       // place and reflow scrollbars
       nsRect insideBorderArea =
         nsRect(nsPoint(state.mComputedBorder.left, state.mComputedBorder.top),
                state.mInsideBorderSize);
@@ -929,17 +929,17 @@ nsHTMLScrollFrame::Reflow(nsPresContext*
   CheckInvalidateSizeChange(aDesiredSize);
 
   FinishAndStoreOverflow(&aDesiredSize);
 
   if (!InInitialReflow() && !mInner.mHadNonInitialReflow) {
     mInner.mHadNonInitialReflow = PR_TRUE;
   }
 
-  if (mInner.mIsRoot && oldScrolledAreaBounds != newScrolledAreaBounds) {
+  if (mInner.mIsRoot && !oldScrolledAreaBounds.IsEqualEdges(newScrolledAreaBounds)) {
     mInner.PostScrolledAreaEvent();
   }
 
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   mInner.PostOverflowEvent();
   return rv;
 }
@@ -1133,17 +1133,17 @@ nsXULScrollFrame::InvalidateInternal(con
       // damage is now in our coordinate system, which means it was
       // translated using the current scroll position. Adjust it to
       // reflect the scroll position at last paint, since that's what
       // the ThebesLayers are currently set up for.
       // This should not be clipped to the scrollport since ThebesLayers
       // can contain content outside the scrollport that may need to be
       // invalidated.
       nsRect thebesLayerDamage = damage + GetScrollPosition() - mInner.mScrollPosAtLastPaint;
-      if (parentDamage == thebesLayerDamage) {
+      if (parentDamage.IsEqualInterior(thebesLayerDamage)) {
         // This single call will take care of both rects
         nsBoxFrame::InvalidateInternal(parentDamage, 0, 0, aForChild, aFlags);
       } else {
         // Invalidate rects separately
         if (!(aFlags & INVALIDATE_NO_THEBES_LAYERS)) {
           nsBoxFrame::InvalidateInternal(thebesLayerDamage, 0, 0, aForChild,
                                          aFlags | INVALIDATE_ONLY_THEBES_LAYERS);
         }
@@ -2824,17 +2824,17 @@ nsXULScrollFrame::LayoutScrollArea(nsBox
   if (originalRect.TopLeft() != finalRect.TopLeft() ||
       originalVisOverflow.TopLeft() != finalVisOverflow.TopLeft())
   {
     // The old overflow rect needs to be adjusted if the frame's position
     // changed.
     mInner.mScrolledFrame->Invalidate(
       originalVisOverflow + originalRect.TopLeft() - finalRect.TopLeft());
     mInner.mScrolledFrame->Invalidate(finalVisOverflow);
-  } else if (!originalVisOverflow.IsExactEqual(finalVisOverflow)) {
+  } else if (!originalVisOverflow.IsEqualInterior(finalVisOverflow)) {
     // If the overflow rect changed then invalidate the difference between the
     // old and new overflow rects.
     mInner.mScrolledFrame->CheckInvalidateSizeChange(
       originalRect, originalVisOverflow, finalRect.Size());
     mInner.mScrolledFrame->InvalidateRectDifference(
       originalVisOverflow, finalVisOverflow);
   }
 
@@ -3233,17 +3233,17 @@ static void LayoutAndInvalidate(nsBoxLay
   // to make sure to catch any overflow.
   // We invalidate the parent (i.e. the scrollframe) directly, because
   // invalidates coming from scrollbars are suppressed by nsHTMLScrollFrame when
   // mHasVScrollbar/mHasHScrollbar is false, and this is called after those
   // flags have been set ... if a scrollbar is being hidden, we still need
   // to invalidate the scrollbar area here.
   // But we also need to invalidate the scrollbar itself in case it has
   // its own layer; we need to ensure that layer is updated.
-  PRBool rectChanged = aBox->GetRect() != aRect;
+  PRBool rectChanged = !aBox->GetRect().IsEqualInterior(aRect);
   if (rectChanged) {
     if (aScrollbarIsBeingHidden) {
       aBox->GetParent()->Invalidate(aBox->GetVisualOverflowRect() +
                                     aBox->GetPosition());
     } else {
       aBox->InvalidateFrameSubtree();
     }
   }
--- a/layout/generic/nsHTMLReflowMetrics.h
+++ b/layout/generic/nsHTMLReflowMetrics.h
@@ -106,18 +106,18 @@ public:
     mRects[0] = aOther.mRects[0];
     mRects[1] = aOther.mRects[1];
     return *this;
   }
 
   bool operator==(const nsOverflowAreas& aOther) const {
     // Scrollable overflow is a point-set rectangle and visual overflow
     // is a pixel-set rectangle.
-    return VisualOverflow() == aOther.VisualOverflow() &&
-           ScrollableOverflow().IsExactEqual(aOther.ScrollableOverflow());
+    return VisualOverflow().IsEqualInterior(aOther.VisualOverflow()) &&
+           ScrollableOverflow().IsEqualEdges(aOther.ScrollableOverflow());
   }
 
   bool operator!=(const nsOverflowAreas& aOther) const {
     return !(*this == aOther);
   }
 
   nsOverflowAreas operator+(const nsPoint& aPoint) const {
     nsOverflowAreas result(*this);
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -590,17 +590,17 @@ nsImageFrame::OnDataAvailable(imgIReques
 
   // Don't invalidate if the current visible frame isn't the one the data is
   // from
   if (!aCurrentFrame)
     return NS_OK;
 
   // XXX We really need to round this out, now that we're doing better
   // image scaling!
-  nsRect r = (*aRect == nsIntRect::GetMaxSizedIntRect()) ?
+  nsRect r = aRect->IsEqualInterior(nsIntRect::GetMaxSizedIntRect()) ?
     GetInnerArea() :
     SourceRectToDest(*aRect);
 
 #ifdef DEBUG_decode
   printf("Source rect (%d,%d,%d,%d) -> invalidate dest rect (%d,%d,%d,%d)\n",
          aRect->x, aRect->y, aRect->width, aRect->height,
          r.x, r.y, r.width, r.height);
 #endif
@@ -674,17 +674,17 @@ nsImageFrame::FrameChanged(imgIContainer
     return NS_OK;
   }
 
   if (IsPendingLoad(aContainer)) {
     // We don't care about it
     return NS_OK;
   }
 
-  nsRect r = (*aDirtyRect == nsIntRect::GetMaxSizedIntRect()) ?
+  nsRect r = aDirtyRect->IsEqualInterior(nsIntRect::GetMaxSizedIntRect()) ?
     GetInnerArea() :
     SourceRectToDest(*aDirtyRect);
 
   // Update border+content to account for image change
   Invalidate(r);
   mImageContainer = nsnull;
   return NS_OK;
 }
--- a/layout/generic/nsLineBox.cpp
+++ b/layout/generic/nsLineBox.cpp
@@ -498,19 +498,18 @@ void
 nsLineBox::SetOverflowAreas(const nsOverflowAreas& aOverflowAreas)
 {
   NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
     NS_ASSERTION(aOverflowAreas.Overflow(otype).width >= 0,
                  "illegal width for combined area");
     NS_ASSERTION(aOverflowAreas.Overflow(otype).height >= 0,
                  "illegal height for combined area");
   }
-  // REVIEW: should this use IsExactEqual?
-  if (aOverflowAreas.VisualOverflow() != mBounds ||
-      aOverflowAreas.ScrollableOverflow() != mBounds) {
+  if (!aOverflowAreas.VisualOverflow().IsEqualInterior(mBounds) ||
+      !aOverflowAreas.ScrollableOverflow().IsEqualEdges(mBounds)) {
     if (!mData) {
       if (IsInline()) {
         mInlineData = new ExtraInlineData(mBounds);
       }
       else {
         mBlockData = new ExtraBlockData(mBounds);
       }
     }
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -2390,17 +2390,17 @@ nsObjectFrame::PaintPlugin(nsDisplayList
         // since I don't see any incorrect painting (at least with Flash and ViewPoint -
         // the originator of bug 135737), it seems that windowless plugins are not relying
         // on information here for clipping their drawing, and we can safely use this message
         // to tell the plugin exactly where it is in all cases.
 
         nsIntPoint origin = GetWindowOriginInPixels(PR_TRUE);
         nsIntRect winlessRect = nsIntRect(origin, nsIntSize(window->width, window->height));
 
-        if (mWindowlessRect != winlessRect) {
+        if (!mWindowlessRect.IsEqualEdges(winlessRect)) {
           mWindowlessRect = winlessRect;
 
           WINDOWPOS winpos;
           memset(&winpos, 0, sizeof(winpos));
           winpos.x = mWindowlessRect.x;
           winpos.y = mWindowlessRect.y;
           winpos.cx = mWindowlessRect.width;
           winpos.cy = mWindowlessRect.height;
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -5551,17 +5551,17 @@ nsTypedSelection::GetSelectionAnchorGeom
   if (!focusFrame)
     return nsnull;
 
   NS_ASSERTION(anchorFrame->PresContext() == focusFrame->PresContext(),
     "points of selection in different documents?");
   // make focusRect relative to anchorFrame
   focusRect += focusFrame->GetOffsetTo(anchorFrame);
 
-  aRect->UnionRectIncludeEmpty(anchorRect, focusRect);
+  aRect->UnionRectEdges(anchorRect, focusRect);
   return anchorFrame;
 }
 
 nsIFrame *
 nsTypedSelection::GetSelectionEndPointGeometry(SelectionRegion aRegion,
                                                nsRect *aRect)
 {
   if (!mFrameSelection)
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -694,17 +694,17 @@ nsStyleList::nsStyleList(const nsStyleLi
 }
 
 nsChangeHint nsStyleList::CalcDifference(const nsStyleList& aOther) const
 {
   if (mListStylePosition != aOther.mListStylePosition)
     return NS_STYLE_HINT_FRAMECHANGE;
   if (EqualImages(mListStyleImage, aOther.mListStyleImage) &&
       mListStyleType == aOther.mListStyleType) {
-    if (mImageRegion == aOther.mImageRegion)
+    if (mImageRegion.IsEqualInterior(aOther.mImageRegion))
       return NS_STYLE_HINT_NONE;
     if (mImageRegion.width == aOther.mImageRegion.width &&
         mImageRegion.height == aOther.mImageRegion.height)
       return NS_STYLE_HINT_VISUAL;
   }
   return NS_STYLE_HINT_REFLOW;
 }
 
@@ -1594,17 +1594,17 @@ nsStyleImage::ComputeActualCropRect(nsIn
   PRInt32 bottom = ConvertToPixelCoord(mCropRect->GetBottom(), imageSize.height);
 
   // IntersectRect() returns an empty rect if we get negative width or height
   nsIntRect cropRect(left, top, right - left, bottom - top);
   nsIntRect imageRect(nsIntPoint(0, 0), imageSize);
   aActualCropRect.IntersectRect(imageRect, cropRect);
 
   if (aIsEntireImage)
-    *aIsEntireImage = (aActualCropRect == imageRect);
+    *aIsEntireImage = aActualCropRect.IsEqualInterior(imageRect);
   return PR_TRUE;
 }
 
 nsresult
 nsStyleImage::RequestDecode() const
 {
   if ((mType == eStyleImageType_Image) && mImage)
     return mImage->RequestDecode();
@@ -2123,17 +2123,17 @@ nsChangeHint nsStyleDisplay::CalcDiffere
   }
 
   // XXX the following is conservative, for now: changing float breaking shouldn't
   // necessarily require a repaint, reflow should suffice.
   if (mBreakType != aOther.mBreakType
       || mBreakBefore != aOther.mBreakBefore
       || mBreakAfter != aOther.mBreakAfter
       || mAppearance != aOther.mAppearance
-      || mClipFlags != aOther.mClipFlags || mClip != aOther.mClip)
+      || mClipFlags != aOther.mClipFlags || !mClip.IsEqualInterior(aOther.mClip))
     NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame));
 
   if (mOpacity != aOther.mOpacity) {
     NS_UpdateHint(hint, nsChangeHint_UpdateOpacityLayer);
   }
 
   /* If we've added or removed the transform property, we need to reconstruct the frame to add
    * or remove the view object, and also to handle abs-pos and fixed-pos containers.
--- a/layout/svg/base/src/nsSVGOuterSVGFrame.cpp
+++ b/layout/svg/base/src/nsSVGOuterSVGFrame.cpp
@@ -653,17 +653,17 @@ nsSVGOuterSVGFrame::UpdateAndInvalidateC
   nsISVGChildFrame *svgFrame = do_QueryFrame(aFrame);
   if (!svgFrame)
     return PR_FALSE;
 
   nsRect oldRegion = svgFrame->GetCoveredRegion();
   Invalidate(nsSVGUtils::FindFilterInvalidation(aFrame, oldRegion));
   svgFrame->UpdateCoveredRegion();
   nsRect newRegion = svgFrame->GetCoveredRegion();
-  if (oldRegion == newRegion)
+  if (oldRegion.IsEqualInterior(newRegion))
     return PR_FALSE;
 
   Invalidate(nsSVGUtils::FindFilterInvalidation(aFrame, newRegion));
   return PR_TRUE;
 }
 
 PRBool
 nsSVGOuterSVGFrame::IsRedrawSuspended()
--- a/layout/xul/base/src/nsSliderFrame.cpp
+++ b/layout/xul/base/src/nsSliderFrame.cpp
@@ -434,17 +434,17 @@ nsSliderFrame::DoLayout(nsBoxLayoutState
   thumbPos += NSToCoordRound(pos * mRatio);
 
   nsRect oldThumbRect(thumbBox->GetRect());
   LayoutChildAt(aState, thumbBox, thumbRect);
 
   SyncLayout(aState);
 
   // Redraw only if thumb changed size.
-  if (oldThumbRect != thumbRect)
+  if (!oldThumbRect.IsEqualInterior(thumbRect))
     Redraw(aState);
 
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsSliderFrame::HandleEvent(nsPresContext* aPresContext,
--- a/layout/xul/base/src/nsSprocketLayout.cpp
+++ b/layout/xul/base/src/nsSprocketLayout.cpp
@@ -519,17 +519,17 @@ nsSprocketLayout::Layout(nsIBox* aBox, n
       // around as a result of the size change.
       if (layout || sizeChanged)
         child->Layout(aState);
       
       // If the child was a block or inline (e.g., HTML) it may have changed its rect *during* layout. 
       // We have to check for this.
       nsRect newChildRect(child->GetRect());
 
-      if (newChildRect != childRect) {
+      if (!newChildRect.IsEqualEdges(childRect)) {
 #ifdef DEBUG_GROW
         child->DumpBox(stdout);
         printf(" GREW from (%d,%d) -> (%d,%d)\n", childRect.width, childRect.height, newChildRect.width, newChildRect.height);
 #endif
         newChildRect.Inflate(margin);
         childRect.Inflate(margin);
 
         // The child changed size during layout.  The ChildResized method handles this
@@ -1158,17 +1158,17 @@ nsSprocketLayout::ChildResized(nsIBox* a
                 containingWidth += aChildComputedSize->size - childLayoutWidth;
               }              
             }
       }
 
       if (recompute)
             ComputeChildSizes(aBox, aState, containingWidth, aBoxSizes, aComputedBoxSizes);
 
-      if (childCurrentRect != aChildActualRect) {
+      if (!childCurrentRect.IsEqualEdges(aChildActualRect)) {
         // the childRect includes the margin
         // make sure we remove it before setting 
         // the bounds.
         nsMargin margin(0,0,0,0);
         aChild->GetMargin(margin);
         nsRect rect(aChildActualRect);
         if (rect.width >= margin.left + margin.right && rect.height >= margin.top + margin.bottom) 
           rect.Deflate(margin);
--- a/layout/xul/base/src/nsStackLayout.cpp
+++ b/layout/xul/base/src/nsStackLayout.cpp
@@ -303,17 +303,17 @@ nsStackLayout::Layout(nsIBox* aBox, nsBo
 
       if (childRect.width < 0)
         childRect.width = 0;
 
       if (childRect.height < 0)
         childRect.height = 0;
 
       nsRect oldRect(child->GetRect());
-      PRBool sizeChanged = !oldRect.IsExactEqual(childRect);
+      PRBool sizeChanged = !oldRect.IsEqualEdges(childRect);
 
       // only lay out dirty children or children whose sizes have changed
       if (sizeChanged || NS_SUBTREE_DIRTY(child)) {
           // add in the child's margin
           nsMargin margin;
           child->GetMargin(margin);
 
           // obtain our offset from the top left border of the stack's content box.
@@ -383,17 +383,17 @@ nsStackLayout::Layout(nsIBox* aBox, nsBo
             }
 
             if (offset.TopBottom() + childRect.height > clientRect.height) {
               clientRect.height = childRect.height + offset.TopBottom();
               grow = PR_TRUE;
             }
           }
 
-          if (childRectNoMargin != oldRect)
+          if (!childRectNoMargin.IsEqualInterior(oldRect))
           {
             // redraw the new and old positions if the 
             // child moved or resized.
             // if the new and old rect intersect meaning we just moved a little
             // then just redraw the union. If they don't intersect (meaning
             // we moved a good distance) redraw both separately.
             if (childRectNoMargin.Intersects(oldRect)) {
               nsRect u;
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
@@ -406,17 +406,17 @@ nsTreeBodyFrame::EnsureView()
   }
 }
 
 void
 nsTreeBodyFrame::SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect,
                            PRBool aRemoveOverflowArea)
 {
   nscoord horzWidth = CalcHorzWidth(GetScrollParts());
-  if ((aRect != mRect || mHorzWidth != horzWidth) && !mReflowCallbackPosted) {
+  if ((!aRect.IsEqualEdges(mRect) || mHorzWidth != horzWidth) && !mReflowCallbackPosted) {
     mReflowCallbackPosted = PR_TRUE;
     PresContext()->PresShell()->PostReflowCallback(this);
   }
 
   mHorzWidth = horzWidth;
 
   nsLeafBoxFrame::SetBounds(aBoxLayoutState, aRect, aRemoveOverflowArea);
 }
--- a/modules/libpr0n/src/RasterImage.cpp
+++ b/modules/libpr0n/src/RasterImage.cpp
@@ -518,17 +518,17 @@ RasterImage::GetCurrentFrameIsOpaque(PRB
 
   // Otherwise, we can make a more intelligent decision
   else {
     *aIsOpaque = !curframe->GetNeedsBackground();
 
     // We are also transparent if the current frame's size doesn't cover our
     // entire area.
     nsIntRect framerect = curframe->GetRect();
-    *aIsOpaque = *aIsOpaque && (framerect != nsIntRect(0, 0, mSize.width, mSize.height));
+    *aIsOpaque = *aIsOpaque && framerect.IsEqualInterior(nsIntRect(0, 0, mSize.width, mSize.height));
   }
 
   return NS_OK;
 }
 
 void
 RasterImage::GetCurrentFrameRect(nsIntRect& aRect)
 {
--- a/modules/libpr0n/src/imgFrame.cpp
+++ b/modules/libpr0n/src/imgFrame.cpp
@@ -759,17 +759,17 @@ PRInt32 imgFrame::GetBlendMethod() const
 
 void imgFrame::SetBlendMethod(PRInt32 aBlendMethod)
 {
   mBlendMethod = (PRInt8)aBlendMethod;
 }
 
 PRBool imgFrame::ImageComplete() const
 {
-  return mDecoded == nsIntRect(mOffset, mSize);
+  return mDecoded.IsEqualInterior(nsIntRect(mOffset, mSize));
 }
 
 // A hint from the image decoders that this image has no alpha, even
 // though we created is ARGB32.  This changes our format to RGB24,
 // which in turn will cause us to Optimize() to RGB24.  Has no effect
 // after Optimize() is called, though in all cases it will be just a
 // performance win -- the pixels are still correct and have the A byte
 // set to 0xff.
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -297,17 +297,17 @@ NS_IMETHODIMP nsViewManager::GetWindowDi
 }
 
 void nsViewManager::DoSetWindowDimensions(nscoord aWidth, nscoord aHeight)
 {
   nsRect oldDim;
   nsRect newDim(0, 0, aWidth, aHeight);
   mRootView->GetDimensions(oldDim);
   // We care about resizes even when one dimension is already zero.
-  if (!oldDim.IsExactEqual(newDim)) {
+  if (!oldDim.IsEqualEdges(newDim)) {
     // Don't resize the widget. It is already being set elsewhere.
     mRootView->SetDimensions(newDim, PR_TRUE, PR_FALSE);
     if (mObserver)
       mObserver->ResizeReflow(mRootView, aWidth, aHeight);
   }
 }
 
 NS_IMETHODIMP nsViewManager::SetWindowDimensions(nscoord aWidth, nscoord aHeight)
@@ -1347,17 +1347,17 @@ void nsViewManager::InvalidateRectDiffer
 
 NS_IMETHODIMP nsViewManager::ResizeView(nsIView *aView, const nsRect &aRect, PRBool aRepaintExposedAreaOnly)
 {
   nsView* view = static_cast<nsView*>(aView);
   NS_ASSERTION(view->GetViewManager() == this, "wrong view manager");
   nsRect oldDimensions;
 
   view->GetDimensions(oldDimensions);
-  if (!oldDimensions.IsExactEqual(aRect)) {
+  if (!oldDimensions.IsEqualEdges(aRect)) {
     // resize the view.
     // Prevent Invalidation of hidden views 
     if (view->GetVisibility() == nsViewVisibility_kHide) {  
       view->SetDimensions(aRect, PR_FALSE);
     } else {
       nsView* parentView = view->GetParent();
       if (!parentView) {
         parentView = view;
--- a/widget/src/os2/nsWindow.cpp
+++ b/widget/src/os2/nsWindow.cpp
@@ -1040,17 +1040,17 @@ nsresult nsWindow::ConfigureChildren(con
 // and Update() because none of them support the options needed here.
 
 void nsWindow::SetPluginClipRegion(const Configuration& aConfiguration)
 {
   NS_ASSERTION((mParent && mParent->mWnd), "Child window has no parent");
 
   // If nothing has changed, exit.
   if (!StoreWindowClipRegion(aConfiguration.mClipRegion) &&
-      mBounds == aConfiguration.mBounds) {
+      mBounds.IsEqualInterior(aConfiguration.mBounds)) {
     return;
   }
 
   // Set the widget's x/y to its nominal unclipped value.  It doesn't
   // affect our calculations but other code relies on it being correct.
   mBounds.MoveTo(aConfiguration.mBounds.TopLeft());
 
   // Get or create the PM window we use as a clipping rectangle.
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -1532,17 +1532,17 @@ NS_METHOD nsWindow::Move(PRInt32 aX, PRI
 
     UINT flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE;
     // Workaround SetWindowPos bug with D3D9. If our window has a clip
     // region, some drivers or OSes may incorrectly copy into the clipped-out
     // area.
     if (mWindowType == eWindowType_plugin &&
         (!mLayerManager || mLayerManager->GetBackendType() == LayerManager::LAYERS_D3D9) &&
         mClipRects &&
-        (mClipRectCount != 1 || mClipRects[0] != nsIntRect(0, 0, mBounds.width, mBounds.height))) {
+        (mClipRectCount != 1 || !mClipRects[0].IsEqualInterior(nsIntRect(0, 0, mBounds.width, mBounds.height)))) {
       flags |= SWP_NOCOPYBITS;
     }
     VERIFY(::SetWindowPos(mWnd, NULL, aX, aY, 0, 0, flags));
 
     SetThemeRegion();
   }
   return NS_OK;
 }
--- a/widget/src/xpwidgets/PuppetWidget.cpp
+++ b/widget/src/xpwidgets/PuppetWidget.cpp
@@ -210,17 +210,17 @@ PuppetWidget::Resize(PRInt32 aWidth,
   // XXX: roc says that |aRepaint| dictates whether or not to
   // invalidate the expanded area
   if (oldBounds.Size() < mBounds.Size() && aRepaint) {
     nsIntRegion dirty(mBounds);
     dirty.Sub(dirty,  oldBounds);
     InvalidateRegion(this, dirty);
   }
 
-  if (oldBounds != mBounds) {
+  if (!oldBounds.IsEqualEdges(mBounds)) {
     DispatchResizeEvent();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PuppetWidget::SetFocus(PRBool aRaise)