Fix miscellaneous reflow methods to use new overflow area APIs. (Bug 542595, patch 19) r=roc a2.0=blocking2.0:beta8
authorL. David Baron <dbaron@dbaron.org>
Wed, 06 Oct 2010 21:25:46 -0700
changeset 55039 08860c83bf8825b1ceabb1a840954f29a46a143f
parent 55038 061f5e6d58be7d05492d55048d4cd38ba7f354b4
child 55040 0705671514244627171aa1b4e49053e1a3c6237c
push id16120
push userdbaron@mozilla.com
push dateThu, 07 Oct 2010 04:26:21 +0000
treeherdermozilla-central@1aab37daf3bc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs542595
milestone2.0b8pre
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
Fix miscellaneous reflow methods to use new overflow area APIs. (Bug 542595, patch 19) r=roc a2.0=blocking2.0:beta8
layout/base/nsPresShell.cpp
layout/forms/nsFieldSetFrame.cpp
layout/forms/nsHTMLButtonControlFrame.cpp
layout/generic/nsBRFrame.cpp
layout/generic/nsBulletFrame.cpp
layout/generic/nsCanvasFrame.cpp
layout/generic/nsColumnSetFrame.cpp
layout/generic/nsContainerFrame.cpp
layout/generic/nsFirstLetterFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrameSetFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsHTMLCanvasFrame.cpp
layout/generic/nsImageFrame.cpp
layout/generic/nsInlineFrame.cpp
layout/generic/nsLeafFrame.cpp
layout/generic/nsObjectFrame.cpp
layout/generic/nsSimplePageSequence.cpp
layout/generic/nsTextFrameThebes.cpp
layout/generic/nsVideoFrame.cpp
layout/generic/nsViewportFrame.cpp
layout/mathml/nsMathMLContainerFrame.cpp
layout/svg/base/src/nsSVGForeignObjectFrame.cpp
layout/svg/base/src/nsSVGOuterSVGFrame.cpp
layout/tables/nsTableCellFrame.cpp
layout/tables/nsTableFrame.cpp
layout/tables/nsTableOuterFrame.cpp
layout/tables/nsTableRowFrame.cpp
layout/tables/nsTableRowGroupFrame.cpp
layout/xul/base/src/nsBox.cpp
layout/xul/base/src/nsBoxFrame.cpp
layout/xul/base/src/nsLeafBoxFrame.cpp
layout/xul/base/src/nsListBoxBodyFrame.cpp
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -7741,28 +7741,32 @@ 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.mOverflowArea ==
+  NS_ASSERTION(desiredSize.VisualOverflow() ==
                  nsRect(nsPoint(0, 0),
                         nsSize(desiredSize.width, desiredSize.height)),
                "reflow roots must not have visible overflow");
+  NS_ASSERTION(desiredSize.ScrollableOverflow() ==
+                 nsRect(nsPoint(0, 0),
+                        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(),
-                                             &desiredSize.mOverflowArea);
+                                             desiredSize.VisualOverflow());
   nsContainerFrame::SyncWindowProperties(mPresContext, target,
                                          target->GetView());
 
   target->DidReflow(mPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
   if (target == rootFrame && size.height == NS_UNCONSTRAINEDSIZE) {
     mPresContext->SetVisibleArea(nsRect(0, 0, desiredSize.width,
                                         desiredSize.height));
   }
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -592,24 +592,24 @@ nsFieldSetFrame::Reflow(nsPresContext*  
   } else {
     nscoord min = borderPadding.TopBottom() + mLegendRect.height;
     aDesiredSize.height =
       aReflowState.ComputedHeight() + borderPadding.TopBottom();
     if (aDesiredSize.height < min)
       aDesiredSize.height = min;
   }
   aDesiredSize.width = contentRect.width + borderPadding.LeftRight();
-  aDesiredSize.mOverflowArea = nsRect(0, 0, aDesiredSize.width, aDesiredSize.height);
+  aDesiredSize.SetOverflowAreasToDesiredBounds();
   if (mLegendFrame)
-    ConsiderChildOverflow(aDesiredSize.mOverflowArea, mLegendFrame);
+    ConsiderChildOverflow(aDesiredSize.mOverflowAreas, mLegendFrame);
   if (mContentFrame)
-    ConsiderChildOverflow(aDesiredSize.mOverflowArea, mContentFrame);
+    ConsiderChildOverflow(aDesiredSize.mOverflowAreas, mContentFrame);
   FinishAndStoreOverflow(&aDesiredSize);
 
-  Invalidate(aDesiredSize.mOverflowArea);
+  Invalidate(aDesiredSize.VisualOverflow());
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 PRIntn
 nsFieldSetFrame::GetSkipSides() const
 {
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -276,19 +276,18 @@ nsHTMLButtonControlFrame::Reflow(nsPresC
   // exposing nsHTMLReflowState::AdjustComputed* or something.
   aDesiredSize.height = NS_CSS_MINMAX(aDesiredSize.height,
                                       aReflowState.mComputedMinHeight,
                                       aReflowState.mComputedMaxHeight);
 
   aDesiredSize.ascent +=
     aReflowState.mComputedBorderPadding.top + focusPadding.top;
 
-  aDesiredSize.mOverflowArea =
-    nsRect(0, 0, aDesiredSize.width, aDesiredSize.height);
-  ConsiderChildOverflow(aDesiredSize.mOverflowArea, firstKid);
+  aDesiredSize.SetOverflowAreasToDesiredBounds();
+  ConsiderChildOverflow(aDesiredSize.mOverflowAreas, firstKid);
   FinishAndStoreOverflow(&aDesiredSize);
 
   aStatus = NS_FRAME_COMPLETE;
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
--- a/layout/generic/nsBRFrame.cpp
+++ b/layout/generic/nsBRFrame.cpp
@@ -176,18 +176,18 @@ BRFrame::Reflow(nsPresContext* aPresCont
 
     aStatus = NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER |
       NS_INLINE_MAKE_BREAK_TYPE(breakType);
     ll->SetLineEndsInBR(PR_TRUE);
   }
   else {
     aStatus = NS_FRAME_COMPLETE;
   }
-  
-  aMetrics.mOverflowArea = nsRect(0, 0, aMetrics.width, aMetrics.height);
+
+  aMetrics.SetOverflowAreasToDesiredBounds();
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
   return NS_OK;
 }
 
 /* virtual */ void
 BRFrame::AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
                            nsIFrame::InlineMinWidthData *aData)
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -1402,18 +1402,18 @@ nsBulletFrame::Reflow(nsPresContext* aPr
   aMetrics.width += borderPadding.left + borderPadding.right;
   aMetrics.height += borderPadding.top + borderPadding.bottom;
   aMetrics.ascent += borderPadding.top;
 
   // XXX this is a bit of a hack, we're assuming that no glyphs used for bullets
   // overflow their font-boxes. It'll do for now; to fix it for real, we really
   // should rewrite all the text-handling code here to use gfxTextRun (bug
   // 397294).
-  aMetrics.mOverflowArea.SetRect(0, 0, aMetrics.width, aMetrics.height);
-  
+  aMetrics.SetOverflowAreasToDesiredBounds();
+
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
   return NS_OK;
 }
 
 /* virtual */ nscoord
 nsBulletFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
 {
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -543,19 +543,19 @@ nsCanvasFrame::Reflow(nsPresContext*    
     aDesiredSize.width = aReflowState.ComputedWidth();
     if (aReflowState.ComputedHeight() == NS_UNCONSTRAINEDSIZE) {
       aDesiredSize.height = kidFrame->GetRect().height +
         kidReflowState.mComputedMargin.TopBottom();
     } else {
       aDesiredSize.height = aReflowState.ComputedHeight();
     }
 
-    aDesiredSize.mOverflowArea.UnionRect(
-      nsRect(0, 0, aDesiredSize.width, aDesiredSize.height),
-      kidDesiredSize.mOverflowArea + kidPt);
+    aDesiredSize.SetOverflowAreasToDesiredBounds();
+    aDesiredSize.mOverflowAreas.UnionWith(
+      kidDesiredSize.mOverflowAreas + kidPt);
 
     if (mAbsoluteContainer.HasAbsoluteFrames()) {
       PRBool widthChanged = aDesiredSize.width != mRect.width;
       PRBool heightChanged = aDesiredSize.height != mRect.height;
       mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, aStatus,
                                 aDesiredSize.width, aDesiredSize.height,
                                 PR_TRUE, widthChanged, heightChanged,
                                 &aDesiredSize.mOverflowAreas);
--- a/layout/generic/nsColumnSetFrame.cpp
+++ b/layout/generic/nsColumnSetFrame.cpp
@@ -550,18 +550,18 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
     //NS_ASSERTION(aKidReason != eReflowReason_Incremental,
     //             "incremental reflow should not have changed the balance height");
   }
 
   // get our border and padding
   const nsMargin &borderPadding = aReflowState.mComputedBorderPadding;
   
   nsRect contentRect(0, 0, 0, 0);
-  nsRect overflowRect(0, 0, 0, 0);
-  
+  nsOverflowAreas overflowRects;
+
   nsIFrame* child = mFrames.FirstChild();
   nsPoint childOrigin = nsPoint(borderPadding.left, borderPadding.top);
   // For RTL, figure out where the last column's left edge should be. Since the
   // columns might not fill the frame exactly, we need to account for the
   // slop. Otherwise we'll waste time moving the columns by some tiny
   // amount unnecessarily.
   nscoord targetX = borderPadding.left;
   if (RTL) {
@@ -690,17 +690,17 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
       if (childContentBottom > availSize.height) {
         aColData.mMaxOverflowingHeight = NS_MAX(childContentBottom,
             aColData.mMaxOverflowingHeight);
       }
     }
 
     contentRect.UnionRect(contentRect, child->GetRect());
 
-    ConsiderChildOverflow(overflowRect, child);
+    ConsiderChildOverflow(overflowRects, child);
     contentBottom = NS_MAX(contentBottom, childContentBottom);
     aColData.mLastHeight = childContentBottom;
     aColData.mSumHeight += childContentBottom;
 
     // Build a continuation column if necessary
     nsIFrame* kidNextInFlow = child->GetNextInFlow();
 
     if (NS_FRAME_IS_FULLY_COMPLETE(aStatus) && !NS_FRAME_IS_TRUNCATED(aStatus)) {
@@ -796,25 +796,25 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
     // bail out immediately, since it'll already have a dirty bit.
     for (; child; child = child->GetNextSibling()) {
       child->AddStateBits(NS_FRAME_IS_DIRTY);
     }
   }
   
   // If we're doing RTL, we need to make sure our last column is at the left-hand side of the frame.
   if (RTL && childOrigin.x != targetX) {
-    overflowRect = nsRect(0, 0, 0, 0);
+    overflowRects.Clear();
     contentRect = nsRect(0, 0, 0, 0);
     PRInt32 deltaX = targetX - childOrigin.x;
 #ifdef DEBUG_roc
     printf("*** CHILDORIGIN.x = %d, targetX = %d, DELTAX = %d\n", childOrigin.x, targetX, deltaX);
 #endif
     for (child = mFrames.FirstChild(); child; child = child->GetNextSibling()) {
       MoveChildTo(this, child, child->GetPosition() + nsPoint(deltaX, 0));
-      ConsiderChildOverflow(overflowRect, child);
+      ConsiderChildOverflow(overflowRects, child);
       contentRect.UnionRect(contentRect, child->GetRect());
     }
   }
   aColData.mMaxHeight = contentBottom;
   contentRect.height = NS_MAX(contentRect.height, contentBottom);
   mLastFrameStatus = aStatus;
   
   // contentRect included the borderPadding.left,borderPadding.top of the child rects
@@ -842,19 +842,19 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
     if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinWidth) {
       contentSize.width = NS_MAX(aReflowState.mComputedMinWidth, contentSize.width);
     }
   }
     
   aDesiredSize.height = borderPadding.top + contentSize.height +
     borderPadding.bottom;
   aDesiredSize.width = contentSize.width + borderPadding.left + borderPadding.right;
-  overflowRect.UnionRect(overflowRect, nsRect(0, 0, aDesiredSize.width, aDesiredSize.height));
-  aDesiredSize.mOverflowArea = overflowRect;
-  
+  aDesiredSize.mOverflowAreas = overflowRects;
+  aDesiredSize.UnionOverflowAreasWithDesiredBounds();
+
 #ifdef DEBUG_roc
   printf("*** DONE PASS feasible=%d\n", allFit && NS_FRAME_IS_FULLY_COMPLETE(aStatus)
          && !NS_FRAME_IS_TRUNCATED(aStatus));
 #endif
   return allFit && NS_FRAME_IS_FULLY_COMPLETE(aStatus)
     && !NS_FRAME_IS_TRUNCATED(aStatus);
 }
 
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -825,34 +825,33 @@ nsContainerFrame::FinishReflowChild(nsIF
 
   aKidFrame->SetRect(bounds);
 
   if (aKidFrame->HasView()) {
     nsIView* view = aKidFrame->GetView();
     // Make sure the frame's view is properly sized and positioned and has
     // things like opacity correct
     SyncFrameViewAfterReflow(aPresContext, aKidFrame, view,
-                             &aDesiredSize.mOverflowArea,
-                             aFlags);
+                             aDesiredSize.VisualOverflow(), aFlags);
   }
 
   if (!(aFlags & NS_FRAME_NO_MOVE_VIEW) &&
       (curOrigin.x != aX || curOrigin.y != aY)) {
     if (!aKidFrame->HasView()) {
       // If the frame has moved, then we need to make sure any child views are
       // correctly positioned
       PositionChildViews(aKidFrame);
     }
 
     // We also need to redraw everything associated with the frame
     // because if the frame's Reflow issued any invalidates, then they
     // will be at the wrong offset ... note that this includes
     // invalidates issued against the frame's children, so we need to
     // invalidate the overflow area too.
-    aKidFrame->Invalidate(aDesiredSize.mOverflowArea);
+    aKidFrame->Invalidate(aDesiredSize.VisualOverflow());
   }
 
   return aKidFrame->DidReflow(aPresContext, aReflowState, NS_FRAME_REFLOW_FINISHED);
 }
 
 nsresult
 nsContainerFrame::ReflowOverflowContainerChildren(nsPresContext*           aPresContext,
                                                   const nsHTMLReflowState& aReflowState,
@@ -943,17 +942,17 @@ nsContainerFrame::ReflowOverflowContaine
 
       // Invalidate if there was a position or size change
       nsRect rect = frame->GetRect();
       if (rect != oldRect) {
         nsRect dirtyRect = oldOverflow;
         dirtyRect.MoveBy(oldRect.x, oldRect.y);
         Invalidate(dirtyRect);
 
-        dirtyRect = frame->GetOverflowRect();
+        dirtyRect = frame->GetVisualOverflowRect();
         dirtyRect.MoveBy(rect.x, rect.y);
         Invalidate(dirtyRect);
       }
 
       // Handle continuations
       if (!NS_FRAME_IS_FULLY_COMPLETE(frameStatus)) {
         if (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
           // Abspos frames can't cause their parent to be incomplete,
--- a/layout/generic/nsFirstLetterFrame.cpp
+++ b/layout/generic/nsFirstLetterFrame.cpp
@@ -244,19 +244,18 @@ nsFirstLetterFrame::Reflow(nsPresContext
   aMetrics.width += lr;
   aMetrics.height += tb;
   aMetrics.ascent += bp.top;
   mBaseline = aMetrics.ascent;
 
   // Ensure that the overflow rect contains the child textframe's overflow rect.
   // Note that if this is floating, the overline/underline drawable area is in
   // the overflow rect of the child textframe.
-  aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea,
-                           nsRect(0, 0, aMetrics.width, aMetrics.height));
-  ConsiderChildOverflow(aMetrics.mOverflowArea, kid);
+  aMetrics.UnionOverflowAreasWithDesiredBounds();
+  ConsiderChildOverflow(aMetrics.mOverflowAreas, kid);
 
   // Create a continuation or remove existing continuations based on
   // the reflow completion status.
   if (NS_FRAME_IS_COMPLETE(aReflowStatus)) {
     if (aReflowState.mLineLayout) {
       aReflowState.mLineLayout->SetFirstLetterStyleOK(PR_FALSE);
     }
     nsIFrame* kidNextInFlow = kid->GetNextInFlow();
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -4522,20 +4522,17 @@ nsFrame::IsFrameTreeTooDeep(const nsHTML
 {
   if (aReflowState.mReflowDepth >  MAX_FRAME_DEPTH) {
     mState |= NS_FRAME_TOO_DEEP_IN_FRAME_TREE;
     ClearOverflowRects();
     aMetrics.width = 0;
     aMetrics.height = 0;
     aMetrics.ascent = 0;
     aMetrics.mCarriedOutBottomMargin.Zero();
-    aMetrics.mOverflowArea.x = 0;
-    aMetrics.mOverflowArea.y = 0;
-    aMetrics.mOverflowArea.width = 0;
-    aMetrics.mOverflowArea.height = 0;
+    aMetrics.mOverflowAreas.Clear();
     return PR_TRUE;
   }
   mState &= ~NS_FRAME_TOO_DEEP_IN_FRAME_TREE;
   return PR_FALSE;
 }
 
 /* virtual */ PRBool nsFrame::IsContainingBlock() const
 {
@@ -6820,18 +6817,19 @@ nsFrame::DoLayout(nsBoxLayoutState& aSta
       // ensure our size is what we think is should be. Someone could have
       // reset the frame to be smaller or something dumb like that. 
       SetSize(nsSize(ourRect.width, ourRect.height));
     }
   }
 
   // Should we do this if IsCollapsed() is true?
   nsSize size(GetSize());
-  desiredSize.mOverflowArea.UnionRect(desiredSize.mOverflowArea,
-                                      nsRect(nsPoint(0, 0), size));
+  desiredSize.width = size.width;
+  desiredSize.height = size.height;
+  desiredSize.UnionOverflowAreasWithDesiredBounds();
   FinishAndStoreOverflow(desiredSize.mOverflowAreas, size);
 
   SyncLayout(aState);
 
   return rv;
 }
 
 nsresult
--- a/layout/generic/nsFrameSetFrame.cpp
+++ b/layout/generic/nsFrameSetFrame.cpp
@@ -1227,18 +1227,17 @@ nsHTMLFramesetFrame::Reflow(nsPresContex
     mChildTypes = nsnull;
     mChildFrameborder = nsnull;
     mChildBorderColors = nsnull;
   }
 
   aStatus = NS_FRAME_COMPLETE;
   mDrag.UnSet();
 
-  aDesiredSize.mOverflowArea = nsRect(0, 0,
-                                      aDesiredSize.width, aDesiredSize.height);
+  aDesiredSize.SetOverflowAreasToDesiredBounds();
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 nsIAtom*
 nsHTMLFramesetFrame::GetType() const
 {
@@ -1604,18 +1603,17 @@ nsHTMLFramesetBorderFrame::Reflow(nsPres
 {
   DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBorderFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
 
   // Override Reflow(), since we don't want to deal with what our
   // computed values are.
   SizeToAvailSize(aReflowState, aDesiredSize);
 
-  aDesiredSize.mOverflowArea = nsRect(0, 0,
-                                      aDesiredSize.width, aDesiredSize.height);
+  aDesiredSize.SetOverflowAreasToDesiredBounds();
   aStatus = NS_FRAME_COMPLETE;
   return NS_OK;
 }
 
 class nsDisplayFramesetBorder : public nsDisplayItem {
 public:
   nsDisplayFramesetBorder(nsDisplayListBuilder* aBuilder,
                           nsHTMLFramesetBorderFrame* aFrame)
@@ -1811,18 +1809,17 @@ nsHTMLFramesetBlankFrame::Reflow(nsPresC
                                  nsReflowStatus&          aStatus)
 {
   DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBlankFrame");
 
   // Override Reflow(), since we don't want to deal with what our
   // computed values are.
   SizeToAvailSize(aReflowState, aDesiredSize);
 
-  aDesiredSize.mOverflowArea = nsRect(0, 0,
-                                      aDesiredSize.width, aDesiredSize.height);
+  aDesiredSize.SetOverflowAreasToDesiredBounds();
   aStatus = NS_FRAME_COMPLETE;
   return NS_OK;
 }
 
 class nsDisplayFramesetBlank : public nsDisplayItem {
 public:
   nsDisplayFramesetBlank(nsDisplayListBuilder* aBuilder,
                          nsIFrame* aFrame) :
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -526,18 +526,17 @@ nsHTMLScrollFrame::ReflowScrolledFrame(S
 
   // XXX Some frames (e.g., nsObjectFrame, nsFrameFrame, nsTextFrame) don't bother
   // setting their mOverflowArea. This is wrong because every frame should
   // always set mOverflowArea. In fact nsObjectFrame and nsFrameFrame don't
   // support the 'outline' property because of this. Rather than fix the world
   // right now, just fix up the overflow area if necessary. Note that we don't
   // check HasOverflowRect() because it could be set even though the
   // overflow area doesn't include the frame bounds.
-  aMetrics->mOverflowArea.UnionRect(aMetrics->mOverflowArea,
-                                    nsRect(0, 0, aMetrics->width, aMetrics->height));
+  aMetrics->UnionOverflowAreasWithDesiredBounds();
 
   aState->mContentsOverflowArea = aMetrics->mOverflowArea;
   aState->mReflowedContentsWithHScrollbar = aAssumeHScroll;
   aState->mReflowedContentsWithVScrollbar = aAssumeVScroll;
   
   return rv;
 }
 
@@ -705,17 +704,17 @@ nsHTMLScrollFrame::PlaceScrollArea(const
   // Note that making the view *exactly* the size of the scrolled area
   // is critical, since the view scrolling code uses the size of the
   // scrolled view to clamp scroll requests.
   // Normally the scrolledFrame won't have a view but in some cases it
   // might create its own.
   nsContainerFrame::SyncFrameViewAfterReflow(scrolledFrame->PresContext(),
                                              scrolledFrame,
                                              scrolledFrame->GetView(),
-                                             &scrolledArea,
+                                             scrolledArea,
                                              0);
 }
 
 nscoord
 nsHTMLScrollFrame::GetIntrinsicVScrollbarWidth(nsIRenderingContext *aRenderingContext)
 {
   nsGfxScrollFrameInner::ScrollbarStyles ss = GetScrollbarStyles();
   if (ss.mVertical != NS_STYLE_OVERFLOW_SCROLL || !mInner.mVScrollbarBox)
@@ -853,17 +852,17 @@ nsHTMLScrollFrame::Reflow(nsPresContext*
     }
   }
 
   aDesiredSize.width = state.mInsideBorderSize.width +
     state.mComputedBorder.LeftRight();
   aDesiredSize.height = state.mInsideBorderSize.height +
     state.mComputedBorder.TopBottom();
 
-  aDesiredSize.mOverflowArea = nsRect(0, 0, aDesiredSize.width, aDesiredSize.height);
+  aDesiredSize.SetOverflowAreasToDesiredBounds();
 
   CheckInvalidateSizeChange(aDesiredSize);
 
   FinishAndStoreOverflow(&aDesiredSize);
 
   if (!InInitialReflow() && !mInner.mHadNonInitialReflow) {
     mInner.mHadNonInitialReflow = PR_TRUE;
   }
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -204,17 +204,17 @@ nsHTMLCanvasFrame::Reflow(nsPresContext*
   aMetrics.height += mBorderPadding.top + mBorderPadding.bottom;
 
   if (GetPrevInFlow()) {
     nscoord y = GetContinuationOffset(&aMetrics.width);
     aMetrics.height -= y + mBorderPadding.top;
     aMetrics.height = NS_MAX(0, aMetrics.height);
   }
 
-  aMetrics.mOverflowArea.SetRect(0, 0, aMetrics.width, aMetrics.height);
+  aMetrics.SetOverflowAreasToDesiredBounds();
   FinishAndStoreOverflow(&aMetrics);
 
   if (mRect.width != aMetrics.width || mRect.height != aMetrics.height) {
     Invalidate(nsRect(0, 0, mRect.width, mRect.height));
   }
 
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                   ("exit nsHTMLCanvasFrame::Reflow: size=%d,%d",
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -852,17 +852,17 @@ nsImageFrame::Reflow(nsPresContext*     
       NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight && 
       aMetrics.height > aReflowState.availableHeight) { 
     // our desired height was greater than 0, so to avoid infinite
     // splitting, use 1 pixel as the min
     aMetrics.height = NS_MAX(nsPresContext::CSSPixelsToAppUnits(1), aReflowState.availableHeight);
     aStatus = NS_FRAME_NOT_COMPLETE;
   }
 
-  aMetrics.mOverflowArea.SetRect(0, 0, aMetrics.width, aMetrics.height);
+  aMetrics.SetOverflowAreasToDesiredBounds();
   FinishAndStoreOverflow(&aMetrics);
 
   // Now that that's all done, check whether we're resizing... if we are,
   // invalidate our rect.
   // XXXbz we really only want to do this when reflow is completely done, but
   // we have no way to detect when mRect changes (since SetRect is non-virtual,
   // so this is the best we can do).
   if (mRect.width != aMetrics.width || mRect.height != aMetrics.height) {
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -674,17 +674,17 @@ nsInlineFrame::ReflowFrames(nsPresContex
     aMetrics.ascent = aMetrics.height = 0;
   }
   aMetrics.ascent += aReflowState.mComputedBorderPadding.top;
   aMetrics.height += aReflowState.mComputedBorderPadding.top +
     aReflowState.mComputedBorderPadding.bottom;
 
   // For now our overflow area is zero. The real value will be
   // computed in |nsLineLayout::RelativePositionFrames|.
-  aMetrics.mOverflowArea.SetRect(0, 0, 0, 0);
+  aMetrics.mOverflowAreas.Clear();
 
 #ifdef NOISY_FINAL_SIZE
   ListTag(stdout);
   printf(": metrics=%d,%d ascent=%d\n",
          aMetrics.width, aMetrics.height, aMetrics.ascent);
 #endif
 
   return rv;
--- a/layout/generic/nsLeafFrame.cpp
+++ b/layout/generic/nsLeafFrame.cpp
@@ -115,19 +115,18 @@ nsLeafFrame::DoReflow(nsPresContext* aPr
   AddBordersAndPadding(aReflowState, aMetrics);
   aStatus = NS_FRAME_COMPLETE;
 
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                  ("exit nsLeafFrame::DoReflow: size=%d,%d",
                   aMetrics.width, aMetrics.height));
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
 
-  aMetrics.mOverflowArea =
-    nsRect(0, 0, aMetrics.width, aMetrics.height);
-  
+  aMetrics.SetOverflowAreasToDesiredBounds();
+
   return NS_OK;
 }
 
 nscoord
 nsLeafFrame::GetIntrinsicHeight()
 {
   NS_NOTREACHED("Someone didn't override Reflow or ComputeAutoSize");
   return 0;
@@ -144,12 +143,11 @@ nsLeafFrame::AddBordersAndPadding(const 
 }
 
 void
 nsLeafFrame::SizeToAvailSize(const nsHTMLReflowState& aReflowState,
                              nsHTMLReflowMetrics& aDesiredSize)
 {
   aDesiredSize.width  = aReflowState.availableWidth; // FRAME
   aDesiredSize.height = aReflowState.availableHeight;
-  aDesiredSize.mOverflowArea =
-    nsRect(0, 0, aDesiredSize.width, aDesiredSize.height);
+  aDesiredSize.SetOverflowAreasToDesiredBounds();
   FinishAndStoreOverflow(&aDesiredSize);  
 }
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -934,17 +934,17 @@ nsObjectFrame::Reflow(nsPresContext*    
                       const nsHTMLReflowState& aReflowState,
                       nsReflowStatus&          aStatus)
 {
   DO_GLOBAL_REFLOW_COUNT("nsObjectFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
 
   // Get our desired size
   GetDesiredSize(aPresContext, aReflowState, aMetrics);
-  aMetrics.mOverflowArea.SetRect(0, 0, aMetrics.width, aMetrics.height);
+  aMetrics.SetOverflowAreasToDesiredBounds();
   FinishAndStoreOverflow(&aMetrics);
 
   // delay plugin instantiation until all children have
   // arrived. Otherwise there may be PARAMs or other stuff that the
   // plugin needs to see that haven't arrived yet.
   if (!GetContent()->IsDoneAddingChildren()) {
     aStatus = NS_FRAME_COMPLETE;
     return NS_OK;
--- a/layout/generic/nsSimplePageSequence.cpp
+++ b/layout/generic/nsSimplePageSequence.cpp
@@ -160,18 +160,17 @@ nsSimplePageSequenceFrame::Reflow(nsPres
   aStatus = NS_FRAME_COMPLETE;  // we're always complete
 
   // Don't do incremental reflow until we've taught tables how to do
   // it right in paginated mode.
   if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
     // Return our desired size
     aDesiredSize.height  = mSize.height * PresContext()->GetPrintPreviewScale();
     aDesiredSize.width   = mSize.width * PresContext()->GetPrintPreviewScale();
-    aDesiredSize.mOverflowArea = nsRect(0, 0, aDesiredSize.width,
-                                        aDesiredSize.height);
+    aDesiredSize.SetOverflowAreasToDesiredBounds();
     FinishAndStoreOverflow(&aDesiredSize);
     return NS_OK;
   }
 
   PRBool isPrintPreview =
     aPresContext->Type() == nsPresContext::eContext_PrintPreview;
 
   // See if we can get a Print Settings from the Context
@@ -345,18 +344,17 @@ nsSimplePageSequenceFrame::Reflow(nsPres
 
   // Return our desired size
   // Adjustr the reflow size by PrintPreviewScale so the scrollbars end up the
   // correct size
   nscoord w = (x + availSize.width + deadSpaceGap);
   aDesiredSize.height  = y * PresContext()->GetPrintPreviewScale(); // includes page heights and dead space
   aDesiredSize.width   = w * PresContext()->GetPrintPreviewScale();
 
-  aDesiredSize.mOverflowArea = nsRect(0, 0, aDesiredSize.width,
-                                      aDesiredSize.height);
+  aDesiredSize.SetOverflowAreasToDesiredBounds();
   FinishAndStoreOverflow(&aDesiredSize);
 
   // cache the size so we can set the desired size 
   // for the other reflows that happen
   mSize.width  = w;
   mSize.height = y;
 
   NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus);
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -6691,17 +6691,17 @@ nsTextFrame::ReflowText(nsLineLayout& aL
     if (details) {
       AddStateBits(NS_FRAME_SELECTED_CONTENT);
       DestroySelectionDetails(details);
     } else {
       RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
     }
   }
 
-  Invalidate(aMetrics.mOverflowArea);
+  Invalidate(aMetrics.VisualOverflow());
 
 #ifdef NOISY_REFLOW
   ListTag(stdout);
   printf(": desiredSize=%d,%d(b=%d) status=%x\n",
          aMetrics.width, aMetrics.height, aMetrics.ascent,
          aStatus);
 #endif
 }
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -330,17 +330,17 @@ nsVideoFrame::Reflow(nsPresContext*     
       nsBoxFrame::LayoutChildAt(boxState,
                                 child,
                                 nsRect(mBorderPadding.left,
                                        mBorderPadding.top,
                                        aReflowState.ComputedWidth(),
                                        aReflowState.ComputedHeight()));
     }
   }
-  aMetrics.mOverflowArea.SetRect(0, 0, aMetrics.width, aMetrics.height);
+  aMetrics.SetOverflowAreasToDesiredBounds();
 
   FinishAndStoreOverflow(&aMetrics);
 
   if (mRect.width != aMetrics.width || mRect.height != aMetrics.height) {
     Invalidate(nsRect(0, 0, mRect.width, mRect.height));
   }
 
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
--- a/layout/generic/nsViewportFrame.cpp
+++ b/layout/generic/nsViewportFrame.cpp
@@ -331,18 +331,17 @@ ViewportFrame::Reflow(nsPresContext*    
 
   // If we were dirty then do a repaint
   if (GetStateBits() & NS_FRAME_IS_DIRTY) {
     nsRect damageRect(0, 0, aDesiredSize.width, aDesiredSize.height);
     Invalidate(damageRect);
   }
 
   // XXX Should we do something to clip our children to this?
-  aDesiredSize.mOverflowArea =
-    nsRect(nsPoint(0, 0), nsSize(aDesiredSize.width, aDesiredSize.height));
+  aDesiredSize.SetOverflowAreasToDesiredBounds();
 
   NS_FRAME_TRACE_REFLOW_OUT("ViewportFrame::Reflow", aStatus);
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return rv; 
 }
 
 nsIAtom*
 ViewportFrame::GetType() const
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -851,40 +851,45 @@ nsMathMLContainerFrame::AttributeChanged
   return NS_OK;
 }
 
 void
 nsMathMLContainerFrame::GatherAndStoreOverflow(nsHTMLReflowMetrics* aMetrics)
 {
   // nsIFrame::FinishAndStoreOverflow likes the overflow area to include the
   // frame rectangle.
-  nsRect frameRect(0, 0, aMetrics->width, aMetrics->height);
+  aMetrics->SetOverflowAreasToDesiredBounds();
 
   // Text-shadow overflows.
   if (PresContext()->CompatibilityMode() != eCompatibility_NavQuirks) {
+    nsRect frameRect(0, 0, aMetrics->width, aMetrics->height);
     nsRect shadowRect = nsLayoutUtils::GetTextShadowRectsUnion(frameRect, this);
-    frameRect.UnionRect(frameRect, shadowRect);
+    // shadows contribute only to visual overflow
+    nsRect& visOverflow = aMetrics->VisualOverflow();
+    visOverflow.UnionRect(visOverflow, shadowRect);
   }
 
   // All non-child-frame content such as nsMathMLChars (and most child-frame
   // content) is included in mBoundingMetrics.
   nsRect boundingBox(mBoundingMetrics.leftBearing,
                      aMetrics->ascent - mBoundingMetrics.ascent,
                      mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing,
                      mBoundingMetrics.ascent + mBoundingMetrics.descent);
 
-  aMetrics->mOverflowArea.UnionRect(frameRect, boundingBox);
+  // REVIEW: Maybe this should contribute only to visual overflow
+  // and not scrollable?
+  aMetrics->mOverflowAreas.UnionAllWith(boundingBox);
 
   // mBoundingMetrics does not necessarily include content of <mpadded>
   // elements whose mBoundingMetrics may not be representative of the true
   // bounds, and doesn't include the CSS2 outline rectangles of children, so
   // make such to include child overflow areas.
   nsIFrame* childFrame = mFrames.FirstChild();
   while (childFrame) {
-    ConsiderChildOverflow(aMetrics->mOverflowArea, childFrame);
+    ConsiderChildOverflow(aMetrics->mOverflowAreas, childFrame);
     childFrame = childFrame->GetNextSibling();
   }
 
   FinishAndStoreOverflow(aMetrics);
 }
 
 nsresult 
 nsMathMLContainerFrame::ReflowChild(nsIFrame*                aChildFrame,
--- a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp
+++ b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp
@@ -149,18 +149,17 @@ nsSVGForeignObjectFrame::Reflow(nsPresCo
                aReflowState.ComputedHeight() == GetSize().height,
                "reflow roots should be reflowed at existing size and "
                "svg.css should ensure we have no padding/border/margin");
 
   DoReflow();
 
   aDesiredSize.width = aReflowState.ComputedWidth();
   aDesiredSize.height = aReflowState.ComputedHeight();
-  aDesiredSize.mOverflowArea =
-    nsRect(0, 0, aReflowState.ComputedWidth(), aReflowState.ComputedHeight());
+  aDesiredSize.SetOverflowAreasToDesiredBounds();
   aStatus = NS_FRAME_COMPLETE;
 
   return NS_OK;
 }
 
 void
 nsSVGForeignObjectFrame::InvalidateInternal(const nsRect& aDamageRect,
                                             nscoord aX, nscoord aY,
--- a/layout/svg/base/src/nsSVGOuterSVGFrame.cpp
+++ b/layout/svg/base/src/nsSVGOuterSVGFrame.cpp
@@ -340,17 +340,17 @@ nsSVGOuterSVGFrame::Reflow(nsPresContext
                           aReflowState.mComputedBorderPadding.LeftRight();
   aDesiredSize.height = aReflowState.ComputedHeight() +
                           aReflowState.mComputedBorderPadding.TopBottom();
 
   NS_ASSERTION(!GetPrevInFlow(), "SVG can't currently be broken across pages.");
 
   // Make sure we scroll if we're too big:
   // XXX Use the bounding box of our descendants? (See bug 353460 comment 14.)
-  aDesiredSize.mOverflowArea.SetRect(0, 0, aDesiredSize.width, aDesiredSize.height);
+  aDesiredSize.SetOverflowAreasToDesiredBounds();
   FinishAndStoreOverflow(&aDesiredSize);
 
   // If our SVG viewport has changed, update our content and notify.
   // http://www.w3.org/TR/SVG11/coords.html#ViewportSpace
 
   svgFloatSize newViewportSize(
     nsPresContext::AppUnitsToFloatCSSPixels(aReflowState.ComputedWidth()),
     nsPresContext::AppUnitsToFloatCSSPixels(aReflowState.ComputedHeight()));
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -613,17 +613,17 @@ void nsTableCellFrame::VerticallyAlignCh
     nsContainerFrame::PositionChildViews(firstKid);
 
     // Invalidate new overflow rect
     firstKid->InvalidateFrameSubtree();
   }
   if (HasView()) {
     nsContainerFrame::SyncFrameViewAfterReflow(PresContext(), this,
                                                GetView(),
-                                               &desiredSize.mOverflowArea, 0);
+                                               desiredSize.VisualOverflow(), 0);
   }
 }
 
 // Per CSS 2.1, we map 'sub', 'super', 'text-top', 'text-bottom',
 // length, percentage, and calc() values to 'baseline'.
 PRUint8
 nsTableCellFrame::GetVerticalAlign() const
 {
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1819,17 +1819,17 @@ NS_METHOD nsTableFrame::Reflow(nsPresCon
       haveDesiredHeight = PR_TRUE;
 
       mutable_rs.mFlags.mSpecialHeightReflow = PR_FALSE;
     }
   }
   else {
     // Calculate the overflow area contribution from our children.
     for (nsIFrame* kid = GetFirstChild(nsnull); kid; kid = kid->GetNextSibling()) {
-      ConsiderChildOverflow(aDesiredSize.mOverflowArea, kid);
+      ConsiderChildOverflow(aDesiredSize.mOverflowAreas, kid);
     }
   }
 
   aDesiredSize.width = aReflowState.ComputedWidth() +
                        aReflowState.mComputedBorderPadding.LeftRight();
   if (!haveDesiredHeight) {
     CalcDesiredHeight(aReflowState, aDesiredSize);
   }
@@ -1847,21 +1847,21 @@ NS_METHOD nsTableFrame::Reflow(nsPresCon
   // make sure the table overflow area does include the table rect.
   nsRect tableRect(0, 0, aDesiredSize.width, aDesiredSize.height) ;
 
   if (!aReflowState.mStyleDisplay->IsTableClip()) {
     // collapsed border may leak out
     nsMargin bcMargin = GetExcludedOuterBCBorder();
     tableRect.Inflate(bcMargin);
   }
-  aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, tableRect);
+  aDesiredSize.mOverflowAreas.UnionAllWith(tableRect);
 
   if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
     // Fulfill the promise InvalidateFrame makes.
-    Invalidate(aDesiredSize.mOverflowArea);
+    Invalidate(aDesiredSize.VisualOverflow());
   } else {
     CheckInvalidateSizeChange(aDesiredSize);
   }
 
   FinishAndStoreOverflow(&aDesiredSize);
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return rv;
 }
@@ -2971,56 +2971,53 @@ nsTableFrame::CalcDesiredHeight(const ns
     if ((tableSpecifiedHeight > 0) &&
         (tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE) &&
         (tableSpecifiedHeight > desiredHeight)) {
       // proportionately distribute the excess height to unconstrained rows in each
       // unconstrained row group.
       DistributeHeightToRows(aReflowState, tableSpecifiedHeight - desiredHeight);
       // this might have changed the overflow area incorporate the childframe overflow area.
       for (nsIFrame* kidFrame = mFrames.FirstChild(); kidFrame; kidFrame = kidFrame->GetNextSibling()) {
-        ConsiderChildOverflow(aDesiredSize.mOverflowArea, kidFrame);
+        ConsiderChildOverflow(aDesiredSize.mOverflowAreas, kidFrame);
       }
       desiredHeight = tableSpecifiedHeight;
     }
   }
   aDesiredSize.height = desiredHeight;
 }
 
 static
 void ResizeCells(nsTableFrame& aTableFrame)
 {
   nsTableFrame::RowGroupArray rowGroups;
   aTableFrame.OrderRowGroups(rowGroups);
   nsHTMLReflowMetrics tableDesiredSize;
   nsRect tableRect = aTableFrame.GetRect();
   tableDesiredSize.width = tableRect.width;
   tableDesiredSize.height = tableRect.height;
-  tableDesiredSize.mOverflowArea = nsRect(0, 0, tableRect.width,
-                                          tableRect.height);
+  tableDesiredSize.SetOverflowAreasToDesiredBounds();
 
   for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
     nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
 
     nsRect rowGroupRect = rgFrame->GetRect();
     nsHTMLReflowMetrics groupDesiredSize;
     groupDesiredSize.width = rowGroupRect.width;
     groupDesiredSize.height = rowGroupRect.height;
-    groupDesiredSize.mOverflowArea = nsRect(0, 0, groupDesiredSize.width,
-                                      groupDesiredSize.height);
+    groupDesiredSize.SetOverflowAreasToDesiredBounds();
+
     nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
     while (rowFrame) {
       rowFrame->DidResize();
-      rgFrame->ConsiderChildOverflow(groupDesiredSize.mOverflowArea, rowFrame);
+      rgFrame->ConsiderChildOverflow(groupDesiredSize.mOverflowAreas, rowFrame);
       rowFrame = rowFrame->GetNextRow();
     }
     rgFrame->FinishAndStoreOverflow(&groupDesiredSize);
-    // make the coordinates of |desiredSize.mOverflowArea| incorrect
-    // since it's about to go away:
-    groupDesiredSize.mOverflowArea.MoveBy(rgFrame->GetPosition());
-    tableDesiredSize.mOverflowArea.UnionRect(tableDesiredSize.mOverflowArea, groupDesiredSize.mOverflowArea);
+    tableDesiredSize.mOverflowAreas.UnionWith(groupDesiredSize.mOverflowAreas +
+                                              rgFrame->GetPosition());
   }
   aTableFrame.FinishAndStoreOverflow(&tableDesiredSize);
 }
 
 void
 nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
                                      nscoord                  aAmount)
 {
--- a/layout/tables/nsTableOuterFrame.cpp
+++ b/layout/tables/nsTableOuterFrame.cpp
@@ -952,20 +952,20 @@ void
 nsTableOuterFrame::UpdateReflowMetrics(PRUint8              aCaptionSide,
                                        nsHTMLReflowMetrics& aMet,
                                        const nsMargin&      aInnerMargin,
                                        const nsMargin&      aCaptionMargin)
 {
   SetDesiredSize(aCaptionSide, aInnerMargin, aCaptionMargin,
                  aMet.width, aMet.height);
 
-  aMet.mOverflowArea = nsRect(0, 0, aMet.width, aMet.height);
-  ConsiderChildOverflow(aMet.mOverflowArea, mInnerTableFrame);
+  aMet.SetOverflowAreasToDesiredBounds();
+  ConsiderChildOverflow(aMet.mOverflowAreas, mInnerTableFrame);
   if (mCaptionFrame) {
-    ConsiderChildOverflow(aMet.mOverflowArea, mCaptionFrame);
+    ConsiderChildOverflow(aMet.mOverflowAreas, mCaptionFrame);
   }
   FinishAndStoreOverflow(&aMet);
 }
 
 NS_METHOD nsTableOuterFrame::Reflow(nsPresContext*           aPresContext,
                                     nsHTMLReflowMetrics&     aDesiredSize,
                                     const nsHTMLReflowState& aOuterRS,
                                     nsReflowStatus&          aStatus)
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -369,18 +369,17 @@ nsTableRowFrame::DidResize()
     return;
   
   nsTableIterator iter(*this);
   nsIFrame* childFrame = iter.First();
   
   nsHTMLReflowMetrics desiredSize;
   desiredSize.width = mRect.width;
   desiredSize.height = mRect.height;
-  desiredSize.mOverflowArea = nsRect(0, 0, desiredSize.width,
-                                     desiredSize.height);
+  desiredSize.SetOverflowAreasToDesiredBounds();
 
   while (childFrame) {
     nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
     if (cellFrame) {
       nscoord cellHeight = mRect.height + GetHeightOfRowsSpannedBelowFirst(*cellFrame, *tableFrame);
 
       // resize the cell's height
       nsRect cellRect = cellFrame->GetRect();
@@ -394,27 +393,28 @@ nsTableRowFrame::DidResize()
       }
 
       // realign cell content based on the new height.  We might be able to
       // skip this if the height didn't change... maybe.  Hard to tell.
       cellFrame->VerticallyAlignChild(mMaxCellAscent);
       
       // Always store the overflow, even if the height didn't change, since
       // we'll lose part of our overflow area otherwise.
-      ConsiderChildOverflow(desiredSize.mOverflowArea, cellFrame);
+      ConsiderChildOverflow(desiredSize.mOverflowAreas, cellFrame);
 
       // Note that if the cell's *content* needs to change in response
       // to this height, it will get a special height reflow.
     }
     // Get the next child
     childFrame = iter.Next();
   }
   FinishAndStoreOverflow(&desiredSize);
   if (HasView()) {
-    nsContainerFrame::SyncFrameViewAfterReflow(PresContext(), this, GetView(), &desiredSize.mOverflowArea, 0);
+    nsContainerFrame::SyncFrameViewAfterReflow(PresContext(), this, GetView(),
+                                               desiredSize.VisualOverflow(), 0);
   }
   // Let our base class do the usual work
 }
 
 // returns max-ascent amongst all cells that have 'vertical-align: baseline'
 // *including* cells with rowspans
 nscoord nsTableRowFrame::GetMaxCellAscent() const
 {
@@ -922,22 +922,18 @@ nsTableRowFrame::ReflowChildren(nsPresCo
       }
       else {
         if (x != kidRect.x) {
           kidFrame->InvalidateFrameSubtree();
         }
         
         desiredSize.width = cellDesiredSize.width;
         desiredSize.height = cellDesiredSize.height;
-        if (cellFrame->HasOverflowRect())
-          desiredSize.mOverflowArea = cellFrame->GetOverflowRect();
-        else
-          desiredSize.mOverflowArea.SetRect(0, 0, cellDesiredSize.width,
-                                            cellDesiredSize.height);
-        
+        desiredSize.mOverflowAreas = cellFrame->GetOverflowAreas();
+
         // if we are in a floated table, our position is not yet established, so we cannot reposition our views
         // the containing block will do this for us after positioning the table
         if (!aTableFrame.GetStyleDisplay()->IsFloating()) {
           // Because we may have moved the frame we need to make sure any views are
           // positioned properly. We have to do this, because any one of our parent
           // frames could have moved and we have no way of knowing...
           nsTableFrame::RePositionViews(kidFrame);
         }
@@ -988,17 +984,17 @@ nsTableRowFrame::ReflowChildren(nsPresCo
       }
       // we need to account for the cell's width even if it isn't reflowed
       x += kidRect.width;
 
       if (kidFrame->GetNextInFlow()) {
         aStatus = NS_FRAME_NOT_COMPLETE;
       }
     }
-    ConsiderChildOverflow(aDesiredSize.mOverflowArea, kidFrame);
+    ConsiderChildOverflow(aDesiredSize.mOverflowAreas, kidFrame);
     x += cellSpacingX;
   }
 
   // just set our width to what was available. The table will calculate the width and not use our value.
   aDesiredSize.width = aReflowState.availableWidth;
 
   if (aReflowState.mFlags.mSpecialHeightReflow) {
     aDesiredSize.height = mRect.height;
@@ -1025,18 +1021,17 @@ nsTableRowFrame::ReflowChildren(nsPresCo
     // height from our prev-in-flows from the style height)
     nscoord styleHeight = CalcHeightFromUnpaginatedHeight(aPresContext, *this);
     if (styleHeight > aReflowState.availableHeight) {
       styleHeight = aReflowState.availableHeight;
       NS_FRAME_SET_INCOMPLETE(aStatus);
     }
     aDesiredSize.height = NS_MAX(cellMaxHeight, styleHeight);
   }
-  nsRect rowRect(0, 0, aDesiredSize.width, aDesiredSize.height);
-  aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, rowRect);
+  aDesiredSize.UnionOverflowAreasWithDesiredBounds();
   FinishAndStoreOverflow(&aDesiredSize);
   return rv;
 }
 
 /** Layout the entire row.
   * This method stacks cells horizontally according to HTML 4.0 rules.
   */
 NS_METHOD
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -470,17 +470,17 @@ nsTableRowGroupFrame::ReflowChildren(nsP
       // Adjust the running y-offset so we know where the next row should be placed
       nscoord height = kidFrame->GetSize().height + cellSpacingY;
       aReflowState.y += height;
 
       if (NS_UNCONSTRAINEDSIZE != aReflowState.availSize.height) {
         aReflowState.availSize.height -= height;
       }
     }
-    ConsiderChildOverflow(aDesiredSize.mOverflowArea, kidFrame);
+    ConsiderChildOverflow(aDesiredSize.mOverflowAreas, kidFrame);
   }
 
   if (haveRow)
     aReflowState.y -= cellSpacingY;
 
   // Return our desired rect
   aDesiredSize.width = aReflowState.reflowState.availableWidth;
   aDesiredSize.height = aReflowState.y;
@@ -543,21 +543,21 @@ UpdateHeights(RowInfo& aRowInfo,
 }
 
 void 
 nsTableRowGroupFrame::DidResizeRows(nsHTMLReflowMetrics& aDesiredSize)
 {
   // update the cells spanning rows with their new heights
   // this is the place where all of the cells in the row get set to the height of the row
   // Reset the overflow area
-  aDesiredSize.mOverflowArea = nsRect(0, 0, 0, 0);
+  aDesiredSize.mOverflowAreas.Clear();
   for (nsTableRowFrame* rowFrame = GetFirstRow();
        rowFrame; rowFrame = rowFrame->GetNextRow()) {
     rowFrame->DidResize();
-    ConsiderChildOverflow(aDesiredSize.mOverflowArea, rowFrame);
+    ConsiderChildOverflow(aDesiredSize.mOverflowAreas, rowFrame);
   }
 }
 
 // This calculates the height of all the rows and takes into account 
 // style height on the row group, style heights on rows and cells, style heights on rowspans. 
 // Actual row heights will be adjusted later if the table has a style height.
 // Even if rows don't change height, this method must be called to set the heights of each
 // cell in the row to the height of its row.
@@ -1344,18 +1344,17 @@ nsTableRowGroupFrame::Reflow(nsPresConte
   }
 
   SetHasStyleHeight((NS_UNCONSTRAINEDSIZE != aReflowState.ComputedHeight()) &&
                     (aReflowState.ComputedHeight() > 0)); 
   
   // just set our width to what was available. The table will calculate the width and not use our value.
   aDesiredSize.width = aReflowState.availableWidth;
 
-  aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, nsRect(0, 0, aDesiredSize.width,
-	                                                                      aDesiredSize.height));
+  aDesiredSize.UnionOverflowAreasWithDesiredBounds();
 
   // If our parent is in initial reflow, it'll handle invalidating our
   // entire overflow rect.
   if (!(GetParent()->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
     CheckInvalidateSizeChange(aDesiredSize);
   }
   
   FinishAndStoreOverflow(&aDesiredSize);
--- a/layout/xul/base/src/nsBox.cpp
+++ b/layout/xul/base/src/nsBox.cpp
@@ -605,49 +605,50 @@ nsBox::SyncLayout(nsBoxLayoutState& aSta
 
   PRUint32 flags = 0;
   GetLayoutFlags(flags);
 
   PRUint32 stateFlags = aState.LayoutFlags();
 
   flags |= stateFlags;
 
-  nsRect rect(nsPoint(0, 0), GetSize());
+  nsRect visualOverflow;
 
   if (ComputesOwnOverflowArea()) {
-    rect = GetOverflowRect();
+    visualOverflow = GetVisualOverflowRect();
   }
   else {
+    nsRect rect(nsPoint(0, 0), GetSize());
+    nsOverflowAreas overflowAreas(rect, rect);
     if (!DoesClipChildren() && !IsCollapsed(aState)) {
       // See if our child frames caused us to overflow after being laid
       // out. If so, store the overflow area.  This normally can't happen
       // in XUL, but it can happen with the CSS 'outline' property and
       // possibly with other exotic stuff (e.g. relatively positioned
       // frames in HTML inside XUL).
-      nsIFrame* box = GetChildBox();
-      while (box) {
-        nsRect bounds = box->GetOverflowRect() + box->GetPosition();
-        rect.UnionRect(rect, bounds);
-
-        box = box->GetNextBox();
+      for (nsIFrame* kid = GetChildBox(); kid; kid = kid->GetNextBox()) {
+        nsOverflowAreas kidOverflow =
+          kid->GetOverflowAreas() + kid->GetPosition();
+        overflowAreas.UnionWith(kidOverflow);
       }
     }
 
-    FinishAndStoreOverflow(&rect, GetSize());
+    FinishAndStoreOverflow(overflowAreas, GetSize());
+    visualOverflow = overflowAreas.VisualOverflow();
   }
 
   nsIView* view = GetView();
   if (view) {
     // Make sure the frame's view is properly sized and positioned and has
     // things like opacity correct
     nsHTMLContainerFrame::SyncFrameViewAfterReflow(
                              presContext, 
                              this,
                              view,
-                             &rect,
+                             visualOverflow,
                              flags);
   } 
 
   return NS_OK;
 }
 
 nsresult
 nsIFrame::Redraw(nsBoxLayoutState& aState,
--- a/layout/xul/base/src/nsBoxFrame.cpp
+++ b/layout/xul/base/src/nsBoxFrame.cpp
@@ -754,17 +754,17 @@ nsBoxFrame::Reflow(nsPresContext*       
   if (!(mState & NS_STATE_IS_ROOT)) {
     ascent = GetBoxAscent(state);
   }
 
   aDesiredSize.width  = mRect.width;
   aDesiredSize.height = mRect.height;
   aDesiredSize.ascent = ascent;
 
-  aDesiredSize.mOverflowArea = GetOverflowRect();
+  aDesiredSize.mOverflowAreas = GetOverflowAreas();
 
 #ifdef DO_NOISY_REFLOW
   {
     printf("%p ** nsBF(done) W:%d H:%d  ", this, aDesiredSize.width, aDesiredSize.height);
 
     if (maxElementSize) {
       printf("MW:%d\n", *maxElementWidth); 
     } else {
--- a/layout/xul/base/src/nsLeafBoxFrame.cpp
+++ b/layout/xul/base/src/nsLeafBoxFrame.cpp
@@ -335,17 +335,17 @@ nsLeafBoxFrame::Reflow(nsPresContext*   
   Layout(state);
   
   // ok our child could have gotten bigger. So lets get its bounds
   aDesiredSize.width  = mRect.width;
   aDesiredSize.height = mRect.height;
   aDesiredSize.ascent = GetBoxAscent(state);
 
   // the overflow rect is set in SetBounds() above
-  aDesiredSize.mOverflowArea = GetOverflowRect();
+  aDesiredSize.mOverflowAreas = GetOverflowAreas();
 
 #ifdef DO_NOISY_REFLOW
   {
     printf("%p ** nsLBF(done) W:%d H:%d  ", this, aDesiredSize.width, aDesiredSize.height);
 
     if (maxElementWidth) {
       printf("MW:%d\n", *maxElementWidth); 
     } else {
--- a/layout/xul/base/src/nsListBoxBodyFrame.cpp
+++ b/layout/xul/base/src/nsListBoxBodyFrame.cpp
@@ -287,31 +287,32 @@ nsListBoxBodyFrame::DoLayout(nsBoxLayout
 {
   if (mScrolling)
     aBoxLayoutState.SetPaintingDisabled(PR_TRUE);
 
   nsresult rv = nsBoxFrame::DoLayout(aBoxLayoutState);
 
   // determine the real height for the scrollable area from the total number
   // of rows, since non-visible rows don't yet have frames
-  nsSize size = GetSize();
-  nsRect overflowRect = nsRect(nsPoint(0, 0), size);
+  nsRect rect(nsPoint(0, 0), GetSize());
+  nsOverflowAreas overflow(rect, rect);
   if (mLayoutManager) {
     nsIFrame* childFrame = mFrames.FirstChild();
     while (childFrame) {
-      ConsiderChildOverflow(overflowRect, childFrame);
+      ConsiderChildOverflow(overflow, childFrame);
       childFrame = childFrame->GetNextSibling();
     }
 
     nsSize prefSize = mLayoutManager->GetPrefSize(this, aBoxLayoutState);
-    if (prefSize.height > overflowRect.height) {
-      overflowRect.height = prefSize.height;
+    NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
+      nsRect& o = overflow.Overflow(otype);
+      o.height = NS_MAX(o.height, prefSize.height);
     }
   }
-  FinishAndStoreOverflow(&overflowRect, GetSize());
+  FinishAndStoreOverflow(overflow, GetSize());
 
   if (mScrolling)
     aBoxLayoutState.SetPaintingDisabled(PR_FALSE);
 
   // if we are scrolled and the row height changed
   // make sure we are scrolled to a correct index.
   if (mAdjustScroll)
      PostReflowCallback();