Bug 1079154 patch 5: convert callers of ApplyRelativePosition, ReflowChild and FinishReflowChild in layout/generic to the logical versions, r=jfkthame
authorSimon Montagu <smontagu@smontagu.org>
Tue, 06 Jan 2015 23:10:07 -0800
changeset 248195 0b2d6f002feea0a8ebb8f4b922c7b17a9fddac20
parent 248194 c16d59bb79d13ff7221511a13b134241dbdc7f44
child 248196 d2a2cdfc45ec6b2455ea9ad36c048a5f94fd2107
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1079154
milestone37.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 1079154 patch 5: convert callers of ApplyRelativePosition, ReflowChild and FinishReflowChild in layout/generic to the logical versions, r=jfkthame
layout/generic/nsBlockReflowContext.cpp
layout/generic/nsBlockReflowState.cpp
layout/generic/nsCanvasFrame.cpp
layout/generic/nsColumnSetFrame.cpp
layout/generic/nsContainerFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsLineLayout.cpp
--- a/layout/generic/nsBlockReflowContext.cpp
+++ b/layout/generic/nsBlockReflowContext.cpp
@@ -419,25 +419,23 @@ nsBlockReflowContext::PlaceBlock(const n
     }
   }
 
   aLine->SetBounds(mWritingMode,
                    mICoord, mBCoord - backupContainingBlockAdvance,
                    mMetrics.ISize(mWritingMode), mMetrics.BSize(mWritingMode),
                    mContainerWidth);
 
-  // XXX temporary until other classes are logicalized
-  nsPoint position = LogicalRect(mWritingMode,
-                                 mICoord, mBCoord,
-                                 mMetrics.ISize(mWritingMode),
-                                 mMetrics.BSize(mWritingMode)).
-                       GetPhysicalPosition(mWritingMode, mContainerWidth);
-
-  aReflowState.ApplyRelativePositioning(&position);
+  WritingMode frameWM = mFrame->GetWritingMode();
+  LogicalPoint logPos =
+    LogicalPoint(mWritingMode, mICoord, mBCoord).
+      ConvertTo(frameWM, mWritingMode, mContainerWidth - mMetrics.Width());
+  aReflowState.ApplyRelativePositioning(&logPos, mContainerWidth);
 
   // Now place the frame and complete the reflow process
   nsContainerFrame::FinishReflowChild(mFrame, mPresContext, mMetrics,
-                                      &aReflowState, position.x, position.y, 0);
+                                      &aReflowState, frameWM, logPos,
+                                      mContainerWidth, 0);
 
-  aOverflowAreas = mMetrics.mOverflowAreas + position;
+  aOverflowAreas = mMetrics.mOverflowAreas + mFrame->GetPosition();
 
   return true;
 }
--- a/layout/generic/nsBlockReflowState.cpp
+++ b/layout/generic/nsBlockReflowState.cpp
@@ -908,45 +908,37 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
       !aFloat->GetPrevInFlow()) {
     PushFloatPastBreak(aFloat);
     return false;
   }
 
   // Calculate the actual origin of the float frame's border rect
   // relative to the parent block; the margin must be added in
   // to get the border rect
-
-  //XXX temporary! ApplyRelativePositioning still uses physical margin and point
-  LogicalSize size = aFloat->GetLogicalSize(wm);
-  LogicalMargin margin = aFloat->GetLogicalUsedMargin(wm);
-  size.ISize(wm) += margin.IStartEnd(wm);
-  size.BSize(wm) += margin.BStartEnd(wm);
-  nsPoint physicalPos =
-    LogicalRect(wm, floatPos, size).GetPhysicalPosition(wm, mContainerWidth);
-  nsPoint origin(floatMargin.Left(wm) + physicalPos.x,
-                 floatMargin.Top(wm) + physicalPos.y);
+  LogicalPoint origin(wm, floatMargin.IStart(wm) + floatPos.I(wm),
+                      floatMargin.BStart(wm) + floatPos.B(wm));
 
   // If float is relatively positioned, factor that in as well
-  nsHTMLReflowState::ApplyRelativePositioning(aFloat,
-                                             floatOffsets.GetPhysicalMargin(wm),
-                                              &origin);
+  nsHTMLReflowState::ApplyRelativePositioning(aFloat, wm, floatOffsets,
+                                              &origin, mContainerWidth);
 
   // Position the float and make sure and views are properly
   // positioned. We need to explicitly position its child views as
   // well, since we're moving the float after flowing it.
-  bool moved = aFloat->GetPosition() != origin;
+  bool moved = aFloat->GetLogicalPosition(wm, mContainerWidth) != origin;
   if (moved) {
-    aFloat->SetPosition(origin);
+    aFloat->SetPosition(wm, origin, mContainerWidth);
     nsContainerFrame::PositionFrameView(aFloat);
     nsContainerFrame::PositionChildViews(aFloat);
   }
 
   // Update the float combined area state
   // XXX Floats should really just get invalidated here if necessary
-  mFloatOverflowAreas.UnionWith(aFloat->GetOverflowAreas() + origin);
+  mFloatOverflowAreas.UnionWith(aFloat->GetOverflowAreas() +
+                                aFloat->GetPosition());
 
   // Place the float in the float manager
   // calculate region
   LogicalRect region =
     nsFloatManager::CalculateRegionFor(wm, aFloat, floatMargin,
                                        mContainerWidth);
   // if the float split, then take up all of the vertical height
   if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus) &&
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -597,28 +597,32 @@ nsCanvasFrame::Reflow(nsPresContext*    
 
     if (aReflowState.IsVResize() &&
         (kidFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT)) {
       // Tell our kid it's being vertically resized too.  Bit of a
       // hack for framesets.
       kidReflowState.SetVResize(true);
     }
 
-    nsPoint kidPt(kidReflowState.ComputedPhysicalMargin().left,
-                  kidReflowState.ComputedPhysicalMargin().top);
+    WritingMode wm = aReflowState.GetWritingMode();
+    WritingMode kidWM = kidReflowState.GetWritingMode();
+    nscoord containerWidth = aReflowState.ComputedWidth();
 
-    kidReflowState.ApplyRelativePositioning(&kidPt);
+    LogicalMargin margin = kidReflowState.ComputedLogicalMargin();
+    LogicalPoint kidPt(kidWM, margin.IStart(kidWM), margin.BStart(kidWM));
+
+    kidReflowState.ApplyRelativePositioning(&kidPt, containerWidth);
 
     // Reflow the frame
     ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState,
-                kidPt.x, kidPt.y, 0, aStatus);
+                kidWM, kidPt, containerWidth, 0, aStatus);
 
     // Complete the reflow and position and size the child frame
     FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, &kidReflowState,
-                      kidPt.x, kidPt.y, 0);
+                      kidWM, kidPt, containerWidth, 0);
 
     if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
       nsIFrame* nextFrame = kidFrame->GetNextInFlow();
       NS_ASSERTION(nextFrame || aStatus & NS_FRAME_REFLOW_NEXTINFLOW,
         "If it's incomplete and has no nif yet, it must flag a nif reflow.");
       if (!nextFrame) {
         nextFrame = aPresContext->PresShell()->FrameConstructor()->
           CreateContinuingFrame(aPresContext, kidFrame, this);
@@ -646,30 +650,29 @@ nsCanvasFrame::Reflow(nsPresContext*    
       // which doesn't need to be painted.
       nsIFrame* viewport = PresContext()->GetPresShell()->GetRootFrame();
       viewport->InvalidateFrame();
     }
     
     // Return our desired size. Normally it's what we're told, but
     // sometimes we can be given an unconstrained height (when a window
     // is sizing-to-content), and we should compute our desired height.
-    WritingMode wm = aReflowState.GetWritingMode();
     LogicalSize finalSize(wm);
     finalSize.ISize(wm) = aReflowState.ComputedISize();
     if (aReflowState.ComputedBSize() == NS_UNCONSTRAINEDSIZE) {
       finalSize.BSize(wm) = kidFrame->GetLogicalSize(wm).BSize(wm) +
         kidReflowState.ComputedLogicalMargin().BStartEnd(wm);
     } else {
       finalSize.BSize(wm) = aReflowState.ComputedBSize();
     }
 
     aDesiredSize.SetSize(wm, finalSize);
     aDesiredSize.SetOverflowAreasToDesiredBounds();
     aDesiredSize.mOverflowAreas.UnionWith(
-      kidDesiredSize.mOverflowAreas + kidPt);
+      kidDesiredSize.mOverflowAreas + kidFrame->GetPosition());
   }
 
   if (prevCanvasFrame) {
     ReflowOverflowContainerChildren(aPresContext, aReflowState,
                                     aDesiredSize.mOverflowAreas, 0,
                                     aStatus);
   }
 
--- a/layout/generic/nsColumnSetFrame.cpp
+++ b/layout/generic/nsColumnSetFrame.cpp
@@ -354,23 +354,24 @@ nsColumnSetFrame::ReflowColumns(nsHTMLRe
     feasible = ReflowChildren(aDesiredSize, aReflowState, aReflowStatus,
                               aConfig, aLastColumnUnbounded,
                               aCarriedOutBEndMargin, aColData);
   }
 
   return feasible;
 }
 
-static void MoveChildTo(nsIFrame* aParent, nsIFrame* aChild, nsPoint aOrigin)
+static void MoveChildTo(nsIFrame* aChild, LogicalPoint aOrigin,
+                        WritingMode aWM, nscoord aContainerWidth)
 {
-  if (aChild->GetPosition() == aOrigin) {
+  if (aChild->GetLogicalPosition(aWM, aContainerWidth) == aOrigin) {
     return;
   }
 
-  aChild->SetPosition(aOrigin);
+  aChild->SetPosition(aWM, aOrigin, aContainerWidth);
   nsContainerFrame::PlaceFrameView(aChild);
 }
 
 nscoord
 nsColumnSetFrame::GetMinISize(nsRenderingContext *aRenderingContext)
 {
   nscoord iSize = 0;
   DISPLAY_MIN_WIDTH(this, iSize);
@@ -480,32 +481,39 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
   // get our border and padding
   LogicalMargin borderPadding = aReflowState.ComputedLogicalBorderPadding();
   borderPadding.ApplySkipSides(GetLogicalSkipSides(&aReflowState));
 
   nsRect contentRect(0, 0, 0, 0);
   nsOverflowAreas overflowRects;
 
   nsIFrame* child = mFrames.FirstChild();
-  nsMargin physicalBP = borderPadding.GetPhysicalMargin(wm);
-  nsPoint childOrigin(physicalBP.left, physicalBP.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& childOriginICoord = isVertical ? childOrigin.y : childOrigin.x;
-  if (isRTL) {
+  LogicalPoint childOrigin(wm, borderPadding.IStart(wm),
+                           borderPadding.BStart(wm));
+  // In vertical-rl mode we can't use the computed width as the
+  // container width because it may be NS_UNCONSTRAINEDSIZE, so we use 0
+  // for now and reposition the columns after reflowing them all.
+  nscoord containerWidth = wm.IsVerticalRL() ? 0 : aReflowState.ComputedWidth();
+
+  // For RTL, 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
+
+  // XXX when all of layout is converted to logical coordinates, we
+  //     probably won't need to do this hack any more. For now, we
+  //     confine it to the legacy horizontal-rl case
+  if (!isVertical && isRTL) {
     nscoord availISize = aReflowState.AvailableISize();
     if (aReflowState.ComputedISize() != NS_INTRINSICSIZE) {
       availISize = aReflowState.ComputedISize();
     }
     if (availISize != NS_INTRINSICSIZE) {
-      childOriginICoord += availISize - aConfig.mColISize;
+      childOrigin.I(wm) = containerWidth - borderPadding.Left(wm) - availISize;
 #ifdef DEBUG_roc
-      printf("*** childOrigin.iCoord = %d\n", childOriginICoord);
+      printf("*** childOrigin.iCoord = %d\n", childOrigin.I(wm));
 #endif
     }
   }
 
   int columnCount = 0;
   int contentBEnd = 0;
   bool reflowNext = false;
 
@@ -554,17 +562,17 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
         NS_NOTREACHED("unknown block direction");
         break;
       }
     }
 
     nscoord childContentBEnd = 0;
     if (!reflowNext && (skipIncremental || skipResizeBSizeShrink)) {
       // This child does not need to be reflowed, but we may need to move it
-      MoveChildTo(this, child, childOrigin);
+      MoveChildTo(child, childOrigin, wm, containerWidth);
 
       // If this is the last frame then make sure we get the right status
       nsIFrame* kidNext = child->GetNextSibling();
       if (kidNext) {
         aStatus = (kidNext->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)
                   ? NS_FRAME_OVERFLOW_INCOMPLETE
                   : NS_FRAME_NOT_COMPLETE;
       } else {
@@ -616,35 +624,38 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
       // XXX it would be cool to consult the float manager for the
       // previous block to figure out the region of floats from the
       // previous column that extend into this column, and subtract
       // that region from the new float manager.  So you could stick a
       // really big float in the first column and text in following
       // columns would flow around it.
 
       // Reflow the frame
+      LogicalPoint origin(wm,
+                          childOrigin.I(wm) +
+                          kidReflowState.ComputedLogicalMargin().IStart(wm),
+                          childOrigin.B(wm) +
+                          kidReflowState.ComputedLogicalMargin().BStart(wm));
       ReflowChild(child, PresContext(), kidDesiredSize, kidReflowState,
-                  childOrigin.x + kidReflowState.ComputedPhysicalMargin().left,
-                  childOrigin.y + kidReflowState.ComputedPhysicalMargin().top,
-                  0, aStatus);
+                  wm, origin, containerWidth, 0, aStatus);
 
       reflowNext = (aStatus & NS_FRAME_REFLOW_NEXTINFLOW) != 0;
-    
+
 #ifdef DEBUG_roc
       printf("*** Reflowed child #%d %p: status = %d, desiredSize=%d,%d CarriedOutBEndMargin=%d\n",
              columnCount, (void*)child, aStatus, kidDesiredSize.Width(), kidDesiredSize.Height(),
              kidDesiredSize.mCarriedOutBEndMargin.get());
 #endif
 
       NS_FRAME_TRACE_REFLOW_OUT("Column::Reflow", aStatus);
 
       *aCarriedOutBEndMargin = kidDesiredSize.mCarriedOutBEndMargin;
 
       FinishReflowChild(child, PresContext(), kidDesiredSize,
-                        &kidReflowState, childOrigin.x, childOrigin.y, 0);
+                        &kidReflowState, wm, childOrigin, containerWidth, 0);
 
       childContentBEnd = nsLayoutUtils::CalculateContentBEnd(wm, child);
       if (childContentBEnd > aConfig.mColMaxBSize) {
         allFit = false;
       }
       if (childContentBEnd > availSize.BSize(wm)) {
         aColData.mMaxOverflowingBSize = std::max(childContentBEnd,
             aColData.mMaxOverflowingBSize);
@@ -727,24 +738,20 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
       // simplest (and probably fastest) thing.
       break;
     }
 
     // Advance to the next column
     child = child->GetNextSibling();
 
     if (child) {
-      if (isRTL) {
-        childOriginICoord -= aConfig.mColISize + aConfig.mColGap;
-      } else {
-        childOriginICoord += aConfig.mColISize + aConfig.mColGap;
-      }
+      childOrigin.I(wm) += aConfig.mColISize + aConfig.mColGap;
 
 #ifdef DEBUG_roc
-      printf("*** NEXT CHILD ORIGIN.iCoord = %d\n", childOriginICoord);
+      printf("*** NEXT CHILD ORIGIN.icoord = %d\n", childOrigin.I(wm));
 #endif
     }
   }
 
   if (PresContext()->CheckForInterrupt(this) &&
       (GetStateBits() & NS_FRAME_IS_DIRTY)) {
     // Mark all our kids starting with |child| dirty
 
@@ -759,31 +766,16 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
     }
   }
 
   aColData.mMaxBSize = contentBEnd;
   LogicalSize contentSize = LogicalSize(wm, contentRect.Size());
   contentSize.BSize(wm) = std::max(contentSize.BSize(wm), contentBEnd);
   mLastFrameStatus = aStatus;
 
-  // In vertical-rl mode, where we want the column "top" (right) edge to be
-  // aligned, we need to adjust the position of any short columns so as to
-  // make them flush-right instead of flush-left within the entire set.
-  if (wm.IsVerticalRL()) {
-    child = mFrames.FirstChild();
-    while (child) {
-      nscoord offset = aColData.mMaxBSize - child->GetRect().width;
-      if (offset) {
-        nsPoint childPos = child->GetPosition();
-        child->SetPosition(childPos + nsPoint(offset, 0));
-      }
-      child = child->GetNextSibling();
-    }
-  }
-
   // Apply computed and min/max values
   if (aConfig.mComputedBSize != NS_INTRINSICSIZE) {
     if (aReflowState.AvailableBSize() != NS_INTRINSICSIZE) {
       contentSize.BSize(wm) = std::min(contentSize.BSize(wm),
                                        aConfig.mComputedBSize);
     } else {
       contentSize.BSize(wm) = aConfig.mComputedBSize;
     }
@@ -805,16 +797,30 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
   }
 
   contentSize.ISize(wm) += borderPadding.IStartEnd(wm);
   contentSize.BSize(wm) += borderPadding.BStartEnd(wm);
   aDesiredSize.SetSize(wm, contentSize);
   aDesiredSize.mOverflowAreas = overflowRects;
   aDesiredSize.UnionOverflowAreasWithDesiredBounds();
 
+  // In vertical-rl mode, make a second pass to reposition the columns
+  // with the correct container width
+  if (wm.IsVerticalRL()) {
+    child = mFrames.FirstChild();
+    while (child) {
+      // Get the logical position as set before with containerWidth=0
+      // and reset with the correct container width (which is the block
+      // size in vertical modes).
+      child->SetPosition(wm, child->GetLogicalPosition(wm, 0),
+                         contentSize.BSize(wm));
+      child = child->GetNextSibling();
+    }
+  }
+
 #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
@@ -1238,34 +1238,36 @@ nsContainerFrame::ReflowOverflowContaine
     // even if the frame isn't dirty.
     if (shouldReflowAllKids || NS_SUBTREE_DIRTY(frame)) {
       // Get prev-in-flow
       nsIFrame* prevInFlow = frame->GetPrevInFlow();
       NS_ASSERTION(prevInFlow,
                    "overflow container frame must have a prev-in-flow");
       NS_ASSERTION(frame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER,
                    "overflow container frame must have overflow container bit set");
-      nsRect prevRect = prevInFlow->GetRect();
+      WritingMode wm = frame->GetWritingMode();
+      nscoord containerWidth = aReflowState.AvailableSize(wm).Width(wm);
+      LogicalRect prevRect = prevInFlow->GetLogicalRect(wm, containerWidth);
 
       // Initialize reflow params
-      WritingMode wm = frame->GetWritingMode();
-      LogicalSize availSpace(wm, LogicalSize(wm, prevRect.Size()).ISize(wm),
+      LogicalSize availSpace(wm, prevRect.ISize(wm),
                              aReflowState.AvailableSize(wm).BSize(wm));
       nsHTMLReflowMetrics desiredSize(aReflowState);
       nsHTMLReflowState frameState(aPresContext, aReflowState,
                                    frame, availSpace);
       nsReflowStatus frameStatus;
 
       // Reflow
+      LogicalPoint pos(wm, prevRect.IStart(wm), 0);
       ReflowChild(frame, aPresContext, desiredSize, frameState,
-                  prevRect.x, 0, aFlags, frameStatus, &tracker);
+                  wm, pos, containerWidth, aFlags, frameStatus, &tracker);
       //XXXfr Do we need to override any shrinkwrap effects here?
       // e.g. desiredSize.Width() = prevRect.width;
       FinishReflowChild(frame, aPresContext, desiredSize, &frameState,
-                        prevRect.x, 0, aFlags);
+                        wm, pos, containerWidth, aFlags);
 
       // 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,
           // only overflow incomplete.
           NS_FRAME_SET_OVERFLOW_INCOMPLETE(frameStatus);
         }
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -498,30 +498,33 @@ nsHTMLScrollFrame::ReflowScrolledFrame(S
   // Temporarily set mHasHorizontalScrollbar/mHasVerticalScrollbar to
   // reflect our assumptions while we reflow the child.
   bool didHaveHorizontalScrollbar = mHelper.mHasHorizontalScrollbar;
   bool didHaveVerticalScrollbar = mHelper.mHasVerticalScrollbar;
   mHelper.mHasHorizontalScrollbar = aAssumeHScroll;
   mHelper.mHasVerticalScrollbar = aAssumeVScroll;
 
   nsReflowStatus status;
+  // No need to pass a container-width to ReflowChild or
+  // FinishReflowChild, because it's only used there when positioning
+  // the frame (i.e. if NS_FRAME_NO_MOVE_FRAME isn't set)
   ReflowChild(mHelper.mScrolledFrame, presContext, *aMetrics,
-              kidReflowState, 0, 0,
+              kidReflowState, wm, LogicalPoint(wm), 0,
               NS_FRAME_NO_MOVE_FRAME, status);
 
   mHelper.mHasHorizontalScrollbar = didHaveHorizontalScrollbar;
   mHelper.mHasVerticalScrollbar = didHaveVerticalScrollbar;
 
   // Don't resize or position the view (if any) because we're going to resize
   // it to the correct size anyway in PlaceScrollArea. Allowing it to
   // resize here would size it to the natural height of the frame,
   // which will usually be different from the scrollport height;
   // invalidating the difference will cause unnecessary repainting.
   FinishReflowChild(mHelper.mScrolledFrame, presContext,
-                    *aMetrics, &kidReflowState, 0, 0,
+                    *aMetrics, &kidReflowState, wm, LogicalPoint(wm), 0,
                     NS_FRAME_NO_MOVE_FRAME | NS_FRAME_NO_SIZE_VIEW);
 
   // XXX Some frames (e.g., nsPluginFrame, nsFrameFrame, nsTextFrame) don't bother
   // setting their mOverflowArea. This is wrong because every frame should
   // always set mOverflowArea. In fact nsPluginFrame 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
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -3028,29 +3028,27 @@ nsLineLayout::RelativePositionFrames(Per
     // line and is sized to match the size of the line's bounding box
     // (the same size as the values returned from VerticalAlignFrames)
     overflowAreas.VisualOverflow() = rect.GetPhysicalRect(wm, mContainerWidth);
     overflowAreas.ScrollableOverflow() = overflowAreas.VisualOverflow();
   }
 
   for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) {
     nsIFrame* frame = pfd->mFrame;
-    nsPoint origin = frame->GetPosition();
 
     // Adjust the origin of the frame
     if (pfd->mRelativePos) {
-      //XXX temporary until ApplyRelativePositioning can handle logical offsets
-      nsMargin physicalOffsets =
-        pfd->mOffsets.GetPhysicalMargin(pfd->mFrame->GetWritingMode());
+      WritingMode frameWM = frame->GetWritingMode();
+      LogicalPoint origin = frame->GetLogicalPosition(mContainerWidth);
       // right and bottom are handled by
       // nsHTMLReflowState::ComputeRelativeOffsets
-      nsHTMLReflowState::ApplyRelativePositioning(pfd->mFrame,
-                                                  physicalOffsets,
-                                                  &origin);
-      frame->SetPosition(origin);
+      nsHTMLReflowState::ApplyRelativePositioning(frame, frameWM,
+                                                  pfd->mOffsets, &origin,
+                                                  mContainerWidth);
+      frame->SetPosition(frameWM, origin, mContainerWidth);
     }
 
     // We must position the view correctly before positioning its
     // descendants so that widgets are positioned properly (since only
     // some views have widgets).
     if (frame->HasView())
       nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, frame,
         frame->GetView(), pfd->mOverflowAreas.VisualOverflow(),
@@ -3094,17 +3092,17 @@ nsLineLayout::RelativePositionFrames(Per
     // below) so we get leaf frames as well.  No need to worry
     // about the root span, since it doesn't have a frame.
     if (frame->HasView())
       nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, frame,
                                                  frame->GetView(),
                                                  r.VisualOverflow(),
                                                  NS_FRAME_NO_MOVE_VIEW);
 
-    overflowAreas.UnionWith(r + origin);
+    overflowAreas.UnionWith(r + frame->GetPosition());
   }
 
   // If we just computed a spans combined area, we need to update its
   // overflow rect...
   if (psd != mRootSpan) {
     PerFrameData* spanPFD = psd->mFrame;
     nsIFrame* frame = spanPFD->mFrame;
     frame->FinishAndStoreOverflow(overflowAreas, frame->GetSize());