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 222403 0b2d6f002feea0a8ebb8f4b922c7b17a9fddac20
parent 222402 c16d59bb79d13ff7221511a13b134241dbdc7f44
child 222404 d2a2cdfc45ec6b2455ea9ad36c048a5f94fd2107
push id10683
push usercbook@mozilla.com
push dateWed, 07 Jan 2015 13:30:50 +0000
treeherderfx-team@3a1103c584cb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1079154
milestone37.0a1
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());