Bug 1143218 - Part 3: A better fix for bug 1105137 using line-left and line-right to place floats. r=jfkthame, a=sledru
authorSimon Montagu <smontagu@smontagu.org>
Sun, 22 Mar 2015 11:44:48 +0200
changeset 248544 16337cb1002a37cc3220eed2ad8bed6c4d8d987f
parent 248543 9d500d926e218825a3b42dbdfd882e0e4c448889
child 248545 5a3897ebc3d69a66e599c5f99af105fa358aa206
push id7858
push userryanvm@gmail.com
push dateMon, 30 Mar 2015 16:34:04 +0000
treeherdermozilla-aurora@8bc9656cad94 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame, sledru
bugs1143218, 1105137
milestone38.0a2
Bug 1143218 - Part 3: A better fix for bug 1105137 using line-left and line-right to place floats. r=jfkthame, a=sledru
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockReflowContext.cpp
layout/generic/nsBlockReflowState.cpp
layout/generic/nsBlockReflowState.h
layout/generic/nsFloatManager.cpp
layout/generic/nsFloatManager.h
layout/generic/nsLineLayout.cpp
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1935,25 +1935,20 @@ nsBlockFrame::PropagateFloatDamage(nsBlo
     WritingMode wm = aState.mReflowState.GetWritingMode();
     nscoord containerWidth = aState.ContainerWidth();
     LogicalRect overflow = aLine->GetOverflowArea(eScrollableOverflow, wm,
                                                   containerWidth);
     nscoord lineBCoordCombinedBefore = overflow.BStart(wm) + aDeltaBCoord;
     nscoord lineBCoordCombinedAfter = lineBCoordCombinedBefore +
                                       overflow.BSize(wm);
 
-    // "Translate" the float manager with an offset of (0, 0) in order to
-    // set the origin to our writing mode
-    LogicalPoint oPt(wm);
-    WritingMode oldWM = floatManager->Translate(wm, oPt, containerWidth);
     bool isDirty = floatManager->IntersectsDamage(wm, lineBCoordBefore,
                                                   lineBCoordAfter) ||
                    floatManager->IntersectsDamage(wm, lineBCoordCombinedBefore,
                                                   lineBCoordCombinedAfter);
-    floatManager->Untranslate(oldWM, oPt, containerWidth);
     if (isDirty) {
       aLine->MarkDirty();
       return;
     }
   }
 
   // Check if the line is moving relative to the float manager
   if (aDeltaBCoord + aState.mReflowState.mBlockDelta != 0) {
@@ -3340,18 +3335,17 @@ nsBlockFrame::ReflowBlockFrame(nsBlockRe
     // Reflow the block into the available space
     // construct the html reflow state for the block. ReflowBlock
     // will initialize it
     nsHTMLReflowState
       blockHtmlRS(aState.mPresContext, aState.mReflowState, frame,
                   availSpace.Size(wm).ConvertTo(frame->GetWritingMode(), wm));
     blockHtmlRS.mFlags.mHasClearance = aLine->HasClearance();
 
-    nsFloatManager::SavedState
-      floatManagerState(aState.mReflowState.GetWritingMode());
+    nsFloatManager::SavedState floatManagerState;
     if (mayNeedRetry) {
       blockHtmlRS.mDiscoveredClearance = &clearanceFrame;
       aState.mFloatManager->PushState(&floatManagerState);
     } else if (!applyBStartMargin) {
       blockHtmlRS.mDiscoveredClearance = aState.mReflowState.mDiscoveredClearance;
     }
 
     nsReflowStatus frameReflowStatus = NS_FRAME_COMPLETE;
@@ -3606,18 +3600,17 @@ nsBlockFrame::ReflowInlineFrames(nsBlock
   do {
     nscoord availableSpaceHeight = 0;
     do {
       bool allowPullUp = true;
       nsIFrame* forceBreakInFrame = nullptr;
       int32_t forceBreakOffset = -1;
       gfxBreakPriority forceBreakPriority = gfxBreakPriority::eNoBreak;
       do {
-        nsFloatManager::SavedState
-          floatManagerState(aState.mReflowState.GetWritingMode());
+        nsFloatManager::SavedState floatManagerState;
         aState.mReflowState.mFloatManager->PushState(&floatManagerState);
 
         // Once upon a time we allocated the first 30 nsLineLayout objects
         // on the stack, and then we switched to the heap.  At that time
         // these objects were large (1100 bytes on a 32 bit system).
         // Then the nsLineLayout object was shrunk to 156 bytes by
         // removing some internal buffers.  Given that it is so much
         // smaller, the complexity of 2 different ways of allocating
@@ -6208,20 +6201,23 @@ nsBlockFrame::RecoverFloatsFor(nsIFrame*
   nsBlockFrame* block = nsLayoutUtils::GetAsBlock(aFrame);
   // Don't recover any state inside a block that has its own space manager
   // (we don't currently have any blocks like this, though, thanks to our
   // use of extra frames for 'overflow')
   if (block && !nsBlockFrame::BlockNeedsFloatManager(block)) {
     // If the element is relatively positioned, then adjust x and y
     // accordingly so that we consider relatively positioned frames
     // at their original position.
-    LogicalPoint pos = block->GetLogicalNormalPosition(aWM, aContainerWidth);
-    WritingMode oldWM = aFloatManager.Translate(aWM, pos, aContainerWidth);
+
+    LogicalRect rect(aWM, block->GetNormalRect(), aContainerWidth);
+    nscoord lineLeft = rect.LineLeft(aWM, aContainerWidth);
+    nscoord blockStart = rect.BStart(aWM);
+    aFloatManager.Translate(lineLeft, blockStart);
     block->RecoverFloats(aFloatManager, aWM, aContainerWidth);
-    aFloatManager.Untranslate(oldWM, pos, aContainerWidth);
+    aFloatManager.Translate(-lineLeft, -blockStart);
   }
 }
 
 //////////////////////////////////////////////////////////////////////
 // Painting, event handling
 
 #ifdef DEBUG
 static void ComputeVisualOverflowArea(nsLineList& aLines,
--- a/layout/generic/nsBlockReflowContext.cpp
+++ b/layout/generic/nsBlockReflowContext.cpp
@@ -247,53 +247,57 @@ nsBlockReflowContext::ReflowBlock(const 
 
     // Adjust the available block size if it's constrained so that the
     // child frame doesn't think it can reflow into its margin area.
     if (NS_UNCONSTRAINEDSIZE != aFrameRS.AvailableBSize()) {
       aFrameRS.AvailableBSize() -= mBStartMargin.get() + aClearance;
     }
   }
 
-  LogicalPoint tPt(mWritingMode);
+  nscoord tI = 0, tB = 0;
   // The values of x and y do not matter for floats, so don't bother
   // calculating them. Floats are guaranteed to have their own float
   // manager, so tI and tB don't matter.  mICoord and mBCoord don't
   // matter becacuse they are only used in PlaceBlock, which is not used
   // for floats.
   if (aLine) {
     // Compute inline/block coordinate where reflow will begin. Use the
     // rules from 10.3.3 to determine what to apply. At this point in the
     // reflow auto inline-start/end margins will have a zero value.
 
     WritingMode frameWM = aFrameRS.GetWritingMode();
-    mICoord = tPt.I(mWritingMode) =
-      mSpace.IStart(mWritingMode) +
-      aFrameRS.ComputedLogicalMargin().ConvertTo(mWritingMode,
-                                                 frameWM).IStart(mWritingMode);
-    mBCoord = tPt.B(mWritingMode) = mSpace.BStart(mWritingMode) +
-                                    mBStartMargin.get() + aClearance;
+    LogicalMargin usedMargin =
+      aFrameRS.ComputedLogicalMargin().ConvertTo(mWritingMode, frameWM);
+    mICoord = mSpace.IStart(mWritingMode) + usedMargin.IStart(mWritingMode);
+    mBCoord = mSpace.BStart(mWritingMode) + mBStartMargin.get() + aClearance;
+
+    LogicalRect space(mWritingMode, mICoord, mBCoord,
+                      mSpace.ISize(mWritingMode) -
+                      usedMargin.IStartEnd(mWritingMode),
+                      mSpace.BSize(mWritingMode) -
+                      usedMargin.BStartEnd(mWritingMode));
+    tI = space.LineLeft(mWritingMode, mContainerWidth);
+    tB = mBCoord;
 
     if ((mFrame->GetStateBits() & NS_BLOCK_FLOAT_MGR) == 0)
       aFrameRS.mBlockDelta =
         mOuterReflowState.mBlockDelta + mBCoord - aLine->BStart();
   }
 
   // Let frame know that we are reflowing it
   mFrame->WillReflow(mPresContext);
 
 #ifdef DEBUG
   mMetrics.ISize(mWritingMode) = nscoord(0xdeadbeef);
   mMetrics.BSize(mWritingMode) = nscoord(0xdeadbeef);
 #endif
 
-  WritingMode oldWM =
-    mOuterReflowState.mFloatManager->Translate(mWritingMode, tPt,
-                                               mContainerWidth);
+  mOuterReflowState.mFloatManager->Translate(tI, tB);
   mFrame->Reflow(mPresContext, mMetrics, aFrameRS, aFrameReflowStatus);
-  mOuterReflowState.mFloatManager->Untranslate(oldWM, tPt, mContainerWidth);
+  mOuterReflowState.mFloatManager->Translate(-tI, -tB);
 
 #ifdef DEBUG
   if (!NS_INLINE_IS_BREAK_BEFORE(aFrameReflowStatus)) {
     if (CRAZY_SIZE(mMetrics.ISize(mWritingMode)) ||
         CRAZY_SIZE(mMetrics.BSize(mWritingMode))) {
       printf("nsBlockReflowContext: ");
       nsFrame::ListTag(stdout, mFrame);
       printf(" metrics=%d,%d!\n",
--- a/layout/generic/nsBlockReflowState.cpp
+++ b/layout/generic/nsBlockReflowState.cpp
@@ -33,18 +33,16 @@ nsBlockReflowState::nsBlockReflowState(c
                                        nsBlockFrame* aFrame,
                                        bool aBStartMarginRoot,
                                        bool aBEndMarginRoot,
                                        bool aBlockNeedsFloatManager,
                                        nscoord aConsumedBSize)
   : mBlock(aFrame),
     mPresContext(aPresContext),
     mReflowState(aReflowState),
-    mFloatManagerOrigin(aReflowState.GetWritingMode()),
-    mFloatManagerStateBefore(aReflowState.GetWritingMode()),
     mContentArea(aReflowState.GetWritingMode()),
     mPushedFloats(nullptr),
     mOverflowTracker(nullptr),
     mBorderPadding(mReflowState.ComputedLogicalBorderPadding()),
     mPrevBEndMargin(),
     mLineNumber(0),
     mFlags(0),
     mFloatBreakType(NS_STYLE_CLEAR_NONE),
@@ -101,17 +99,17 @@ nsBlockReflowState::nsBlockReflowState(c
   }
   
   mFloatManager = aReflowState.mFloatManager;
 
   NS_ASSERTION(mFloatManager,
                "FloatManager should be set in nsBlockReflowState" );
   if (mFloatManager) {
     // Save the coordinate system origin for later.
-    mFloatManager->GetTranslation(mFloatManagerWM, mFloatManagerOrigin);
+    mFloatManager->GetTranslation(mFloatManagerI, mFloatManagerB);
     mFloatManager->PushState(&mFloatManagerStateBefore); // never popped
   }
 
   mReflowStatus = NS_FRAME_COMPLETE;
 
   mNextInFlow = static_cast<nsBlockFrame*>(mBlock->GetNextInFlow());
 
   NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowState.ComputedISize(),
@@ -306,26 +304,21 @@ nsBlockReflowState::ComputeBlockAvailSpa
 nsFlowAreaRect
 nsBlockReflowState::GetFloatAvailableSpaceWithState(
                       nscoord aBCoord,
                       nsFloatManager::SavedState *aState) const
 {
   WritingMode wm = mReflowState.GetWritingMode();
 #ifdef DEBUG
   // Verify that the caller setup the coordinate system properly
-  WritingMode wWM;
-  LogicalPoint wPt(wWM);
-  mFloatManager->GetTranslation(wWM, wPt);
+  nscoord wI, wB;
+  mFloatManager->GetTranslation(wI, wB);
 
-  if (wWM == mFloatManagerWM) {
-    NS_ASSERTION(wPt == mFloatManagerOrigin, "bad coord system");
-  } else {
-    //XXX if the writing modes are different we can't easily assert that
-    //    the origin is the same.
-  }
+  NS_ASSERTION((wI == mFloatManagerI) && (wB == mFloatManagerB),
+               "bad coord system");
 #endif
 
   nscoord blockSize = (mContentArea.BSize(wm) == nscoord_MAX)
     ? nscoord_MAX : std::max(mContentArea.BEnd(wm) - aBCoord, 0);
   nsFlowAreaRect result =
     mFloatManager->GetFlowArea(wm, aBCoord, nsFloatManager::BAND_FROM_POINT,
                                blockSize, mContentArea, aState,
                                ContainerWidth());
@@ -348,25 +341,21 @@ nsBlockReflowState::GetFloatAvailableSpa
 nsFlowAreaRect
 nsBlockReflowState::GetFloatAvailableSpaceForBSize(
                       nscoord aBCoord, nscoord aBSize,
                       nsFloatManager::SavedState *aState) const
 {
   WritingMode wm = mReflowState.GetWritingMode();
 #ifdef DEBUG
   // Verify that the caller setup the coordinate system properly
-  WritingMode wWM;
-  LogicalPoint wPt(wWM);
-  mFloatManager->GetTranslation(wWM, wPt);
-  if (wWM == mFloatManagerWM) {
-    NS_ASSERTION(wPt == mFloatManagerOrigin, "bad coord system");
-  } else {
-    //XXX if the writing modes are different we can't easily assert that
-    //    the origin is the same.
-  }
+  nscoord wI, wB;
+  mFloatManager->GetTranslation(wI, wB);
+
+  NS_ASSERTION((wI == mFloatManagerI) && (wB == mFloatManagerB),
+               "bad coord system");
 #endif
   nsFlowAreaRect result =
     mFloatManager->GetFlowArea(wm, aBCoord, nsFloatManager::WIDTH_WITHIN_HEIGHT,
                                aBSize, mContentArea, aState, ContainerWidth());
   // Keep the width >= 0 for compatibility with nsSpaceManager.
   if (result.mRect.ISize(wm) < 0) {
     result.mRect.ISize(wm) = 0;
   }
@@ -464,41 +453,34 @@ nsBlockReflowState::AppendPushedFloatCha
  * incremental reflow O(N^2) and this state should really be kept
  * around, attached to the frame tree.
  */
 void
 nsBlockReflowState::RecoverFloats(nsLineList::iterator aLine,
                                   nscoord aDeltaBCoord)
 {
   WritingMode wm = mReflowState.GetWritingMode();
-  // "Translate" the float manager with an offset of (0, 0) in order to
-  // set the origin to our writing mode
-  LogicalPoint oPt(wm);
-  WritingMode oldWM = mFloatManager->Translate(wm, oPt, ContainerWidth());
   if (aLine->HasFloats()) {
     // Place the floats into the space-manager again. Also slide
     // them, just like the regular frames on the line.
     nsFloatCache* fc = aLine->GetFirstFloat();
     while (fc) {
       nsIFrame* floatFrame = fc->mFloat;
       if (aDeltaBCoord != 0) {
         floatFrame->MovePositionBy(nsPoint(0, aDeltaBCoord));
         nsContainerFrame::PositionFrameView(floatFrame);
         nsContainerFrame::PositionChildViews(floatFrame);
       }
 #ifdef DEBUG
       if (nsBlockFrame::gNoisyReflow || nsBlockFrame::gNoisyFloatManager) {
-        WritingMode tWM;
-        LogicalPoint tPt(tWM);
-        mFloatManager->GetTranslation(tWM, tPt);
+        nscoord tI, tB;
+        mFloatManager->GetTranslation(tI, tB);
         nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
-        printf("RecoverFloats: txy=%d,%d (%d,%d) ",
-               tPt.I(tWM), tPt.B(tWM),
-               mFloatManagerOrigin.I(mFloatManagerWM),
-               mFloatManagerOrigin.B(mFloatManagerWM));
+        printf("RecoverFloats: tIB=%d,%d (%d,%d) ",
+               tI, tB, mFloatManagerI, mFloatManagerB);
         nsFrame::ListTag(stdout, floatFrame);
         LogicalRect region = nsFloatManager::GetRegionFor(wm, floatFrame,
                                                           ContainerWidth());
         printf(" aDeltaBCoord=%d region={%d,%d,%d,%d}\n",
                aDeltaBCoord, region.IStart(wm), region.BStart(wm),
                region.ISize(wm), region.BSize(wm));
       }
 #endif
@@ -507,17 +489,16 @@ nsBlockReflowState::RecoverFloats(nsLine
                                                            ContainerWidth()),
                               wm, ContainerWidth());
       fc = fc->Next();
     }
   } else if (aLine->IsBlock()) {
     nsBlockFrame::RecoverFloatsFor(aLine->mFirstChild, *mFloatManager, wm,
                                    ContainerWidth());
   }
-  mFloatManager->Untranslate(oldWM, oPt, ContainerWidth());
 }
 
 /**
  * Everything done in this function is done O(N) times for each pass of
  * reflow so it is O(N*M) where M is the number of incremental reflow
  * passes.  That's bad.  Don't do stuff here.
  *
  * When this function is called, |aLine| has just been slid by |aDeltaBCoord|
@@ -593,20 +574,21 @@ nsBlockReflowState::AddFloat(nsLineLayou
     mBlock->mFloats.AppendFrame(mBlock, aFloat);
   }
 
   // Because we are in the middle of reflowing a placeholder frame
   // within a line (and possibly nested in an inline frame or two
   // that's a child of our block) we need to restore the space
   // manager's translation to the space that the block resides in
   // before placing the float.
-  WritingMode oldWM;
-  LogicalPoint oPt(oldWM);
-  mFloatManager->GetTranslation(oldWM, oPt);
-  mFloatManager->SetTranslation(mFloatManagerWM, mFloatManagerOrigin);
+  nscoord oI, oB;
+  mFloatManager->GetTranslation(oI, oB);
+  nscoord dI = oI - mFloatManagerI;
+  nscoord dB = oB - mFloatManagerB;
+  mFloatManager->Translate(-dI, -dB);
 
   bool placed;
 
   // Now place the float immediately if possible. Otherwise stash it
   // away in mPendingFloats and place it later.
   // If one or more floats has already been pushed to the next line,
   // don't let this one go on the current line, since that would violate
   // float ordering.
@@ -636,17 +618,17 @@ nsBlockReflowState::AddFloat(nsLineLayou
     // deal with this in PlaceBelowCurrentLineFloats
     placed = true;
     // This float will be placed after the line is done (it is a
     // below-current-line float).
     mBelowCurrentLineFloats.Append(mFloatCacheFreeList.Alloc(aFloat));
   }
 
   // Restore coordinate system
-  mFloatManager->SetTranslation(oldWM, oPt);
+  mFloatManager->Translate(dI, dB);
 
   return placed;
 }
 
 bool
 nsBlockReflowState::CanPlaceFloat(nscoord aFloatISize,
                                   const nsFlowAreaRect& aFloatAvailableSpace)
 {
@@ -703,22 +685,17 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
   const nsStyleDisplay* floatDisplay = aFloat->StyleDisplay();
 
   // The float's old region, so we can propagate damage.
   LogicalRect oldRegion = nsFloatManager::GetRegionFor(wm, aFloat,
                                                        ContainerWidth());
 
   // Enforce CSS2 9.5.1 rule [2], i.e., make sure that a float isn't
   // ``above'' another float that preceded it in the flow.
-  // "Translate" the float manager with an offset of (0, 0) in order to
-  // set the origin to our writing mode
-  LogicalPoint oPt(wm);
-  WritingMode oldWM = mFloatManager->Translate(wm, oPt, ContainerWidth());
-  mBCoord = std::max(mFloatManager->GetLowestFloatTop(wm, ContainerWidth()),
-                     mBCoord);
+  mBCoord = std::max(mFloatManager->GetLowestFloatTop(), mBCoord);
 
   // See if the float should clear any preceding floats...
   // XXX We need to mark this float somehow so that it gets reflowed
   // when floats are inserted before it.
   if (NS_STYLE_CLEAR_NONE != floatDisplay->mBreakType) {
     // XXXldb Does this handle vertical margins correctly?
     mBCoord = ClearFloats(mBCoord, floatDisplay->mBreakType);
   }
@@ -844,17 +821,19 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
     mustPlaceFloat = false;
   }
 
   // If the float is continued, it will get the same absolute x value as its prev-in-flow
 
   // We don't worry about the geometry of the prev in flow, let the continuation
   // place and size itself as required.
 
-  // Assign inline and block dir coordinates to the float.
+  // Assign inline and block dir coordinates to the float. We don't use
+  // LineLeft() and LineRight() here, because we would only have to
+  // convert the result back into this block's writing mode.
   LogicalPoint floatPos(wm);
   if ((NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) == wm.IsBidiLTR()) {
     floatPos.I(wm) = floatAvailableSpace.mRect.IStart(wm);
   }
   else {
     if (!keepFloatOnSameLine) {
       floatPos.I(wm) = floatAvailableSpace.mRect.IEnd(wm) - floatMarginISize;
     }
@@ -974,40 +953,35 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
 
   if (!NS_FRAME_IS_FULLY_COMPLETE(reflowStatus)) {
     mBlock->SplitFloat(*this, aFloat, reflowStatus);
   } else {
     MOZ_ASSERT(!aFloat->GetNextInFlow());
   }
 
 #ifdef NOISY_FLOATMANAGER
-  WritingMode tWM;
-  LogicalPoint tPt(wm);
-  mFloatManager->GetTranslation(tWM, tPt);
-  nsFrame::ListTag(stdout, mBlock);
-  printf(": FlowAndPlaceFloat: AddFloat: txy=%d,%d (%d,%d) {%d,%d,%d,%d}\n",
-         tPt.I(tWM), tPt.B(tWM),
-         mFloatManagerOrigin.I(mFloatManagerWM),
-         mFloatManagerOrigin.B(mFloatManagerWM),
+  nscoord tI, tB;
+  mFloatManager->GetTranslation(tI, tB);
+  nsIFrame::ListTag(stdout, mBlock);
+  printf(": FlowAndPlaceFloat: AddFloat: tIB=%d,%d (%d,%d) {%d,%d,%d,%d}\n",
+         tI, tB, mFloatManagerI, mFloatManagerB,
          region.IStart(wm), region.BStart(wm),
          region.ISize(wm), region.BSize(wm));
 #endif
 
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyReflow) {
     nsRect r = aFloat->GetRect();
     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
     printf("placed float: ");
     nsFrame::ListTag(stdout, aFloat);
     printf(" %d,%d,%d,%d\n", r.x, r.y, r.width, r.height);
   }
 #endif
 
-  mFloatManager->Untranslate(oldWM, oPt, ContainerWidth());
-
   return true;
 }
 
 void
 nsBlockReflowState::PushFloatPastBreak(nsIFrame *aFloat)
 {
   // This ensures that we:
   //  * don't try to place later but smaller floats (which CSS says
@@ -1080,18 +1054,17 @@ nsBlockReflowState::ClearFloats(nscoord 
   if (!mFloatManager->HasAnyFloats()) {
     return aBCoord;
   }
 
   nscoord newBCoord = aBCoord;
   WritingMode wm = mReflowState.GetWritingMode();
 
   if (aBreakType != NS_STYLE_CLEAR_NONE) {
-    newBCoord = mFloatManager->ClearFloats(wm, newBCoord, aBreakType,
-                                           ContainerWidth(), aFlags);
+    newBCoord = mFloatManager->ClearFloats(newBCoord, aBreakType, aFlags);
   }
 
   if (aReplacedBlock) {
     for (;;) {
       nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(newBCoord);
       if (!floatAvailableSpace.mHasFloats) {
         // If there aren't any floats here, then we always fit.
         // We check this before calling ISizeToClearPastFloats, which is
--- a/layout/generic/nsBlockReflowState.h
+++ b/layout/generic/nsBlockReflowState.h
@@ -154,18 +154,17 @@ public:
 
   nsFloatManager* mFloatManager;
 
   // The coordinates within the float manager where the block is being
   // placed <b>after</b> taking into account the blocks border and
   // padding. This, therefore, represents the inner "content area" (in
   // spacemanager coordinates) where child frames will be placed,
   // including child blocks and floats.
-  mozilla::WritingMode mFloatManagerWM;
-  mozilla::LogicalPoint mFloatManagerOrigin;
+  nscoord mFloatManagerI, mFloatManagerB;
 
   // XXX get rid of this
   nsReflowStatus mReflowStatus;
 
   // The float manager state as it was before the contents of this
   // block.  This is needed for positioning bullets, since we only want
   // to move the bullet to flow around floats that were before this
   // block, not floats inside of it.
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -35,17 +35,17 @@ PSArenaFreeCB(size_t aSize, void* aPtr, 
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // nsFloatManager
 
 nsFloatManager::nsFloatManager(nsIPresShell* aPresShell,
                                mozilla::WritingMode aWM)
   : mWritingMode(aWM),
-    mOrigin(aWM),
+    mLineLeft(0), mBlockStart(0),
     mFloatDamage(PSArenaAllocCB, PSArenaFreeCB, aPresShell),
     mPushedLeftFloatPastBreak(false),
     mPushedRightFloatPastBreak(false),
     mSplitLeftFloatAcrossBreak(false),
     mSplitRightFloatAcrossBreak(false)
 {
   MOZ_COUNT_CTOR(nsFloatManager);
 }
@@ -116,18 +116,17 @@ nsFloatManager::GetFlowArea(WritingMode 
                             BandInfoType aInfoType, nscoord aBSize,
                             LogicalRect aContentArea, SavedState* aState,
                             nscoord aContainerWidth) const
 {
   NS_ASSERTION(aBSize >= 0, "unexpected max block size");
   NS_ASSERTION(aContentArea.ISize(aWM) >= 0,
                "unexpected content area inline size");
 
-  LogicalPoint origin = mOrigin.ConvertTo(aWM, mWritingMode, aContainerWidth);
-  nscoord blockStart = aBOffset + origin.B(aWM);
+  nscoord blockStart = aBOffset + mBlockStart;
   if (blockStart < nscoord_MIN) {
     NS_WARNING("bad value");
     blockStart = nscoord_MIN;
   }
 
   // Determine the last float that we should consider.
   uint32_t floatCount;
   if (aState) {
@@ -157,43 +156,41 @@ nsFloatManager::GetFlowArea(WritingMode 
     blockEnd = nscoord_MAX;
   } else {
     blockEnd = blockStart + aBSize;
     if (blockEnd < blockStart || blockEnd > nscoord_MAX) {
       NS_WARNING("bad value");
       blockEnd = nscoord_MAX;
     }
   }
-  nscoord inlineStart = origin.I(aWM) + aContentArea.IStart(aWM);
-  nscoord inlineEnd = origin.I(aWM) + aContentArea.IEnd(aWM);
-  if (inlineEnd < inlineStart) {
+  nscoord lineLeft = mLineLeft + aContentArea.LineLeft(aWM, aContainerWidth);
+  nscoord lineRight = mLineLeft + aContentArea.LineRight(aWM, aContainerWidth);
+  if (lineRight < lineLeft) {
     NS_WARNING("bad value");
-    inlineEnd = inlineStart;
+    lineRight = lineLeft;
   }
 
   // Walk backwards through the floats until we either hit the front of
   // the list or we're above |blockStart|.
   bool haveFloats = false;
   for (uint32_t i = floatCount; i > 0; --i) {
     const FloatInfo &fi = mFloats[i-1];
     if (fi.mLeftBEnd <= blockStart && fi.mRightBEnd <= blockStart) {
       // There aren't any more floats that could intersect this band.
       break;
     }
-    if (fi.mRect.IsEmpty()) {
+    if (fi.IsEmpty()) {
       // For compatibility, ignore floats with empty rects, even though it
       // disagrees with the spec.  (We might want to fix this in the
       // future, though.)
       continue;
     }
 
-    LogicalRect rect = fi.mRect.ConvertTo(aWM, fi.mWritingMode,
-                                          aContainerWidth);
-    nscoord floatBStart = rect.BStart(aWM);
-    nscoord floatBEnd = rect.BEnd(aWM);
+    nscoord floatBStart = fi.BStart();
+    nscoord floatBEnd = fi.BEnd();
     if (blockStart < floatBStart && aInfoType == BAND_FROM_POINT) {
       // This float is below our band.  Shrink our band's height if needed.
       if (floatBStart < blockEnd) {
         blockEnd = floatBStart;
       }
     }
     // If blockStart == blockEnd (which happens only with WIDTH_WITHIN_HEIGHT),
     // we include floats that begin at our 0-height vertical area.  We
@@ -206,81 +203,88 @@ nsFloatManager::GetFlowArea(WritingMode 
       // This float is in our band.
 
       // Shrink our band's height if needed.
       if (floatBEnd < blockEnd && aInfoType == BAND_FROM_POINT) {
         blockEnd = floatBEnd;
       }
 
       // Shrink our band's width if needed.
-      if ((fi.mFrame->StyleDisplay()->mFloats == NS_STYLE_FLOAT_LEFT) ==
-          aWM.IsBidiLTR()) {
-        // A left float in an ltr block or a right float in an rtl block
-        nscoord inlineEndEdge = rect.IEnd(aWM);
-        if (inlineEndEdge > inlineStart) {
-          inlineStart = inlineEndEdge;
+      if (fi.mFrame->StyleDisplay()->mFloats == NS_STYLE_FLOAT_LEFT) {
+        // A left float
+        nscoord lineRightEdge = fi.LineRight();
+        if (lineRightEdge > lineLeft) {
+          lineLeft = lineRightEdge;
           // Only set haveFloats to true if the float is inside our
           // containing block.  This matches the spec for what some
           // callers want and disagrees for other callers, so we should
           // probably provide better information at some point.
           haveFloats = true;
         }
       } else {
-        // A left float in an rtl block or a right float in an ltr block
-        nscoord inlineStartEdge = rect.IStart(aWM);
-        if (inlineStartEdge < inlineEnd) {
-          inlineEnd = inlineStartEdge;
+        // A right float
+        nscoord lineLeftEdge = fi.LineLeft();
+        if (lineLeftEdge < lineRight) {
+          lineRight = lineLeftEdge;
           // See above.
           haveFloats = true;
         }
       }
     }
   }
 
   nscoord blockSize = (blockEnd == nscoord_MAX) ?
                        nscoord_MAX : (blockEnd - blockStart);
-  return nsFlowAreaRect(aWM,
-                        inlineStart - origin.I(aWM), blockStart - origin.B(aWM),
-                        inlineEnd - inlineStart, blockSize, haveFloats);
+  // convert back from LineLeft/Right to IStart
+  nscoord inlineStart = aWM.IsVertical() || aWM.IsBidiLTR()
+                         ? lineLeft - mLineLeft
+                         : mLineLeft + aContainerWidth - lineRight;
+
+  return nsFlowAreaRect(aWM, inlineStart, blockStart - mBlockStart,
+                        lineRight - lineLeft, blockSize, haveFloats);
 }
 
 nsresult
 nsFloatManager::AddFloat(nsIFrame* aFloatFrame, const LogicalRect& aMarginRect,
                          WritingMode aWM, nscoord aContainerWidth)
 {
   NS_ASSERTION(aMarginRect.ISize(aWM) >= 0, "negative inline size!");
   NS_ASSERTION(aMarginRect.BSize(aWM) >= 0, "negative block size!");
 
-  FloatInfo info(aFloatFrame, aWM, aMarginRect + mOrigin);
+  FloatInfo info(aFloatFrame,
+                 aMarginRect.LineLeft(aWM, aContainerWidth) + mLineLeft,
+                 aMarginRect.BStart(aWM) + mBlockStart,
+                 aMarginRect.ISize(aWM),
+                 aMarginRect.BSize(aWM));
 
   // Set mLeftBEnd and mRightBEnd.
   if (HasAnyFloats()) {
     FloatInfo &tail = mFloats[mFloats.Length() - 1];
     info.mLeftBEnd = tail.mLeftBEnd;
     info.mRightBEnd = tail.mRightBEnd;
   } else {
     info.mLeftBEnd = nscoord_MIN;
     info.mRightBEnd = nscoord_MIN;
   }
   uint8_t floatStyle = aFloatFrame->StyleDisplay()->mFloats;
   NS_ASSERTION(floatStyle == NS_STYLE_FLOAT_LEFT ||
                floatStyle == NS_STYLE_FLOAT_RIGHT, "unexpected float");
-  nscoord& sideBEnd =
-    ((floatStyle == NS_STYLE_FLOAT_LEFT) == aWM.IsBidiLTR()) ? info.mLeftBEnd
-                                                             : info.mRightBEnd;
-  nscoord thisBEnd = info.mRect.BEnd(aWM);
+  nscoord& sideBEnd = floatStyle == NS_STYLE_FLOAT_LEFT ? info.mLeftBEnd
+                                                        : info.mRightBEnd;
+  nscoord thisBEnd = info.BEnd();
   if (thisBEnd > sideBEnd)
     sideBEnd = thisBEnd;
 
   if (!mFloats.AppendElement(info))
     return NS_ERROR_OUT_OF_MEMORY;
 
   return NS_OK;
 }
 
+// static
 LogicalRect
 nsFloatManager::CalculateRegionFor(WritingMode          aWM,
                                    nsIFrame*            aFloat,
                                    const LogicalMargin& aMargin,
                                    nscoord              aContainerWidth)
 {
   // We consider relatively positioned frames at their original position.
   LogicalRect region(aWM, nsRect(aFloat->GetNormalPosition(),
@@ -397,56 +401,53 @@ nsFloatManager::PushState(SavedState* aS
   // intentionally not saved or restored in PushState() and PopState(),
   // since that could lead to bugs where damage is missed/dropped when
   // we move from position A to B (during the intermediate incremental
   // reflow mentioned above) and then from B to C during the subsequent
   // reflow. In the typical case A and C will be the same, but not always.
   // Allowing mFloatDamage to accumulate the damage incurred during both
   // reflows ensures that nothing gets missed.
   aState->mWritingMode = mWritingMode;
-  aState->mOrigin = mOrigin;
+  aState->mLineLeft = mLineLeft;
+  aState->mBlockStart = mBlockStart;
   aState->mPushedLeftFloatPastBreak = mPushedLeftFloatPastBreak;
   aState->mPushedRightFloatPastBreak = mPushedRightFloatPastBreak;
   aState->mSplitLeftFloatAcrossBreak = mSplitLeftFloatAcrossBreak;
   aState->mSplitRightFloatAcrossBreak = mSplitRightFloatAcrossBreak;
   aState->mFloatInfoCount = mFloats.Length();
 }
 
 void
 nsFloatManager::PopState(SavedState* aState)
 {
   NS_PRECONDITION(aState, "No state to restore?");
 
   mWritingMode = aState->mWritingMode;
-  mOrigin = aState->mOrigin;
+  mLineLeft = aState->mLineLeft;
+  mBlockStart = aState->mBlockStart;
   mPushedLeftFloatPastBreak = aState->mPushedLeftFloatPastBreak;
   mPushedRightFloatPastBreak = aState->mPushedRightFloatPastBreak;
   mSplitLeftFloatAcrossBreak = aState->mSplitLeftFloatAcrossBreak;
   mSplitRightFloatAcrossBreak = aState->mSplitRightFloatAcrossBreak;
 
   NS_ASSERTION(aState->mFloatInfoCount <= mFloats.Length(),
                "somebody misused PushState/PopState");
   mFloats.TruncateLength(aState->mFloatInfoCount);
 }
 
 nscoord
-nsFloatManager::GetLowestFloatTop(WritingMode aWM,
-                                  nscoord aContainerWidth) const
+nsFloatManager::GetLowestFloatTop() const
 {
   if (mPushedLeftFloatPastBreak || mPushedRightFloatPastBreak) {
     return nscoord_MAX;
   }
   if (!HasAnyFloats()) {
     return nscoord_MIN;
   }
-  FloatInfo fi = mFloats[mFloats.Length() - 1];
-  LogicalRect rect = fi.mRect.ConvertTo(aWM, fi.mWritingMode, aContainerWidth);
-  LogicalPoint origin = mOrigin.ConvertTo(aWM, mWritingMode, aContainerWidth);
-
-  return rect.BStart(aWM) - origin.B(aWM);
+  return mFloats[mFloats.Length() -1].BStart() - mBlockStart;
 }
 
 #ifdef DEBUG_FRAME_DUMP
 void
 DebugListFloatManager(const nsFloatManager *aFloatManager)
 {
   aFloatManager->List(stdout);
 }
@@ -456,61 +457,54 @@ nsFloatManager::List(FILE* out) const
 {
   if (!HasAnyFloats())
     return NS_OK;
 
   for (uint32_t i = 0; i < mFloats.Length(); ++i) {
     const FloatInfo &fi = mFloats[i];
     fprintf_stderr(out, "Float %u: frame=%p rect={%d,%d,%d,%d} ymost={l:%d, r:%d}\n",
                    i, static_cast<void*>(fi.mFrame),
-                   fi.mRect.IStart(fi.mWritingMode),
-                   fi.mRect.BStart(fi.mWritingMode),
-                   fi.mRect.ISize(fi.mWritingMode),
-                   fi.mRect.BSize(fi.mWritingMode),
+                   fi.LineLeft(), fi.BStart(), fi.ISize(), fi.BSize(),
                    fi.mLeftBEnd, fi.mRightBEnd);
   }
   return NS_OK;
 }
 #endif
 
 nscoord
-nsFloatManager::ClearFloats(WritingMode aWM, nscoord aBCoord,
-                            uint8_t aBreakType, nscoord aContainerWidth,
+nsFloatManager::ClearFloats(nscoord aBCoord, uint8_t aBreakType,
                             uint32_t aFlags) const
 {
   if (!(aFlags & DONT_CLEAR_PUSHED_FLOATS) && ClearContinues(aBreakType)) {
     return nscoord_MAX;
   }
   if (!HasAnyFloats()) {
     return aBCoord;
   }
 
-  LogicalPoint origin = mOrigin.ConvertTo(aWM, mWritingMode, aContainerWidth);
-  nscoord blockEnd = aBCoord + origin.B(aWM);
+  nscoord blockEnd = aBCoord + mBlockStart;
 
   const FloatInfo &tail = mFloats[mFloats.Length() - 1];
   switch (aBreakType) {
     case NS_STYLE_CLEAR_BOTH:
       blockEnd = std::max(blockEnd, tail.mLeftBEnd);
       blockEnd = std::max(blockEnd, tail.mRightBEnd);
       break;
     case NS_STYLE_CLEAR_LEFT:
-      blockEnd = std::max(blockEnd, aWM.IsBidiLTR() ? tail.mLeftBEnd
-                                                    : tail.mRightBEnd);
+      blockEnd = std::max(blockEnd, tail.mLeftBEnd);
       break;
     case NS_STYLE_CLEAR_RIGHT:
-      blockEnd = std::max(blockEnd, aWM.IsBidiLTR() ? tail.mRightBEnd
-                                                    : tail.mLeftBEnd);
+      blockEnd = std::max(blockEnd, tail.mRightBEnd);
       break;
     default:
       // Do nothing
       break;
   }
 
-  blockEnd -= origin.B(aWM);
+  blockEnd -= mBlockStart;
 
   return blockEnd;
 }
 
 bool
 nsFloatManager::ClearContinues(uint8_t aBreakType) const
 {
   return ((mPushedLeftFloatPastBreak || mSplitLeftFloatAcrossBreak) &&
@@ -519,30 +513,31 @@ nsFloatManager::ClearContinues(uint8_t a
          ((mPushedRightFloatPastBreak || mSplitRightFloatAcrossBreak) &&
           (aBreakType == NS_STYLE_CLEAR_BOTH ||
            aBreakType == NS_STYLE_CLEAR_RIGHT));
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // FloatInfo
 
-nsFloatManager::FloatInfo::FloatInfo(nsIFrame* aFrame, WritingMode aWM,
-                                     const LogicalRect& aRect)
-  : mFrame(aFrame), mRect(aRect), mWritingMode(aWM)
+nsFloatManager::FloatInfo::FloatInfo(nsIFrame* aFrame,
+                                     nscoord aLineLeft, nscoord aBStart,
+                                     nscoord aISize, nscoord aBSize)
+  : mFrame(aFrame)
+  , mRect(aLineLeft, aBStart, aISize, aBSize)
 {
   MOZ_COUNT_CTOR(nsFloatManager::FloatInfo);
 }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
 nsFloatManager::FloatInfo::FloatInfo(const FloatInfo& aOther)
   : mFrame(aOther.mFrame),
-    mRect(aOther.mRect),
-    mWritingMode(aOther.mWritingMode),
     mLeftBEnd(aOther.mLeftBEnd),
-    mRightBEnd(aOther.mRightBEnd)
+    mRightBEnd(aOther.mRightBEnd),
+    mRect(aOther.mRect)
 {
   MOZ_COUNT_CTOR(nsFloatManager::FloatInfo);
 }
 
 nsFloatManager::FloatInfo::~FloatInfo()
 {
   MOZ_COUNT_DTOR(nsFloatManager::FloatInfo);
 }
--- a/layout/generic/nsFloatManager.h
+++ b/layout/generic/nsFloatManager.h
@@ -81,79 +81,50 @@ public:
   static void StoreRegionFor(mozilla::WritingMode aWM,
                              nsIFrame* aFloat,
                              const mozilla::LogicalRect& aRegion,
                              nscoord aContainerWidth);
 
   // Structure that stores the current state of a frame manager for
   // Save/Restore purposes.
   struct SavedState {
-    explicit SavedState(mozilla::WritingMode aWM)
-      : mWritingMode(aWM)
-      , mOrigin(aWM)
-    {}
+    explicit SavedState() {}
   private:
     uint32_t mFloatInfoCount;
     mozilla::WritingMode mWritingMode;
-    mozilla::LogicalPoint mOrigin;
+    nscoord mLineLeft, mBlockStart;
     bool mPushedLeftFloatPastBreak;
     bool mPushedRightFloatPastBreak;
     bool mSplitLeftFloatAcrossBreak;
     bool mSplitRightFloatAcrossBreak;
 
     friend class nsFloatManager;
   };
 
   /**
-   * Translate the current origin by the specified (dICoord, dBCoord). This
+   * Translate the current origin by the specified offsets. This
    * creates a new local coordinate space relative to the current
    * coordinate space.
    * @returns previous writing mode
    */
-  mozilla::WritingMode Translate(mozilla::WritingMode aWM,
-                                 mozilla::LogicalPoint aDOrigin,
-                                 nscoord aContainerWidth)
+  void Translate(nscoord aLineLeft, nscoord aBlockStart)
   {
-    mozilla::WritingMode oldWM = mWritingMode;
-    mOrigin = mOrigin.ConvertTo(aWM, oldWM, aContainerWidth);
-    mWritingMode = aWM;
-    mOrigin += aDOrigin;
-    return oldWM;
-  }
-
-  /*
-   * Set the translation origin to a specified value instead of
-   * translating by a delta.
-   */
-  void SetTranslation(mozilla::WritingMode aWM,
-                      mozilla::LogicalPoint aOrigin)
-  {
-    mWritingMode = aWM;
-    mOrigin = aOrigin;
-  }
-
-  void Untranslate(mozilla::WritingMode aWM,
-                   mozilla::LogicalPoint aDOrigin,
-                   nscoord aContainerWidth)
-  {
-    mOrigin -= aDOrigin;
-    mOrigin = mOrigin.ConvertTo(aWM, mWritingMode, aContainerWidth);
-    mWritingMode = aWM;
+    mLineLeft += aLineLeft;
+    mBlockStart += aBlockStart;
   }
 
   /**
    * Returns the current translation from local coordinate space to
    * world coordinate space. This represents the accumulated calls to
    * Translate().
    */
-  void GetTranslation(mozilla::WritingMode& aWM,
-                      mozilla::LogicalPoint& aOrigin) const
+  void GetTranslation(nscoord& aLineLeft, nscoord& aBlockStart) const
   {
-    aWM = mWritingMode;
-    aOrigin = mOrigin;
+    aLineLeft = mLineLeft;
+    aBlockStart = mBlockStart;
   }
 
   /**
    * Get information about the area available to content that flows
    * around floats.  Two different types of space can be requested:
    *   BAND_FROM_POINT: returns the band containing block-dir coordinate
    *     |aBCoord| (though actually with the top truncated to begin at
    *     aBCoord), but up to at most |aBSize| (which may be nscoord_MAX).
@@ -252,25 +223,25 @@ public:
   bool HasFloatDamage() const
   {
     return !mFloatDamage.IsEmpty();
   }
 
   void IncludeInDamage(mozilla::WritingMode aWM,
                        nscoord aIntervalBegin, nscoord aIntervalEnd)
   {
-    mFloatDamage.IncludeInterval(aIntervalBegin + mOrigin.B(aWM),
-                                 aIntervalEnd + mOrigin.B(aWM));
+    mFloatDamage.IncludeInterval(aIntervalBegin + mBlockStart,
+                                 aIntervalEnd + mBlockStart);
   }
 
   bool IntersectsDamage(mozilla::WritingMode aWM,
                         nscoord aIntervalBegin, nscoord aIntervalEnd) const
   {
-    return mFloatDamage.Intersects(aIntervalBegin + mOrigin.B(aWM),
-                                   aIntervalEnd + mOrigin.B(aWM));
+    return mFloatDamage.Intersects(aIntervalBegin + mBlockStart,
+                                   aIntervalEnd + mBlockStart);
   }
 
   /**
    * Saves the current state of the float manager into aState.
    */
   void PushState(SavedState* aState);
 
   /**
@@ -287,45 +258,44 @@ public:
 
   /**
    * Get the block start of the last float placed into the float
    * manager, to enforce the rule that a float can't be above an earlier
    * float. Returns the minimum nscoord value if there are no floats.
    *
    * The result is relative to the current translation.
    */
-  nscoord GetLowestFloatTop(mozilla::WritingMode aWM,
-                            nscoord aContainerWidth) const;
+  nscoord GetLowestFloatTop() const;
 
   /**
    * Return the coordinate of the lowest float matching aBreakType in
    * this float manager. Returns aBCoord if there are no matching
    * floats.
    *
    * Both aBCoord and the result are relative to the current translation.
    */
   enum {
     // Tell ClearFloats not to push to nscoord_MAX when floats have been
     // pushed to the next page/column.
     DONT_CLEAR_PUSHED_FLOATS = (1<<0)
   };
-  nscoord ClearFloats(mozilla::WritingMode aWM, nscoord aBCoord,
-                      uint8_t aBreakType, nscoord aContainerWidth,
+  nscoord ClearFloats(nscoord aBCoord, uint8_t aBreakType,
                       uint32_t aFlags = 0) const;
 
   /**
    * Checks if clear would pass into the floats' BFC's next-in-flow,
    * i.e. whether floats affecting this clear have continuations.
    */
   bool ClearContinues(uint8_t aBreakType) const;
 
   void AssertStateMatches(SavedState *aState) const
   {
     NS_ASSERTION(aState->mWritingMode == mWritingMode &&
-                 aState->mOrigin == mOrigin &&
+                 aState->mLineLeft == mLineLeft &&
+                 aState->mBlockStart == mBlockStart &&
                  aState->mPushedLeftFloatPastBreak ==
                    mPushedLeftFloatPastBreak &&
                  aState->mPushedRightFloatPastBreak ==
                    mPushedRightFloatPastBreak &&
                  aState->mSplitLeftFloatAcrossBreak ==
                    mSplitLeftFloatAcrossBreak &&
                  aState->mSplitRightFloatAcrossBreak ==
                    mSplitRightFloatAcrossBreak &&
@@ -339,34 +309,50 @@ public:
    */
   nsresult List(FILE* out) const;
 #endif
 
 private:
 
   struct FloatInfo {
     nsIFrame *const mFrame;
-    mozilla::LogicalRect mRect;
-    mozilla::WritingMode mWritingMode;
     // The lowest block-ends of left/right floats up to and including
     // this one.
     nscoord mLeftBEnd, mRightBEnd;
 
-    FloatInfo(nsIFrame* aFrame, mozilla::WritingMode aWM,
-              const mozilla::LogicalRect& aRect);
+    FloatInfo(nsIFrame* aFrame, nscoord aLineLeft, nscoord aBStart,
+              nscoord aISize, nscoord aBSize);
+
+    nscoord LineLeft() const { return mRect.x; }
+    nscoord LineRight() const { return mRect.XMost(); }
+    nscoord ISize() const { return mRect.width; }
+    nscoord BStart() const { return mRect.y; }
+    nscoord BEnd() const { return mRect.YMost(); }
+    nscoord BSize() const { return mRect.height; }
+    bool IsEmpty() const { return mRect.IsEmpty(); }
+
 #ifdef NS_BUILD_REFCNT_LOGGING
     FloatInfo(const FloatInfo& aOther);
     ~FloatInfo();
 #endif
+
+  private:
+    // NB! This is really a logical rect in a writing mode suitable for
+    // placing floats, which is not necessarily the actual writing mode
+    // either of the block which created the frame manager or the block
+    // that is calling the frame manager. The inline coordinates are in
+    // the line-relative axis of the frame manager and its block
+    // coordinates are in the frame manager's real block direction.
+    nsRect mRect;
   };
 
   mozilla::WritingMode mWritingMode;
-  mozilla::LogicalPoint mOrigin;  // translation from local to global
-                                  // coordinate space
 
+  // Translation from local to global coordinate space.
+  nscoord mLineLeft, mBlockStart;
   nsTArray<FloatInfo> mFloats;
   nsIntervalSet   mFloatDamage;
 
   // Did we try to place a float that could not fit at all and had to be
   // pushed to the next page/column?  If so, we can't place any more
   // floats in this page/column because of the rule that the top of a
   // float cannot be above the top of an earlier float.  And we also
   // need to apply this information to 'clear', and thus need to
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -937,18 +937,19 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
   aFrame->WillReflow(mPresContext);
 
   // Adjust spacemanager coordinate system for the frame.
   nsHTMLReflowMetrics metrics(lineWM);
 #ifdef DEBUG
   metrics.ISize(lineWM) = nscoord(0xdeadbeef);
   metrics.BSize(lineWM) = nscoord(0xdeadbeef);
 #endif
-  LogicalPoint tPt = pfd->mBounds.Origin(lineWM);
-  WritingMode oldWM = mFloatManager->Translate(lineWM, tPt, ContainerWidth());
+  nscoord tI = pfd->mBounds.LineLeft(lineWM, ContainerWidth());
+  nscoord tB = pfd->mBounds.BStart(lineWM);
+  mFloatManager->Translate(tI, tB);
 
   int32_t savedOptionalBreakOffset;
   gfxBreakPriority savedOptionalBreakPriority;
   nsIFrame* savedOptionalBreakFrame =
     GetLastOptionalBreakPosition(&savedOptionalBreakOffset,
                                  &savedOptionalBreakPriority);
 
   if (!isText) {
@@ -1026,17 +1027,17 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
         isEmpty = !pfd->mSpan->mHasNonemptyContent && pfd->mFrame->IsSelfEmpty();
       } else {
         isEmpty = pfd->mFrame->IsEmpty();
       }
     }
   }
   pfd->mIsEmpty = isEmpty;
 
-  mFloatManager->Untranslate(oldWM, tPt, ContainerWidth());
+  mFloatManager->Translate(-tI, -tB);
 
   NS_ASSERTION(metrics.ISize(lineWM) >= 0, "bad inline size");
   NS_ASSERTION(metrics.BSize(lineWM) >= 0,"bad block size");
   if (metrics.ISize(lineWM) < 0) {
     metrics.ISize(lineWM) = 0;
   }
   if (metrics.BSize(lineWM) < 0) {
     metrics.BSize(lineWM) = 0;