Bug 1079139: make nsFlowAreaRect.mRect a LogicalRect. r=jfkthame
authorSimon Montagu <smontagu@smontagu.org>
Tue, 21 Oct 2014 15:16:13 -0700
changeset 211675 3b63378162d709eba82b3ee0c32aad53aa425088
parent 211674 171e352854e7020251acc5a24c95b410db8936cb
child 211676 04a18f29f77478f5228752c78a7e77ea42ae1af1
push id27686
push userryanvm@gmail.com
push dateWed, 22 Oct 2014 20:01:01 +0000
treeherdermozilla-central@6066a2a0766f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1079139
milestone36.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 1079139: make nsFlowAreaRect.mRect a LogicalRect. r=jfkthame
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/generic/nsBlockReflowContext.cpp
layout/generic/nsBlockReflowContext.h
layout/generic/nsBlockReflowState.cpp
layout/generic/nsBlockReflowState.h
layout/generic/nsFloatManager.cpp
layout/generic/nsFloatManager.h
layout/generic/nsLineBox.h
layout/generic/nsLineLayout.cpp
layout/generic/nsLineLayout.h
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -901,27 +901,30 @@ nsBlockFrame::GetPrefWidthTightBounds(ns
     }
   }
   data.ForceBreak(aRenderingContext);
 
   return NS_OK;
 }
 
 static bool
-AvailableSpaceShrunk(const nsRect& aOldAvailableSpace,
-                     const nsRect& aNewAvailableSpace)
-{
-  if (aNewAvailableSpace.width == 0) {
-    // Positions are not significant if the width is zero.
-    return aOldAvailableSpace.width != 0;
-  }
-  NS_ASSERTION(aOldAvailableSpace.x <= aNewAvailableSpace.x &&
-               aOldAvailableSpace.XMost() >= aNewAvailableSpace.XMost(),
+AvailableSpaceShrunk(WritingMode aWM,
+                     const LogicalRect& aOldAvailableSpace,
+                     const LogicalRect& aNewAvailableSpace)
+{
+  if (aNewAvailableSpace.ISize(aWM) == 0) {
+    // Positions are not significant if the inline size is zero.
+    return aOldAvailableSpace.ISize(aWM) != 0;
+  }
+  NS_ASSERTION(aOldAvailableSpace.IStart(aWM) <=
+               aNewAvailableSpace.IStart(aWM) &&
+               aOldAvailableSpace.IEnd(aWM) >=
+               aNewAvailableSpace.IEnd(aWM),
                "available space should never grow");
-  return aOldAvailableSpace.width != aNewAvailableSpace.width;
+  return aOldAvailableSpace.ISize(aWM) != aNewAvailableSpace.ISize(aWM);
 }
 
 static LogicalSize
 CalculateContainingBlockSizeForAbsolutes(WritingMode aWM,
                                          const nsHTMLReflowState& aReflowState,
                                          LogicalSize aFrameSize)
 {
   // The issue here is that for a 'height' of 'auto' the reflow state
@@ -1808,69 +1811,81 @@ nsBlockFrame::PrepareResizeReflow(nsBloc
 }
 
 //----------------------------------------
 
 /**
  * Propagate reflow "damage" from from earlier lines to the current
  * line.  The reflow damage comes from the following sources:
  *  1. The regions of float damage remembered during reflow.
- *  2. The combination of nonzero |aDeltaY| and any impact by a float,
- *     either the previous reflow or now.
+ *  2. The combination of nonzero |aDeltaBCoord| and any impact by a
+ *     float, either the previous reflow or now.
  *
  * When entering this function, |aLine| is still at its old position and
- * |aDeltaY| indicates how much it will later be slid (assuming it
+ * |aDeltaBCoord| indicates how much it will later be slid (assuming it
  * doesn't get marked dirty and reflowed entirely).
  */
 void
 nsBlockFrame::PropagateFloatDamage(nsBlockReflowState& aState,
                                    nsLineBox* aLine,
-                                   nscoord aDeltaY)
+                                   nscoord aDeltaBCoord)
 {
   nsFloatManager *floatManager = aState.mReflowState.mFloatManager;
   NS_ASSERTION((aState.mReflowState.parentReflowState &&
                 aState.mReflowState.parentReflowState->mFloatManager == floatManager) ||
                 aState.mReflowState.mBlockDelta == 0, "Bad block delta passed in");
 
   // Check to see if there are any floats; if there aren't, there can't
   // be any float damage
   if (!floatManager->HasAnyFloats())
     return;
 
   // Check the damage region recorded in the float damage.
   if (floatManager->HasFloatDamage()) {
     // Need to check mBounds *and* mCombinedArea to find intersections 
     // with aLine's floats
-    nscoord lineYA = aLine->BStart() + aDeltaY;
-    nscoord lineYB = lineYA + aLine->BSize();
+    nscoord lineBCoordBefore = aLine->BStart() + aDeltaBCoord;
+    nscoord lineBCoordAfter = lineBCoordBefore + aLine->BSize();
     // Scrollable overflow should be sufficient for things that affect
     // layout.
-    nsRect overflow = aLine->GetOverflowArea(eScrollableOverflow);
-    nscoord lineYCombinedA = overflow.y + aDeltaY;
-    nscoord lineYCombinedB = lineYCombinedA + overflow.height;
     WritingMode wm = aState.mReflowState.GetWritingMode();
-    if (floatManager->IntersectsDamage(wm, lineYA, lineYB) ||
-        floatManager->IntersectsDamage(wm, lineYCombinedA, lineYCombinedB)) {
+    nscoord containerWidth = aState.mContainerWidth;
+    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 (aDeltaY + aState.mReflowState.mBlockDelta != 0) {
+  if (aDeltaBCoord + aState.mReflowState.mBlockDelta != 0) {
     if (aLine->IsBlock()) {
       // Unconditionally reflow sliding blocks; we only really need to reflow
       // if there's a float impacting this block, but the current float manager
       // makes it difficult to check that.  Therefore, we let the child block
       // decide what it needs to reflow.
       aLine->MarkDirty();
     } else {
       bool wasImpactedByFloat = aLine->IsImpactedByFloat();
       nsFlowAreaRect floatAvailableSpace =
-        aState.GetFloatAvailableSpaceForBSize(aLine->BStart() + aDeltaY,
+        aState.GetFloatAvailableSpaceForBSize(aLine->BStart() + aDeltaBCoord,
                                               aLine->BSize(),
                                               nullptr);
 
 #ifdef REALLY_NOISY_REFLOW
     printf("nsBlockFrame::PropagateFloatDamage %p was = %d, is=%d\n", 
            this, wasImpactedByFloat, floatAvailableSpace.mHasFloats);
 #endif
 
@@ -1907,30 +1922,30 @@ nsBlockFrame::ReparentFloats(nsIFrame* a
     for (nsIFrame* f = list.FirstChild(); f; f = f->GetNextSibling()) {
       ReparentFrame(f, aOldParent, this);
     }
     mFloats.AppendFrames(nullptr, list);
   }
 }
 
 static void DumpLine(const nsBlockReflowState& aState, nsLineBox* aLine,
-                     nscoord aDeltaY, int32_t aDeltaIndent) {
+                     nscoord aDeltaBCoord, int32_t aDeltaIndent) {
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyReflow) {
     nsRect ovis(aLine->GetVisualOverflowArea());
     nsRect oscr(aLine->GetScrollableOverflowArea());
     nsBlockFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent + aDeltaIndent);
     printf("line=%p mBCoord=%d dirty=%s oldBounds={%d,%d,%d,%d} oldoverflow-vis={%d,%d,%d,%d} oldoverflow-scr={%d,%d,%d,%d} deltaBCoord=%d mPrevBEndMargin=%d childCount=%d\n",
            static_cast<void*>(aLine), aState.mBCoord,
            aLine->IsDirty() ? "yes" : "no",
            aLine->IStart(), aLine->BStart(),
            aLine->ISize(), aLine->BSize(),
            ovis.x, ovis.y, ovis.width, ovis.height,
            oscr.x, oscr.y, oscr.width, oscr.height,
-           aDeltaY, aState.mPrevBEndMargin.get(), aLine->GetChildCount());
+           aDeltaBCoord, aState.mPrevBEndMargin.get(), aLine->GetChildCount());
   }
 #endif
 }
 
 void
 nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
 {
   bool keepGoing = true;
@@ -3131,63 +3146,64 @@ nsBlockFrame::ReflowBlockFrame(nsBlockRe
     // Here aState.mBCoord is the block-start border-edge of the block.
     // Compute the available space for the block
     nsFlowAreaRect floatAvailableSpace = aState.GetFloatAvailableSpace();
 #ifdef REALLY_NOISY_REFLOW
     printf("setting line %p isImpacted to %s\n",
            aLine.get(), floatAvailableSpace.mHasFloats?"true":"false");
 #endif
     aLine->SetLineIsImpactedByFloat(floatAvailableSpace.mHasFloats);
-    nsRect availSpace;
+    WritingMode wm = aState.mReflowState.GetWritingMode();
+    LogicalRect availSpace(wm);
     aState.ComputeBlockAvailSpace(frame, display, floatAvailableSpace,
                                   replacedBlock != nullptr, availSpace);
 
     // The check for
     //   (!aState.mReflowState.mFlags.mIsTopOfPage || clearedFloats)
     // is to some degree out of paranoia:  if we reliably eat up top
     // margins at the top of the page as we ought to, it wouldn't be
     // needed.
     if ((!aState.mReflowState.mFlags.mIsTopOfPage || clearedFloats) &&
-        availSpace.height < 0) {
+        availSpace.BSize(wm) < 0) {
       // We know already that this child block won't fit on this
       // page/column due to the top margin or the clearance.  So we need
       // to get out of here now.  (If we don't, most blocks will handle
       // things fine, and report break-before, but zero-height blocks
       // won't, and will thus make their parent overly-large and force
       // *it* to be pushed in its entirety.)
       // Doing this means that we also don't need to worry about the
-      // |availSpace.height += bStartMargin| below interacting with pushed
-      // floats (which force nscoord_MAX clearance) to cause a
-      // constrained height to turn into an unconstrained one.
+      // |availSpace.BSize(wm) += bStartMargin| below interacting with
+      // pushed floats (which force nscoord_MAX clearance) to cause a
+      // constrained block size to turn into an unconstrained one.
       aState.mBCoord = startingBCoord;
       aState.mPrevBEndMargin = incomingMargin;
       *aKeepReflowGoing = false;
       if (ShouldAvoidBreakInside(aState.mReflowState)) {
         aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
       } else {
         PushLines(aState, aLine.prev());
         NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
       }
       return;
     }
 
-    // Now put the Y coordinate back to the top of the top-margin +
-    // clearance, and flow the block.
+    // Now put the block-dir coordinate back to the start of the
+    // block-start-margin + clearance, and flow the block.
     aState.mBCoord -= bStartMargin;
-    availSpace.y -= bStartMargin;
-    if (NS_UNCONSTRAINEDSIZE != availSpace.height) {
-      availSpace.height += bStartMargin;
+    availSpace.BStart(wm) -= bStartMargin;
+    if (NS_UNCONSTRAINEDSIZE != availSpace.BSize(wm)) {
+      availSpace.BSize(wm) += bStartMargin;
     }
 
     // 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,
-                  LogicalSize(frame->GetWritingMode(), availSpace.Size()));
+                  availSpace.Size(wm).ConvertTo(frame->GetWritingMode(), wm));
     blockHtmlRS.mFlags.mHasClearance = aLine->HasClearance();
 
     nsFloatManager::SavedState
       floatManagerState(aState.mReflowState.GetWritingMode());
     if (mayNeedRetry) {
       blockHtmlRS.mDiscoveredClearance = &clearanceFrame;
       aState.mFloatManager->PushState(&floatManagerState);
     } else if (!applyBStartMargin) {
@@ -3539,19 +3555,21 @@ nsBlockFrame::DoReflowInlineFrames(nsBlo
   // are impacted by floats.
   if (aFloatAvailableSpace.mHasFloats)
     aLine->SetLineIsImpactedByFloat(true);
 #ifdef REALLY_NOISY_REFLOW
   printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
          this, aFloatAvailableSpace.mHasFloats);
 #endif
 
+  WritingMode outerWM = aState.mReflowState.GetWritingMode();
   WritingMode lineWM = GetWritingMode(aLine->mFirstChild);
-  LogicalRect lineRect(lineWM, aFloatAvailableSpace.mRect,
-                       aState.mContainerWidth);
+  LogicalRect lineRect =
+    aFloatAvailableSpace.mRect.ConvertTo(lineWM, outerWM,
+                                         aState.mContainerWidth);
 
   nscoord iStart = lineRect.IStart(lineWM);
   nscoord availISize = lineRect.ISize(lineWM);
   nscoord availBSize;
   if (aState.GetFlag(BRS_UNCONSTRAINEDBSIZE)) {
     availBSize = NS_UNCONSTRAINEDSIZE;
   }
   else {
@@ -3678,29 +3696,30 @@ nsBlockFrame::DoReflowInlineFrames(nsBlo
 
   if (LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus) {
     // This happens only when we have a line that is impacted by
     // floats and the first element in the line doesn't fit with
     // the floats.
     //
     // What we do is to advance past the first float we find and
     // then reflow the line all over again.
-    NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aFloatAvailableSpace.mRect.height,
-                 "unconstrained height on totally empty line");
+    NS_ASSERTION(NS_UNCONSTRAINEDSIZE !=
+                 aFloatAvailableSpace.mRect.BSize(outerWM),
+                 "unconstrained block size on totally empty line");
 
     // See the analogous code for blocks in nsBlockReflowState::ClearFloats.
-    if (aFloatAvailableSpace.mRect.height > 0) {
+    if (aFloatAvailableSpace.mRect.BSize(outerWM) > 0) {
       NS_ASSERTION(aFloatAvailableSpace.mHasFloats,
                    "redo line on totally empty line with non-empty band...");
       // We should never hit this case if we've placed floats on the
       // line; if we have, then the GetFloatAvailableSpace call is wrong
       // and needs to happen after the caller pops the space manager
       // state.
       aState.mFloatManager->AssertStateMatches(aFloatStateBeforeLine);
-      aState.mBCoord += aFloatAvailableSpace.mRect.height;
+      aState.mBCoord += aFloatAvailableSpace.mRect.BSize(outerWM);
       aFloatAvailableSpace = aState.GetFloatAvailableSpace();
     } else {
       NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aState.mReflowState.AvailableBSize(),
                    "We shouldn't be running out of height here");
       if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.AvailableBSize()) {
         // just move it down a bit to try to get out of this mess
         aState.mBCoord += 1;
         // We should never hit this case if we've placed floats on the
@@ -4109,70 +4128,71 @@ nsBlockFrame::IsLastLine(nsBlockReflowSt
   return true;
 }
 
 bool
 nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
                         nsLineLayout&       aLineLayout,
                         line_iterator       aLine,
                         nsFloatManager::SavedState *aFloatStateBeforeLine,
-                        nsRect&             aFloatAvailableSpace,
+                        LogicalRect&        aFloatAvailableSpace,
                         nscoord&            aAvailableSpaceHeight,
                         bool*             aKeepReflowGoing)
 {
   // Trim extra white-space from the line before placing the frames
   aLineLayout.TrimTrailingWhiteSpace();
 
   // Vertically align the frames on this line.
   //
   // According to the CSS2 spec, section 12.6.1, the "marker" box
   // participates in the height calculation of the list-item box's
   // first line box.
   //
   // There are exactly two places a bullet can be placed: near the
   // first or second line. It's only placed on the second line in a
   // rare case: when the first line is empty.
+  WritingMode wm = aState.mReflowState.GetWritingMode();
   bool addedBullet = false;
   if (HasOutsideBullet() &&
       ((aLine == mLines.front() &&
         (!aLineLayout.IsZeroBSize() || (aLine == mLines.back()))) ||
        (mLines.front() != mLines.back() &&
         0 == mLines.front()->BSize() &&
         aLine == mLines.begin().next()))) {
     nsHTMLReflowMetrics metrics(aState.mReflowState);
     nsIFrame* bullet = GetOutsideBullet();
     ReflowBullet(bullet, aState, metrics, aState.mBCoord);
-    NS_ASSERTION(!BulletIsEmpty() ||
-                 metrics.BSize(aState.mReflowState.GetWritingMode()) == 0,
+    NS_ASSERTION(!BulletIsEmpty() || metrics.BSize(wm) == 0,
                  "empty bullet took up space");
     aLineLayout.AddBulletFrame(bullet, metrics);
     addedBullet = true;
   }
   aLineLayout.VerticalAlignLine();
 
   // We want to compare to the available space that we would have had in
   // the line's height *before* we placed any floats in the line itself.
   // Floats that are in the line are handled during line reflow (and may
   // result in floats being pushed to below the line or (I HOPE???) in a
   // reflow with a forced break position).
-  nsRect oldFloatAvailableSpace(aFloatAvailableSpace);
+  LogicalRect oldFloatAvailableSpace(aFloatAvailableSpace);
   // As we redo for floats, we can't reduce the amount of height we're
   // checking.
   aAvailableSpaceHeight = std::max(aAvailableSpaceHeight, aLine->BSize());
   aFloatAvailableSpace =
     aState.GetFloatAvailableSpaceForBSize(aLine->BStart(),
                                           aAvailableSpaceHeight,
                                           aFloatStateBeforeLine).mRect;
-  NS_ASSERTION(aFloatAvailableSpace.y == oldFloatAvailableSpace.y, "yikes");
+  NS_ASSERTION(aFloatAvailableSpace.BStart(wm) ==
+               oldFloatAvailableSpace.BStart(wm), "yikes");
   // Restore the height to the position of the next band.
-  aFloatAvailableSpace.height = oldFloatAvailableSpace.height;
+  aFloatAvailableSpace.BSize(wm) = oldFloatAvailableSpace.BSize(wm);
   // If the available space between the floats is smaller now that we
   // know the height, return false (and cause another pass with
   // LINE_REFLOW_REDO_MORE_FLOATS).
-  if (AvailableSpaceShrunk(oldFloatAvailableSpace, aFloatAvailableSpace)) {
+  if (AvailableSpaceShrunk(wm, oldFloatAvailableSpace, aFloatAvailableSpace)) {
     return false;
   }
 
 #ifdef DEBUG
   {
     static nscoord lastHeight = 0;
     if (CRAZY_SIZE(aLine->BStart())) {
       lastHeight = aLine->BStart();
@@ -5712,36 +5732,37 @@ nsBlockFrame::StyleTextForLineLayout()
 {
   // Return the pointer to an unmodified style text
   return StyleText();
 }
 
 ////////////////////////////////////////////////////////////////////////
 // Float support
 
-nsRect
+LogicalRect
 nsBlockFrame::AdjustFloatAvailableSpace(nsBlockReflowState& aState,
-                                        const nsRect& aFloatAvailableSpace,
+                                        const LogicalRect& aFloatAvailableSpace,
                                         nsIFrame* aFloatFrame)
 {
-  // Compute the available width. By default, assume the width of the
-  // containing block.
+  // Compute the available inline size. By default, assume the inline
+  // size of the containing block.
   nscoord availISize;
   const nsStyleDisplay* floatDisplay = aFloatFrame->StyleDisplay();
+  WritingMode wm = aState.mReflowState.GetWritingMode();
 
   if (NS_STYLE_DISPLAY_TABLE != floatDisplay->mDisplay ||
       eCompatibility_NavQuirks != aState.mPresContext->CompatibilityMode() ) {
     availISize = aState.ContentISize();
   }
   else {
     // This quirk matches the one in nsBlockReflowState::FlowAndPlaceFloat
     // give tables only the available space
     // if they can shrink we may not be constrained to place
     // them in the next line
-    availISize = aFloatAvailableSpace.width;
+    availISize = aFloatAvailableSpace.ISize(wm);
   }
 
   nscoord availBSize = NS_UNCONSTRAINEDSIZE == aState.ContentBSize()
                        ? NS_UNCONSTRAINEDSIZE
                        : std::max(0, aState.ContentBEnd() - aState.mBCoord);
 
 #ifdef DISABLE_FLOAT_BREAKING_IN_COLUMNS
   if (availBSize != NS_UNCONSTRAINEDSIZE &&
@@ -5749,81 +5770,80 @@ nsBlockFrame::AdjustFloatAvailableSpace(
     // Tell the float it has unrestricted block-size, so it won't break.
     // If the float doesn't actually fit in the column it will fail to be
     // placed, and either move to the block-start of the next column or just
     // overflow.
     availBSize = NS_UNCONSTRAINEDSIZE;
   }
 #endif
 
-  WritingMode wm = aState.mReflowState.GetWritingMode();
-  LogicalRect availSpace(wm, aState.ContentIStart(), aState.ContentBStart(),
-                         availISize, availBSize);
-
-  // for now return a physical rect
-  return availSpace.GetPhysicalRect(wm, aState.mContainerWidth);
+  return LogicalRect(wm, aState.ContentIStart(), aState.ContentBStart(),
+                     availISize, availBSize);
 }
 
 nscoord
-nsBlockFrame::ComputeFloatWidth(nsBlockReflowState& aState,
-                                const nsRect&       aFloatAvailableSpace,
+nsBlockFrame::ComputeFloatISize(nsBlockReflowState& aState,
+                                const LogicalRect&  aFloatAvailableSpace,
                                 nsIFrame*           aFloat)
 {
   NS_PRECONDITION(aFloat->GetStateBits() & NS_FRAME_OUT_OF_FLOW,
                   "aFloat must be an out-of-flow frame");
   // Reflow the float.
-  nsRect availSpace = AdjustFloatAvailableSpace(aState, aFloatAvailableSpace,
-                                                aFloat);
-
-  WritingMode wm = aFloat->GetWritingMode();
-  nsHTMLReflowState floatRS(aState.mPresContext, aState.mReflowState, aFloat,
-                            LogicalSize(wm, availSpace.Size()));
-
-  return floatRS.ComputedWidth() + floatRS.ComputedPhysicalBorderPadding().LeftRight() +
-    floatRS.ComputedPhysicalMargin().LeftRight();
+  LogicalRect availSpace = AdjustFloatAvailableSpace(aState,
+                                                     aFloatAvailableSpace,
+                                                     aFloat);
+
+  WritingMode blockWM = aState.mReflowState.GetWritingMode();
+  WritingMode floatWM = aFloat->GetWritingMode();
+  nsHTMLReflowState
+    floatRS(aState.mPresContext, aState.mReflowState, aFloat,
+            availSpace.Size(blockWM).ConvertTo(floatWM, blockWM));
+
+  return floatRS.ComputedSizeWithMarginBorderPadding(blockWM).ISize(blockWM);
 }
 
 void
 nsBlockFrame::ReflowFloat(nsBlockReflowState& aState,
-                          const nsRect&       aAdjustedAvailableSpace,
+                          const LogicalRect&  aAdjustedAvailableSpace,
                           nsIFrame*           aFloat,
-                          nsMargin&           aFloatMargin,
-                          nsMargin&           aFloatOffsets,
+                          LogicalMargin&      aFloatMargin,
+                          LogicalMargin&      aFloatOffsets,
                           bool                aFloatPushedDown,
                           nsReflowStatus&     aReflowStatus)
 {
   NS_PRECONDITION(aFloat->GetStateBits() & NS_FRAME_OUT_OF_FLOW,
                   "aFloat must be an out-of-flow frame");
   // Reflow the float.
   aReflowStatus = NS_FRAME_COMPLETE;
 
+  WritingMode wm = aState.mReflowState.GetWritingMode();
 #ifdef NOISY_FLOAT
   printf("Reflow Float %p in parent %p, availSpace(%d,%d,%d,%d)\n",
-          aFloat, this, 
-          aFloatAvailableSpace.x, aFloatAvailableSpace.y, 
-          aFloatAvailableSpace.width, aFloatAvailableSpace.height
+         aFloat, this,
+         aFloatAvailableSpace.IStart(wm), aFloatAvailableSpace.BStart(wm),
+         aFloatAvailableSpace.ISize(wm), aFloatAvailableSpace.BSize(wm)
   );
 #endif
 
   nsHTMLReflowState
     floatRS(aState.mPresContext, aState.mReflowState, aFloat,
-            LogicalSize(aFloat->GetWritingMode(),
-                        aAdjustedAvailableSpace.Size()));
+            aAdjustedAvailableSpace.Size(wm).ConvertTo(aFloat->GetWritingMode(),
+                                                       wm));
 
   // Normally the mIsTopOfPage state is copied from the parent reflow
   // state.  However, when reflowing a float, if we've placed other
   // floats that force this float *down* or *narrower*, we should unset
   // the mIsTopOfPage state.
   // FIXME: This is somewhat redundant with the |isAdjacentWithTop|
   // variable below, which has the exact same effect.  Perhaps it should
   // be merged into that, except that the test for narrowing here is not
   // about adjacency with the top, so it seems misleading.
   if (floatRS.mFlags.mIsTopOfPage &&
       (aFloatPushedDown ||
-       aAdjustedAvailableSpace.width != aState.ContentISize())) {
+       aAdjustedAvailableSpace.ISize(wm) != aState.ContentISize())) {
     floatRS.mFlags.mIsTopOfPage = false;
   }
 
   // Setup a block reflow context to reflow the float.
   nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState);
 
   // Reflow the float
   bool isAdjacentWithTop = aState.IsAdjacentWithTop();
@@ -5851,48 +5871,51 @@ nsBlockFrame::ReflowFloat(nsBlockReflowS
                     nullptr, floatRS,
                     aReflowStatus, aState);
   } while (clearanceFrame);
 
   if (!NS_FRAME_IS_FULLY_COMPLETE(aReflowStatus) &&
       ShouldAvoidBreakInside(floatRS)) {
     aReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();
   } else if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
-             (NS_UNCONSTRAINEDSIZE == aAdjustedAvailableSpace.height)) {
-    // An incomplete reflow status means we should split the float 
-    // if the height is constrained (bug 145305). 
+             (NS_UNCONSTRAINEDSIZE == aAdjustedAvailableSpace.BSize(wm))) {
+    // An incomplete reflow status means we should split the float
+    // if the height is constrained (bug 145305).
     aReflowStatus = NS_FRAME_COMPLETE;
   }
 
   if (aReflowStatus & NS_FRAME_REFLOW_NEXTINFLOW) {
     aState.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
   }
 
   if (aFloat->GetType() == nsGkAtoms::letterFrame) {
     // We never split floating first letters; an incomplete state for
     // such frames simply means that there is more content to be
     // reflowed on the line.
     if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus)) 
       aReflowStatus = NS_FRAME_COMPLETE;
   }
 
   // Capture the margin and offsets information for the caller
-  aFloatMargin = floatRS.ComputedPhysicalMargin(); // float margins don't collapse
-  aFloatOffsets = floatRS.ComputedPhysicalOffsets();
+  aFloatMargin =
+    // float margins don't collapse
+    floatRS.ComputedLogicalMargin().ConvertTo(wm, floatRS.GetWritingMode());
+  aFloatOffsets =
+    floatRS.ComputedLogicalOffsets().ConvertTo(wm, floatRS.GetWritingMode());
 
   const nsHTMLReflowMetrics& metrics = brc.GetMetrics();
 
   // Set the rect, make sure the view is properly sized and positioned,
   // and tell the frame we're done reflowing it
   // XXXldb This seems like the wrong place to be doing this -- shouldn't
   // we be doing this in nsBlockReflowState::FlowAndPlaceFloat after
   // we've positioned the float, and shouldn't we be doing the equivalent
   // of |PlaceFrameView| here?
-  WritingMode wm = metrics.GetWritingMode();
-  aFloat->SetSize(wm, metrics.Size(wm));
+  WritingMode metricsWM = metrics.GetWritingMode();
+  aFloat->SetSize(metricsWM, metrics.Size(metricsWM));
   if (aFloat->HasView()) {
     nsContainerFrame::SyncFrameViewAfterReflow(aState.mPresContext, aFloat,
                                                aFloat->GetView(),
                                                metrics.VisualOverflow(),
                                                NS_FRAME_NO_MOVE_VIEW);
   }
   // Pass floatRS so the frame hierarchy can be used (redoFloatRS has the same hierarchy)  
   aFloat->DidReflow(aState.mPresContext, &floatRS,
@@ -6824,17 +6847,17 @@ nsBlockFrame::ReflowBullet(nsIFrame* aBu
   aBulletFrame->WillReflow(aState.mPresContext);
   aBulletFrame->Reflow(aState.mPresContext, aMetrics, reflowState, status);
 
   // Get the float available space using our saved state from before we
   // started reflowing the block, so that we ignore any floats inside
   // the block.
   // FIXME: aLineTop isn't actually set correctly by some callers, since
   // they reposition the line.
-  nsRect floatAvailSpace =
+  LogicalRect floatAvailSpace =
     aState.GetFloatAvailableSpaceWithState(aLineTop,
                                            &aState.mFloatManagerStateBefore)
           .mRect;
   // FIXME (bug 25888): need to check the entire region that the first
   // line overlaps, not just the top pixel.
 
   // Place the bullet now.  We want to place the bullet relative to the
   // border-box of the associated block (using the right/left margin of
@@ -6844,35 +6867,33 @@ nsBlockFrame::ReflowBullet(nsIFrame* aBu
   // the edge of the floats is the content-edge of the block, and place
   // the bullet at a position offset from there by the block's padding,
   // the block's border, and the bullet frame's margin.
 
   // IStart from floatAvailSpace gives us the content/float start edge
   // in the current writing mode. Then we subtract out the start
   // border/padding and the bullet's width and margin to offset the position.
   WritingMode wm = rs.GetWritingMode();
-  nscoord containerWidth = floatAvailSpace.XMost();
-  LogicalRect logicalFAS(wm, floatAvailSpace, containerWidth);
   // Get the bullet's margin, converted to our writing mode so that we can
   // combine it with other logical values here.
   LogicalMargin bulletMargin =
     reflowState.ComputedLogicalMargin().ConvertTo(wm, bulletWM);
-  nscoord iStart = logicalFAS.IStart(wm) -
+  nscoord iStart = floatAvailSpace.IStart(wm) -
                    rs.ComputedLogicalBorderPadding().IStart(wm) -
                    bulletMargin.IEnd(wm) -
                    aMetrics.ISize(wm);
 
   // Approximate the bullets position; vertical alignment will provide
   // the final vertical location. We pass our writing-mode here, because
   // it may be different from the bullet frame's mode.
-  nscoord bStart = logicalFAS.BStart(wm);
-  aBulletFrame->SetRect(wm, LogicalRect(wm, LogicalPoint(wm, iStart, bStart),
-                                        LogicalSize(wm, aMetrics.ISize(wm),
-                                                    aMetrics.BSize(wm))),
-                        containerWidth);
+  nscoord bStart = floatAvailSpace.BStart(wm);
+  aBulletFrame->SetRect(wm, LogicalRect(wm, iStart, bStart,
+                                        aMetrics.ISize(wm),
+                                        aMetrics.BSize(wm)),
+                        aState.mContainerWidth);
   aBulletFrame->DidReflow(aState.mPresContext, &aState.mReflowState,
                           nsDidReflowStatus::FINISHED);
 }
 
 // This is used to scan frames for any float placeholders, add their
 // floats to the list represented by aList, and remove the
 // floats from whatever list they might be in. We don't search descendants
 // that are float containing blocks.  Floats that or not children of 'this'
@@ -7015,47 +7036,52 @@ nsBlockFrame::BlockCanIntersectFloats(ns
          !(aFrame->GetStateBits() & NS_BLOCK_FLOAT_MGR);
 }
 
 // Note that this width can vary based on the vertical position.
 // However, the cases where it varies are the cases where the width fits
 // in the available space given, which means that variation shouldn't
 // matter.
 /* static */
-nsBlockFrame::ReplacedElementWidthToClear
-nsBlockFrame::WidthToClearPastFloats(nsBlockReflowState& aState,
-                                     const nsRect& aFloatAvailableSpace,
+nsBlockFrame::ReplacedElementISizeToClear
+nsBlockFrame::ISizeToClearPastFloats(nsBlockReflowState& aState,
+                                     const LogicalRect& aFloatAvailableSpace,
                                      nsIFrame* aFrame)
 {
-  nscoord leftOffset, rightOffset;
+  nscoord inlineStartOffset, inlineEndOffset;
   WritingMode wm = aState.mReflowState.GetWritingMode();
   nsCSSOffsetState offsetState(aFrame, aState.mReflowState.rendContext,
                                aState.mContentArea.Width(wm));
 
-  ReplacedElementWidthToClear result;
+  ReplacedElementISizeToClear result;
   aState.ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace,
-                                              leftOffset, rightOffset);
-  nscoord availWidth = aState.mContentArea.Width(wm) - leftOffset - rightOffset;
+                                              inlineStartOffset,
+                                              inlineEndOffset);
+  nscoord availISize = aState.mContentArea.ISize(wm) -
+                       inlineStartOffset - inlineEndOffset;
 
   // We actually don't want the min width here; see bug 427782; we only
   // want to displace if the width won't compute to a value small enough
   // to fit.
   // All we really need here is the result of ComputeSize, and we
   // could *almost* get that from an nsCSSOffsetState, except for the
   // last argument.
-  LogicalSize availSpace(aFrame->GetWritingMode(),
-                         nsSize(availWidth, NS_UNCONSTRAINEDSIZE));
+  WritingMode frWM = aFrame->GetWritingMode();
+  LogicalSize availSpace = LogicalSize(wm, availISize, NS_UNCONSTRAINEDSIZE).
+                             ConvertTo(frWM, wm);
   nsHTMLReflowState reflowState(aState.mPresContext, aState.mReflowState,
                                 aFrame, availSpace);
-  result.borderBoxWidth = reflowState.ComputedWidth() +
-                          reflowState.ComputedPhysicalBorderPadding().LeftRight();
+  result.borderBoxISize =
+    reflowState.ComputedSizeWithBorderPadding().ConvertTo(wm, frWM).ISize(wm);
   // Use the margins from offsetState rather than reflowState so that
   // they aren't reduced by ignoring margins in overconstrained cases.
-  result.marginLeft  = offsetState.ComputedPhysicalMargin().left;
-  result.marginRight = offsetState.ComputedPhysicalMargin().right;
+  LogicalMargin computedMargin =
+    offsetState.ComputedLogicalMargin().ConvertTo(wm, frWM);
+  result.marginIStart = computedMargin.IStart(wm);
+  result.marginIEnd = computedMargin.IEnd(wm);
   return result;
 }
  
 /* static */
 nsBlockFrame*
 nsBlockFrame::GetNearestAncestorBlock(nsIFrame* aCandidate)
 {
   nsBlockFrame* block = nullptr;
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -309,29 +309,29 @@ public:
   /**
    * Returns whether aFrame is a block frame that will wrap its contents
    * around floats intruding on it from the outside.  (aFrame need not
    * be a block frame, but if it's not, the result will be false.)
    */
   static bool BlockCanIntersectFloats(nsIFrame* aFrame);
 
   /**
-   * Returns the width that needs to be cleared past floats for blocks
-   * that cannot intersect floats.  aState must already have
-   * GetAvailableSpace called on it for the vertical position that we
-   * care about (which need not be its current mY)
+   * Returns the inline size that needs to be cleared past floats for
+   * blocks that cannot intersect floats.  aState must already have
+   * GetAvailableSpace called on it for the block-dir position that we
+   * care about (which need not be its current mBCoord)
    */
-  struct ReplacedElementWidthToClear {
-    nscoord marginLeft, borderBoxWidth, marginRight;
-    nscoord MarginBoxWidth() const
-      { return marginLeft + borderBoxWidth + marginRight; }
+  struct ReplacedElementISizeToClear {
+    nscoord marginIStart, borderBoxISize, marginIEnd;
+    nscoord MarginBoxISize() const
+      { return marginIStart + borderBoxISize + marginIEnd; }
   };
-  static ReplacedElementWidthToClear
-    WidthToClearPastFloats(nsBlockReflowState& aState,
-                           const nsRect& aFloatAvailableSpace,
+  static ReplacedElementISizeToClear
+    ISizeToClearPastFloats(nsBlockReflowState& aState,
+                           const mozilla::LogicalRect& aFloatAvailableSpace,
                            nsIFrame* aFrame);
 
   /**
    * Creates a contination for aFloat and adds it to the list of overflow floats.
    * Also updates aState.mReflowStatus to include the float's incompleteness.
    * Must only be called while this block frame is in reflow.
    * aFloatStatus must be the float's true, unmodified reflow status.
    * 
@@ -600,23 +600,23 @@ protected:
    */
   void ReflowLine(nsBlockReflowState& aState,
                   line_iterator aLine,
                   bool* aKeepReflowGoing);
 
   // Return false if it needs another reflow because of reduced space
   // between floats that are next to it (but not next to its top), and
   // return true otherwise.
-  bool PlaceLine(nsBlockReflowState& aState,
-                   nsLineLayout&       aLineLayout,
-                   line_iterator       aLine,
+  bool PlaceLine(nsBlockReflowState&           aState,
+                   nsLineLayout&               aLineLayout,
+                   line_iterator               aLine,
                    nsFloatManager::SavedState* aFloatStateBeforeLine,
-                   nsRect&             aFloatAvailableSpace, /* in-out */
-                   nscoord&            aAvailableSpaceHeight, /* in-out */
-                   bool*             aKeepReflowGoing);
+                   mozilla::LogicalRect&       aFloatAvailableSpace, //in-out
+                   nscoord&                    aAvailableSpaceHeight, // in-out
+                   bool*                       aKeepReflowGoing);
 
   /**
     * If NS_BLOCK_LOOK_FOR_DIRTY_FRAMES is set, call MarkLineDirty
     * on any line with a child frame that is dirty.
     */
   void LazyMarkLinesDirty();
 
   /**
@@ -664,38 +664,39 @@ protected:
                             bool aAllowPullUp);
 
   void ReflowInlineFrame(nsBlockReflowState& aState,
                          nsLineLayout& aLineLayout,
                          line_iterator aLine,
                          nsIFrame* aFrame,
                          LineReflowStatus* aLineReflowStatus);
 
-  // Compute the available width for a float. 
-  nsRect AdjustFloatAvailableSpace(nsBlockReflowState& aState,
-                                   const nsRect&       aFloatAvailableSpace,
-                                   nsIFrame*           aFloatFrame);
-  // Computes the border-box width of the float
-  nscoord ComputeFloatWidth(nsBlockReflowState& aState,
-                            const nsRect&       aFloatAvailableSpace,
-                            nsIFrame*           aFloat);
+  // Compute the available inline size for a float.
+  mozilla::LogicalRect AdjustFloatAvailableSpace(
+                         nsBlockReflowState&         aState,
+                         const mozilla::LogicalRect& aFloatAvailableSpace,
+                         nsIFrame*                   aFloatFrame);
+  // Computes the border-box inline size of the float
+  nscoord ComputeFloatISize(nsBlockReflowState&         aState,
+                            const mozilla::LogicalRect& aFloatAvailableSpace,
+                            nsIFrame*                   aFloat);
   // An incomplete aReflowStatus indicates the float should be split
   // but only if the available height is constrained.
   // aAdjustedAvailableSpace is the result of calling
   // nsBlockFrame::AdjustFloatAvailableSpace.
-  void ReflowFloat(nsBlockReflowState& aState,
-                   const nsRect&       aAdjustedAvailableSpace,
-                   nsIFrame*           aFloat,
-                   nsMargin&           aFloatMargin,
-                   nsMargin&           aFloatOffsets,
+  void ReflowFloat(nsBlockReflowState&         aState,
+                   const mozilla::LogicalRect& aAdjustedAvailableSpace,
+                   nsIFrame*                   aFloat,
+                   mozilla::LogicalMargin&     aFloatMargin,
+                   mozilla::LogicalMargin&     aFloatOffsets,
                    // Whether the float's position
                    // (aAdjustedAvailableSpace) has been pushed down
                    // due to the presence of other floats.
-                   bool                aFloatPushedDown,
-                   nsReflowStatus&     aReflowStatus);
+                   bool                        aFloatPushedDown,
+                   nsReflowStatus&             aReflowStatus);
 
   //----------------------------------------
   // Methods for pushing/pulling lines/frames
 
   /**
    * Create a next-in-flow, if necessary, for aFrame. If a new frame is
    * created, place it in aLine if aLine is not null.
    * @param aState the block reflow state
@@ -751,17 +752,17 @@ protected:
    * @param aLineBefore a line in 'mLines' (or begin_lines() when
    *        pushing the first line)
    */
   void PushLines(nsBlockReflowState& aState,
                  nsLineList::iterator aLineBefore);
 
   void PropagateFloatDamage(nsBlockReflowState& aState,
                             nsLineBox* aLine,
-                            nscoord aDeltaY);
+                            nscoord aDeltaBCoord);
 
   void CheckFloats(nsBlockReflowState& aState);
 
   //----------------------------------------
   // List handling kludge
 
   // If this returns true, the block it's called on should get the
   // NS_FRAME_HAS_DIRTY_CHILDREN bit set on it by the caller; either directly
--- a/layout/generic/nsBlockReflowContext.cpp
+++ b/layout/generic/nsBlockReflowContext.cpp
@@ -209,30 +209,30 @@ nsBlockReflowContext::ComputeCollapsedBS
   nsFrame::ListTag(stdout, aRS.frame);
   printf(": => %d\n", aMargin->get());
 #endif
 
   return dirtiedLine;
 }
 
 void
-nsBlockReflowContext::ReflowBlock(const nsRect&       aSpace,
+nsBlockReflowContext::ReflowBlock(const LogicalRect&  aSpace,
                                   bool                aApplyBStartMargin,
                                   nsCollapsingMargin& aPrevMargin,
                                   nscoord             aClearance,
                                   bool                aIsAdjacentWithBStart,
                                   nsLineBox*          aLine,
                                   nsHTMLReflowState&  aFrameRS,
                                   nsReflowStatus&     aFrameReflowStatus,
                                   nsBlockReflowState& aState)
 {
   mFrame = aFrameRS.frame;
   mWritingMode = aState.mReflowState.GetWritingMode();
   mContainerWidth = aState.mContainerWidth;
-  mSpace = LogicalRect(mWritingMode, aSpace, mContainerWidth);
+  mSpace = aSpace;
 
   if (!aIsAdjacentWithBStart) {
     aFrameRS.mFlags.mIsTopOfPage = false;  // make sure this is cleared
   }
 
   if (aApplyBStartMargin) {
     mBStartMargin = aPrevMargin;
 
--- a/layout/generic/nsBlockReflowContext.h
+++ b/layout/generic/nsBlockReflowContext.h
@@ -23,25 +23,25 @@ struct nsBlockHorizontalAlign;
  * An encapsulation of the state and algorithm for reflowing block frames.
  */
 class nsBlockReflowContext {
 public:
   nsBlockReflowContext(nsPresContext* aPresContext,
                        const nsHTMLReflowState& aParentRS);
   ~nsBlockReflowContext() { }
 
-  void ReflowBlock(const nsRect&       aSpace,
-                   bool                aApplyBStartMargin,
-                   nsCollapsingMargin& aPrevMargin,
-                   nscoord             aClearance,
-                   bool                aIsAdjacentWithBStart,
-                   nsLineBox*          aLine,
-                   nsHTMLReflowState&  aReflowState,
-                   nsReflowStatus&     aReflowStatus,
-                   nsBlockReflowState& aState);
+  void ReflowBlock(const mozilla::LogicalRect& aSpace,
+                   bool                        aApplyBStartMargin,
+                   nsCollapsingMargin&         aPrevMargin,
+                   nscoord                     aClearance,
+                   bool                        aIsAdjacentWithBStart,
+                   nsLineBox*                  aLine,
+                   nsHTMLReflowState&          aReflowState,
+                   nsReflowStatus&             aReflowStatus,
+                   nsBlockReflowState&         aState);
 
   bool PlaceBlock(const nsHTMLReflowState& aReflowState,
                   bool                     aForceFit,
                   nsLineBox*               aLine,
                   nsCollapsingMargin&      aBEndMarginResult /* out */,
                   nsOverflowAreas&         aOverflowAreas,
                   nsReflowStatus           aReflowStatus);
 
--- a/layout/generic/nsBlockReflowState.cpp
+++ b/layout/generic/nsBlockReflowState.cpp
@@ -124,54 +124,58 @@ nsBlockReflowState::GetConsumedBSize()
   if (mConsumedBSize == NS_INTRINSICSIZE) {
     mConsumedBSize = mBlock->GetConsumedBSize();
   }
 
   return mConsumedBSize;
 }
 
 void
-nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
-                                                         const nsRect& aFloatAvailableSpace,
-                                                         nscoord& aLeftResult,
-                                                         nscoord& aRightResult)
+nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(
+                      nsIFrame* aFrame,
+                      const LogicalRect& aFloatAvailableSpace,
+                      nscoord& aIStartResult,
+                      nscoord& aIEndResult)
 {
-  nsRect contentArea =
-    mContentArea.GetPhysicalRect(mReflowState.GetWritingMode(), mContainerWidth);
+  WritingMode wm = mReflowState.GetWritingMode();
   // The frame is clueless about the float manager and therefore we
   // only give it free space. An example is a table frame - the
   // tables do not flow around floats.
   // However, we can let its margins intersect floats.
-  NS_ASSERTION(aFloatAvailableSpace.x >= contentArea.x, "bad avail space rect x");
-  NS_ASSERTION(aFloatAvailableSpace.width == 0 ||
-               aFloatAvailableSpace.XMost() <= contentArea.XMost(),
-               "bad avail space rect width");
+  NS_ASSERTION(aFloatAvailableSpace.IStart(wm) >= mContentArea.IStart(wm),
+               "bad avail space rect inline-coord");
+  NS_ASSERTION(aFloatAvailableSpace.ISize(wm) == 0 ||
+               aFloatAvailableSpace.IEnd(wm) <= mContentArea.IEnd(wm),
+               "bad avail space rect inline-size");
 
-  nscoord leftOffset, rightOffset;
-  if (aFloatAvailableSpace.width == contentArea.width) {
+  nscoord iStartOffset, iEndOffset;
+  if (aFloatAvailableSpace.ISize(wm) == mContentArea.ISize(wm)) {
     // We don't need to compute margins when there are no floats around.
-    leftOffset = 0;
-    rightOffset = 0;
+    iStartOffset = 0;
+    iEndOffset = 0;
   } else {
-    nsMargin frameMargin;
-    nsCSSOffsetState os(aFrame, mReflowState.rendContext, contentArea.width);
-    frameMargin = os.ComputedPhysicalMargin();
+    LogicalMargin frameMargin(wm);
+    nsCSSOffsetState os(aFrame, mReflowState.rendContext,
+                        mContentArea.ISize(wm));
+    frameMargin =
+      os.ComputedLogicalMargin().ConvertTo(wm, aFrame->GetWritingMode());
 
-    nscoord leftFloatXOffset = aFloatAvailableSpace.x - contentArea.x;
-    leftOffset = std::max(leftFloatXOffset, frameMargin.left) -
-                 frameMargin.left;
-    leftOffset = std::max(leftOffset, 0); // in case of negative margin
-    nscoord rightFloatXOffset =
-      contentArea.XMost() - aFloatAvailableSpace.XMost();
-    rightOffset = std::max(rightFloatXOffset, frameMargin.right) -
-                  frameMargin.right;
-    rightOffset = std::max(rightOffset, 0); // in case of negative margin
+    nscoord iStartFloatIOffset =
+      aFloatAvailableSpace.IStart(wm) - mContentArea.IStart(wm);
+    iStartOffset = std::max(iStartFloatIOffset, frameMargin.IStart(wm)) -
+                   frameMargin.IStart(wm);
+    iStartOffset = std::max(iStartOffset, 0); // in case of negative margin
+    nscoord iEndFloatIOffset =
+      mContentArea.IEnd(wm) - aFloatAvailableSpace.IEnd(wm);
+    iEndOffset = std::max(iEndFloatIOffset, frameMargin.IEnd(wm)) -
+                 frameMargin.IEnd(wm);
+    iEndOffset = std::max(iEndOffset, 0); // in case of negative margin
   }
-  aLeftResult = leftOffset;
-  aRightResult = rightOffset;
+  aIStartResult = iStartOffset;
+  aIEndResult = iEndOffset;
 }
 
 static nscoord
 GetBEndMarginClone(nsIFrame* aFrame,
                    nsRenderingContext* aRenderingContext,
                    const LogicalRect& aContentArea,
                    WritingMode aWritingMode)
 {
@@ -188,96 +192,89 @@ GetBEndMarginClone(nsIFrame* aFrame,
 // Compute the amount of available space for reflowing a block frame
 // at the current Y coordinate. This method assumes that
 // GetAvailableSpace has already been called.
 void
 nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
                                            const nsStyleDisplay* aDisplay,
                                            const nsFlowAreaRect& aFloatAvailableSpace,
                                            bool aBlockAvoidsFloats,
-                                           nsRect& aResult)
+                                           LogicalRect& aResult)
 {
 #ifdef REALLY_NOISY_REFLOW
   printf("CBAS frame=%p has floats %d\n",
          aFrame, aFloatAvailableSpace.mHasFloats);
 #endif
   WritingMode wm = mReflowState.GetWritingMode();
-  LogicalRect result(wm);
-  LogicalRect floatAvailSpace = LogicalRect(wm,
-                                            aFloatAvailableSpace.mRect,
-                                            mContainerWidth); //??mReflowState.AvailableWidth());
-  result.BStart(wm) = mBCoord;
-  result.BSize(wm) = GetFlag(BRS_UNCONSTRAINEDBSIZE)
+  aResult.BStart(wm) = mBCoord;
+  aResult.BSize(wm) = GetFlag(BRS_UNCONSTRAINEDBSIZE)
     ? NS_UNCONSTRAINEDSIZE
     : mReflowState.AvailableBSize() - mBCoord
       - GetBEndMarginClone(aFrame, mReflowState.rendContext, mContentArea, wm);
   // mBCoord might be greater than mBEndEdge if the block's top margin pushes
   // it off the page/column. Negative available height can confuse other code
   // and is nonsense in principle.
 
   // XXX Do we really want this condition to be this restrictive (i.e.,
   // more restrictive than it used to be)?  The |else| here is allowed
   // by the CSS spec, but only out of desperation given implementations,
   // and the behavior it leads to is quite undesirable (it can cause
   // things to become extremely narrow when they'd fit quite well a
   // little bit lower).  Should the else be a quirk or something that
   // applies to a specific set of frame classes and no new ones?
   // If we did that, then for those frames where the condition below is
   // true but nsBlockFrame::BlockCanIntersectFloats is false,
-  // nsBlockFrame::WidthToClearPastFloats would need to use the
+  // nsBlockFrame::ISizeToClearPastFloats would need to use the
   // shrink-wrap formula, max(MIN_ISIZE, min(avail width, PREF_ISIZE))
   // rather than just using MIN_ISIZE.
   NS_ASSERTION(nsBlockFrame::BlockCanIntersectFloats(aFrame) == 
                  !aBlockAvoidsFloats,
                "unexpected replaced width");
   if (!aBlockAvoidsFloats) {
     if (aFloatAvailableSpace.mHasFloats) {
       // Use the float-edge property to determine how the child block
       // will interact with the float.
       const nsStyleBorder* borderStyle = aFrame->StyleBorder();
       switch (borderStyle->mFloatEdge) {
         default:
         case NS_STYLE_FLOAT_EDGE_CONTENT:  // content and only content does runaround of floats
           // The child block will flow around the float. Therefore
           // give it all of the available space.
-          result.IStart(wm) = ContentIStart();
-          result.ISize(wm) = ContentISize();
+          aResult.IStart(wm) = mContentArea.IStart(wm);
+          aResult.ISize(wm) = mContentArea.ISize(wm);
           break;
         case NS_STYLE_FLOAT_EDGE_MARGIN:
           {
             // The child block's margins should be placed adjacent to,
             // but not overlap the float.
-            result.IStart(wm) = floatAvailSpace.IStart(wm);
-            result.ISize(wm) = floatAvailSpace.ISize(wm);
+            aResult.IStart(wm) = aFloatAvailableSpace.mRect.IStart(wm);
+            aResult.ISize(wm) = aFloatAvailableSpace.mRect.ISize(wm);
           }
           break;
       }
     }
     else {
       // Since there are no floats present the float-edge property
       // doesn't matter therefore give the block element all of the
       // available space since it will flow around the float itself.
-      result.IStart(wm) = ContentIStart();
-      result.ISize(wm) = ContentISize();
+      aResult.IStart(wm) = mContentArea.IStart(wm);
+      aResult.ISize(wm) = mContentArea.ISize(wm);
     }
-    aResult = result.GetPhysicalRect(wm, mContainerWidth);
   }
   else {
-    aResult = result.GetPhysicalRect(wm, mContainerWidth);
-    nsRect contentArea =
-      mContentArea.GetPhysicalRect(wm, mContainerWidth);
-    nscoord leftOffset, rightOffset;
+    nscoord iStartOffset, iEndOffset;
     ComputeReplacedBlockOffsetsForFloats(aFrame, aFloatAvailableSpace.mRect,
-                                         leftOffset, rightOffset);
-    aResult.x = contentArea.x + leftOffset;
-    aResult.width = contentArea.width - leftOffset - rightOffset;
+                                         iStartOffset, iEndOffset);
+    aResult.IStart(wm) = mContentArea.IStart(wm) + iStartOffset;
+    aResult.ISize(wm) = mContentArea.ISize(wm) - iStartOffset - iEndOffset;
   }
 
 #ifdef REALLY_NOISY_REFLOW
-  printf("  CBAS: result %d %d %d %d\n", aResult.x, aResult.y, aResult.width, aResult.height);
+  printf("  CBAS: result %d %d %d %d\n", aResult.IStart(wm), aResult.BStart(wm),
+         aResult.ISize(wm), aResult.BSize(wm));
 #endif
 }
 
 nsFlowAreaRect
 nsBlockReflowState::GetFloatAvailableSpaceWithState(
                       nscoord aBCoord,
                       nsFloatManager::SavedState *aState) const
 {
@@ -297,26 +294,27 @@ nsBlockReflowState::GetFloatAvailableSpa
 #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,
                                mContainerWidth);
-  // Keep the width >= 0 for compatibility with nsSpaceManager.
-  if (result.mRect.width < 0)
-    result.mRect.width = 0;
+  // Keep the inline size >= 0 for compatibility with nsSpaceManager.
+  if (result.mRect.ISize(wm) < 0) {
+    result.mRect.ISize(wm) = 0;
+  }
 
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyReflow) {
     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
     printf("GetAvailableSpace: band=%d,%d,%d,%d hasfloats=%d\n",
-           result.mRect.x, result.mRect.y, result.mRect.width,
-           result.mRect.height, result.mHasFloats);
+           result.mRect.IStart(wm), result.mRect.BStart(wm),
+           result.mRect.ISize(wm), result.mRect.BSize(wm), result.mHasFloats);
   }
 #endif
   return result;
 }
 
 nsFlowAreaRect
 nsBlockReflowState::GetFloatAvailableSpaceForBSize(
                       nscoord aBCoord, nscoord aBSize,
@@ -334,25 +332,26 @@ nsBlockReflowState::GetFloatAvailableSpa
     //XXX if the writing modes are different we can't easily assert that
     //    the origin is the same.
   }
 #endif
   nsFlowAreaRect result =
     mFloatManager->GetFlowArea(wm, aBCoord, nsFloatManager::WIDTH_WITHIN_HEIGHT,
                                aBSize, mContentArea, aState, mContainerWidth);
   // Keep the width >= 0 for compatibility with nsSpaceManager.
-  if (result.mRect.width < 0)
-    result.mRect.width = 0;
+  if (result.mRect.ISize(wm) < 0) {
+    result.mRect.ISize(wm) = 0;
+  }
 
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyReflow) {
     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
     printf("GetAvailableSpaceForHeight: space=%d,%d,%d,%d hasfloats=%d\n",
-           result.mRect.x, result.mRect.y, result.mRect.width,
-           result.mRect.height, result.mHasFloats);
+           result.mRect.IStart(wm), result.mRect.BStart(wm),
+           result.mRect.ISize(wm), result.mRect.BSize(wm), result.mHasFloats);
   }
 #endif
   return result;
 }
 
 /*
  * Reconstruct the vertical margin before the line |aLine| in order to
  * do an incremental reflow that begins with |aLine| without reflowing
@@ -517,17 +516,17 @@ nsBlockReflowState::RecoverStateFrom(nsL
 
 // XXXldb This behavior doesn't quite fit with CSS1 and CSS2 --
 // technically we're supposed let the current line flow around the
 // float as well unless it won't fit next to what we already have.
 // But nobody else implements it that way...
 bool
 nsBlockReflowState::AddFloat(nsLineLayout*       aLineLayout,
                              nsIFrame*           aFloat,
-                             nscoord             aAvailableWidth)
+                             nscoord             aAvailableISize)
 {
   NS_PRECONDITION(aLineLayout, "must have line layout");
   NS_PRECONDITION(mBlock->end_lines() != mCurrentLine, "null ptr");
   NS_PRECONDITION(aFloat->GetStateBits() & NS_FRAME_OUT_OF_FLOW,
                   "aFloat must be an out-of-flow frame");
 
   NS_ABORT_IF_FALSE(aFloat->GetParent(), "float must have parent");
   NS_ABORT_IF_FALSE(aFloat->GetParent()->IsFrameOfType(nsIFrame::eBlockFrame),
@@ -568,29 +567,31 @@ nsBlockReflowState::AddFloat(nsLineLayou
 
   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.
-  nsRect floatAvailableSpace = GetFloatAvailableSpace().mRect;
+  LogicalRect floatAvailableSpace = GetFloatAvailableSpace().mRect;
   if (mBelowCurrentLineFloats.IsEmpty() &&
       (aLineLayout->LineIsEmpty() ||
-       mBlock->ComputeFloatWidth(*this, floatAvailableSpace, aFloat)
-       <= aAvailableWidth)) {
+       mBlock->ComputeFloatISize(*this, floatAvailableSpace, aFloat)
+       <= aAvailableISize)) {
     // And then place it
     placed = FlowAndPlaceFloat(aFloat);
     if (placed) {
       // Pass on updated available space to the current inline reflow engine
+      WritingMode wm = mReflowState.GetWritingMode();
       nsFlowAreaRect floatAvailSpace = GetFloatAvailableSpace(mBCoord);
-      nsRect availSpace(nsPoint(floatAvailSpace.mRect.x, mBCoord),
-                        floatAvailSpace.mRect.Size());
-      aLineLayout->UpdateBand(availSpace, aFloat);
+      LogicalRect availSpace(wm, floatAvailSpace.mRect.IStart(wm), mBCoord,
+                             floatAvailSpace.mRect.ISize(wm),
+                             floatAvailSpace.mRect.BSize(wm));
+      aLineLayout->UpdateBand(wm, availSpace, aFloat);
       // Record this float in the current-line list
       mCurrentLineFloats.Append(mFloatCacheFreeList.Alloc(aFloat));
     } else {
       (*aLineLayout->GetLine())->SetHadFloatPushed();
     }
   }
   else {
     // Always claim to be placed; we don't know whether we fit yet, so we
@@ -603,47 +604,53 @@ nsBlockReflowState::AddFloat(nsLineLayou
 
   // Restore coordinate system
   mFloatManager->SetTranslation(oldWM, oPt);
 
   return placed;
 }
 
 bool
-nsBlockReflowState::CanPlaceFloat(nscoord aFloatWidth,
+nsBlockReflowState::CanPlaceFloat(nscoord aFloatISize,
                                   const nsFlowAreaRect& aFloatAvailableSpace)
 {
-  // A float fits at a given vertical position if there are no floats at
-  // its horizontal position (no matter what its width) or if its width
-  // fits in the space remaining after prior floats have been placed.
+  // A float fits at a given block-dir position if there are no floats
+  // at its inline-dir position (no matter what its inline size) or if
+  // its inline size fits in the space remaining after prior floats have
+  // been placed.
   // FIXME: We should allow overflow by up to half a pixel here (bug 21193).
   return !aFloatAvailableSpace.mHasFloats ||
-         aFloatAvailableSpace.mRect.width >= aFloatWidth;
+    aFloatAvailableSpace.mRect.ISize(mReflowState.GetWritingMode()) >=
+      aFloatISize;
 }
 
 static nscoord
-FloatMarginWidth(const nsHTMLReflowState& aCBReflowState,
-                 nscoord aFloatAvailableWidth,
+FloatMarginISize(const nsHTMLReflowState& aCBReflowState,
+                 nscoord aFloatAvailableISize,
                  nsIFrame *aFloat,
                  const nsCSSOffsetState& aFloatOffsetState)
 {
   AutoMaybeDisableFontInflation an(aFloat);
-  WritingMode fosWM = aFloatOffsetState.GetWritingMode();
-  return aFloat->ComputeSize(
-    aCBReflowState.rendContext,
-    fosWM,
-    aCBReflowState.ComputedSize(fosWM),
-    aFloatAvailableWidth,
-    aFloatOffsetState.ComputedLogicalMargin().Size(fosWM),
-    aFloatOffsetState.ComputedLogicalBorderPadding().Size(fosWM) -
-      aFloatOffsetState.ComputedLogicalPadding().Size(fosWM),
-    aFloatOffsetState.ComputedLogicalPadding().Size(fosWM),
-    true).Width(fosWM) +
-  aFloatOffsetState.ComputedPhysicalMargin().LeftRight() +
-  aFloatOffsetState.ComputedPhysicalBorderPadding().LeftRight();
+  WritingMode wm = aFloatOffsetState.GetWritingMode();
+
+  LogicalSize floatSize =
+    aFloat->ComputeSize(
+              aCBReflowState.rendContext,
+              wm,
+              aCBReflowState.ComputedSize(wm),
+              aFloatAvailableISize,
+              aFloatOffsetState.ComputedLogicalMargin().Size(wm),
+              aFloatOffsetState.ComputedLogicalBorderPadding().Size(wm) -
+                aFloatOffsetState.ComputedLogicalPadding().Size(wm),
+              aFloatOffsetState.ComputedLogicalPadding().Size(wm),
+              true);
+
+  return floatSize.ISize(wm) +
+         aFloatOffsetState.ComputedLogicalMargin().IStartEnd(wm) +
+         aFloatOffsetState.ComputedLogicalBorderPadding().IStartEnd(wm);
 }
 
 bool
 nsBlockReflowState::FlowAndPlaceFloat(nsIFrame* aFloat)
 {
   WritingMode wm = mReflowState.GetWritingMode();
   // Save away the Y coordinate before placing the float. We will
   // restore mBCoord at the end after placing the float. This is
@@ -674,41 +681,41 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
   // 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);
   }
     // Get the band of available space
   nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(mBCoord);
-  nsRect adjustedAvailableSpace = mBlock->AdjustFloatAvailableSpace(*this,
-                                    floatAvailableSpace.mRect, aFloat);
+  LogicalRect adjustedAvailableSpace =
+    mBlock->AdjustFloatAvailableSpace(*this, floatAvailableSpace.mRect, aFloat);
 
   NS_ASSERTION(aFloat->GetParent() == mBlock,
                "Float frame has wrong parent");
 
   nsCSSOffsetState offsets(aFloat, mReflowState.rendContext,
                            mReflowState.ComputedWidth());
 
-  nscoord floatMarginWidth = FloatMarginWidth(mReflowState,
-                                              adjustedAvailableSpace.width,
+  nscoord floatMarginISize = FloatMarginISize(mReflowState,
+                                              adjustedAvailableSpace.ISize(wm),
                                               aFloat, offsets);
 
-  nsMargin floatMargin; // computed margin
-  nsMargin floatOffsets;
+  LogicalMargin floatMargin(wm); // computed margin
+  LogicalMargin floatOffsets(wm);
   nsReflowStatus reflowStatus;
 
   // If it's a floating first-letter, we need to reflow it before we
   // know how wide it is (since we don't compute which letters are part
   // of the first letter until reflow!).
   bool isLetter = aFloat->GetType() == nsGkAtoms::letterFrame;
   if (isLetter) {
     mBlock->ReflowFloat(*this, adjustedAvailableSpace, aFloat, floatMargin,
                         floatOffsets, false, reflowStatus);
-    floatMarginWidth = aFloat->GetSize().width + floatMargin.LeftRight();
+    floatMarginISize = aFloat->ISize(wm) + floatMargin.IStartEnd(wm);
     NS_ASSERTION(NS_FRAME_IS_COMPLETE(reflowStatus),
                  "letter frames shouldn't break, and if they do now, "
                  "then they're breaking at the wrong point");
   }
 
   // Find a place to place the float. The CSS2 spec doesn't want
   // floats overlapping each other or sticking out of the containing
   // block if possible (CSS2 spec section 9.5.1, see the rule list).
@@ -722,35 +729,35 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
   // Are we required to place at least part of the float because we're
   // at the top of the page (to avoid an infinite loop of pushing and
   // breaking).
   bool mustPlaceFloat =
     mReflowState.mFlags.mIsTopOfPage && IsAdjacentWithTop();
 
   for (;;) {
     if (mReflowState.AvailableHeight() != NS_UNCONSTRAINEDSIZE &&
-        floatAvailableSpace.mRect.height <= 0 &&
+        floatAvailableSpace.mRect.BSize(wm) <= 0 &&
         !mustPlaceFloat) {
       // No space, nowhere to put anything.
       PushFloatPastBreak(aFloat);
       return false;
     }
 
-    if (CanPlaceFloat(floatMarginWidth, floatAvailableSpace)) {
+    if (CanPlaceFloat(floatMarginISize, floatAvailableSpace)) {
       // We found an appropriate place.
       break;
     }
 
     // Nope. try to advance to the next band.
     if (NS_STYLE_DISPLAY_TABLE != floatDisplay->mDisplay ||
           eCompatibility_NavQuirks != mPresContext->CompatibilityMode() ) {
 
-      mBCoord += floatAvailableSpace.mRect.height;
-      if (adjustedAvailableSpace.height != NS_UNCONSTRAINEDSIZE) {
-        adjustedAvailableSpace.height -= floatAvailableSpace.mRect.height;
+      mBCoord += floatAvailableSpace.mRect.BSize(wm);
+      if (adjustedAvailableSpace.BSize(wm) != NS_UNCONSTRAINEDSIZE) {
+        adjustedAvailableSpace.BSize(wm) -= floatAvailableSpace.mRect.BSize(wm);
       }
       floatAvailableSpace = GetFloatAvailableSpace(mBCoord);
     } else {
       // This quirk matches the one in nsBlockFrame::AdjustFloatAvailableSpace
       // IE handles float tables in a very special way
 
       // see if the previous float is also a table and has "align"
       nsFloatCache* fc = mCurrentLineFloats.Head();
@@ -780,110 +787,121 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
               // since we cannot evangelize the world
               break;
             }
           }
         }
       }
 
       // the table does not fit anymore in this line so advance to next band 
-      mBCoord += floatAvailableSpace.mRect.height;
+      mBCoord += floatAvailableSpace.mRect.BSize(wm);
       // To match nsBlockFrame::AdjustFloatAvailableSpace, we have to
       // get a new width for the new band.
       floatAvailableSpace = GetFloatAvailableSpace(mBCoord);
       adjustedAvailableSpace = mBlock->AdjustFloatAvailableSpace(*this,
                                  floatAvailableSpace.mRect, aFloat);
-      floatMarginWidth = FloatMarginWidth(mReflowState,
-                                          adjustedAvailableSpace.width,
+      floatMarginISize = FloatMarginISize(mReflowState,
+                                          adjustedAvailableSpace.ISize(wm),
                                           aFloat, offsets);
     }
 
     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 an x and y coordinate to the float.
-  nscoord floatX, floatY;
-  if (NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) {
-    floatX = floatAvailableSpace.mRect.x;
+  // Assign inline and block dir coordinates to the float.
+  LogicalPoint floatPos(wm);
+  if ((NS_STYLE_FLOAT_LEFT == floatDisplay->mFloats) == wm.IsBidiLTR()) {
+    floatPos.I(wm) = floatAvailableSpace.mRect.IStart(wm);
   }
   else {
     if (!keepFloatOnSameLine) {
-      floatX = floatAvailableSpace.mRect.XMost() - floatMarginWidth;
-    } 
+      floatPos.I(wm) = floatAvailableSpace.mRect.IEnd(wm) - floatMarginISize;
+    }
     else {
       // this is the IE quirk (see few lines above)
       // the table is kept in the same line: don't let it overlap the
-      // previous float 
-      floatX = floatAvailableSpace.mRect.x;
+      // previous float
+      floatPos.I(wm) = floatAvailableSpace.mRect.IStart(wm);
     }
   }
   // CSS2 spec, 9.5.1 rule [4]: "A floating box's outer top may not
   // be higher than the top of its containing block."  (Since the
   // containing block is the content edge of the block box, this
   // means the margin edge of the float can't be higher than the
   // content edge of the block that contains it.)
-  floatY = std::max(mBCoord, ContentBStart());
+  floatPos.B(wm) = std::max(mBCoord, ContentBStart());
 
   // Reflow the float after computing its vertical position so it knows
   // where to break.
   if (!isLetter) {
     bool pushedDown = mBCoord != saveBCoord;
     mBlock->ReflowFloat(*this, adjustedAvailableSpace, aFloat, floatMargin,
                         floatOffsets, pushedDown, reflowStatus);
   }
   if (aFloat->GetPrevInFlow())
-    floatMargin.top = 0;
+    floatMargin.BStart(wm) = 0;
   if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus))
-    floatMargin.bottom = 0;
+    floatMargin.BEnd(wm) = 0;
 
   // In the case that we're in columns and not splitting floats, we need
   // to check here that the float's height fit, and if it didn't, bail.
   // (This code is only for DISABLE_FLOAT_BREAKING_IN_COLUMNS .)
   //
   // Likewise, if none of the float fit, and it needs to be pushed in
   // its entirety to the next page (NS_FRAME_IS_TRUNCATED or
   // NS_INLINE_IS_BREAK_BEFORE), we need to do the same.
   if ((ContentBSize() != NS_UNCONSTRAINEDSIZE &&
-       adjustedAvailableSpace.height == NS_UNCONSTRAINEDSIZE &&
+       adjustedAvailableSpace.BSize(wm) == NS_UNCONSTRAINEDSIZE &&
        !mustPlaceFloat &&
-       aFloat->GetSize().height + floatMargin.TopBottom() >
-         ContentBEnd() - floatY) ||
+       aFloat->BSize(wm) + floatMargin.BStartEnd(wm) >
+       ContentBEnd() - floatPos.B(wm)) ||
       NS_FRAME_IS_TRUNCATED(reflowStatus) ||
       NS_INLINE_IS_BREAK_BEFORE(reflowStatus)) {
     PushFloatPastBreak(aFloat);
     return false;
   }
 
   // We can't use aFloat->ShouldAvoidBreakInside(mReflowState) here since
   // its mIsTopOfPage may be true even though the float isn't at the
-  // top when floatY > 0.
+  // top when floatPos.B(wm) > 0.
   if (ContentBSize() != NS_UNCONSTRAINEDSIZE &&
-      !mustPlaceFloat && (!mReflowState.mFlags.mIsTopOfPage || floatY > 0) &&
+      !mustPlaceFloat &&
+      (!mReflowState.mFlags.mIsTopOfPage || floatPos.B(wm) > 0) &&
       NS_STYLE_PAGE_BREAK_AVOID == aFloat->StyleDisplay()->mBreakInside &&
       (!NS_FRAME_IS_FULLY_COMPLETE(reflowStatus) ||
-       aFloat->GetSize().height + floatMargin.TopBottom() >
-       ContentBEnd() - floatY) &&
+       aFloat->BSize(wm) + floatMargin.BStartEnd(wm) >
+       ContentBEnd() - floatPos.B(wm)) &&
       !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
-  nsPoint origin(floatMargin.left + floatX,
-                 floatMargin.top + floatY);
+
+  //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);
 
   // If float is relatively positioned, factor that in as well
-  nsHTMLReflowState::ApplyRelativePositioning(aFloat, floatOffsets, &origin);
+  nsHTMLReflowState::ApplyRelativePositioning(aFloat,
+                                             floatOffsets.GetPhysicalMargin(wm),
+                                              &origin);
 
   // 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;
   if (moved) {
     aFloat->SetPosition(origin);
     nsContainerFrame::PositionFrameView(aFloat);
@@ -892,23 +910,23 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
 
   // Update the float combined area state
   // XXX Floats should really just get invalidated here if necessary
   mFloatOverflowAreas.UnionWith(aFloat->GetOverflowAreas() + origin);
 
   // Place the float in the float manager
   // calculate region
   LogicalRect region =
-    nsFloatManager::CalculateRegionFor(wm, aFloat,
-                                       LogicalMargin(wm, floatMargin),
+    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) &&
       (NS_UNCONSTRAINEDSIZE != ContentBSize())) {
-    region.BSize(wm) = std::max(region.BSize(wm), ContentBSize() - floatY);
+    region.BSize(wm) = std::max(region.BSize(wm),
+                                ContentBSize() - floatPos.B(wm));
   }
   DebugOnly<nsresult> rv = mFloatManager->AddFloat(aFloat, region, wm,
                                                    mContainerWidth);
   NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "bad float placement");
   // store region
   nsFloatManager::StoreRegionFor(wm, aFloat, region, mContainerWidth);
 
   // If the float's dimensions have changed, note the damage in the
@@ -1040,37 +1058,37 @@ nsBlockReflowState::ClearFloats(nscoord 
                                            mContainerWidth, 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 WidthToClearPastFloats, which is
+        // We check this before calling ISizeToClearPastFloats, which is
         // somewhat expensive.
         break;
       }
-      nsBlockFrame::ReplacedElementWidthToClear replacedWidth =
-        nsBlockFrame::WidthToClearPastFloats(*this, floatAvailableSpace.mRect,
+      nsBlockFrame::ReplacedElementISizeToClear replacedISize =
+        nsBlockFrame::ISizeToClearPastFloats(*this, floatAvailableSpace.mRect,
                                              aReplacedBlock);
-      if (std::max(floatAvailableSpace.mRect.x -
-                    mContentArea.X(wm, mContainerWidth),
-                   replacedWidth.marginLeft) +
-            replacedWidth.borderBoxWidth +
-            std::max(mContentArea.XMost(wm, mContainerWidth) -
-                      floatAvailableSpace.mRect.XMost(),
-                     replacedWidth.marginRight) <=
-          mContentArea.Width(wm)) {
+      if (std::max(floatAvailableSpace.mRect.IStart(wm) -
+                    mContentArea.IStart(wm),
+                   replacedISize.marginIStart) +
+            replacedISize.borderBoxISize +
+            std::max(mContentArea.IEnd(wm) -
+                     floatAvailableSpace.mRect.IEnd(wm),
+                     replacedISize.marginIEnd) <=
+          mContentArea.ISize(wm)) {
         break;
       }
       // See the analogous code for inlines in nsBlockFrame::DoReflowInlineFrames
-      if (floatAvailableSpace.mRect.height > 0) {
+      if (floatAvailableSpace.mRect.BSize(wm) > 0) {
         // See if there's room in the next band.
-        newBCoord += floatAvailableSpace.mRect.height;
+        newBCoord += floatAvailableSpace.mRect.BSize(wm);
       } else {
         if (mReflowState.AvailableHeight() != NS_UNCONSTRAINEDSIZE) {
           // Stop trying to clear here; we'll just get pushed to the
           // next column or page and try again there.
           break;
         }
         NS_NOTREACHED("avail space rect with zero height!");
         newBCoord += 1;
--- a/layout/generic/nsBlockReflowState.h
+++ b/layout/generic/nsBlockReflowState.h
@@ -108,26 +108,26 @@ public:
   nscoord GetConsumedBSize();
 
   // Reconstruct the previous block-end margin that goes before |aLine|.
   void ReconstructMarginBefore(nsLineList::iterator aLine);
 
   // Caller must have called GetAvailableSpace for the correct position
   // (which need not be the current mBCoord).
   void ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame,
-                                            const nsRect& aFloatAvailableSpace,
-                                            nscoord& aLeftResult,
-                                            nscoord& aRightResult);
+                          const mozilla::LogicalRect& aFloatAvailableSpace,
+                                            nscoord&  aIStartResult,
+                                            nscoord&  aIEndResult);
 
   // Caller must have called GetAvailableSpace for the current mBCoord
   void ComputeBlockAvailSpace(nsIFrame* aFrame,
                               const nsStyleDisplay* aDisplay,
                               const nsFlowAreaRect& aFloatAvailableSpace,
                               bool aBlockAvoidsFloats,
-                              nsRect& aResult);
+                              mozilla::LogicalRect& aResult);
 
 protected:
   void RecoverFloats(nsLineList::iterator aLine, nscoord aDeltaBCoord);
 
 public:
   void RecoverStateFrom(nsLineList::iterator aLine, nscoord aDeltaBCoord);
 
   void AdvanceToNextLine() {
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -139,21 +139,18 @@ nsFloatManager::GetFlowArea(WritingMode 
     floatCount = mFloats.Length();
   }
 
   // If there are no floats at all, or we're below the last one, return
   // quickly.
   if (floatCount == 0 ||
       (mFloats[floatCount-1].mLeftBEnd <= blockStart &&
        mFloats[floatCount-1].mRightBEnd <= blockStart)) {
-    //XXX temporary!
-    LogicalRect rect(aWM, aContentArea.IStart(aWM), aBOffset,
-                     aContentArea.ISize(aWM), aBSize);
-    nsRect phys = rect.GetPhysicalRect(aWM, aContainerWidth);
-    return nsFlowAreaRect(phys.x, phys.y, phys.width, phys.height, false);
+    return nsFlowAreaRect(aWM, aContentArea.IStart(aWM), aBOffset,
+                          aContentArea.ISize(aWM), aBSize, false);
   }
 
   nscoord blockEnd;
   if (aBSize == nscoord_MAX) {
     // This warning (and the two below) are possible to hit on pages
     // with really large objects.
     NS_WARN_IF_FALSE(aInfoType == BAND_FROM_POINT,
                      "bad height");
@@ -233,24 +230,21 @@ nsFloatManager::GetFlowArea(WritingMode 
           inlineEnd = inlineStartEdge;
           // See above.
           haveFloats = true;
         }
       }
     }
   }
 
-  nscoord height = (blockEnd == nscoord_MAX) ?
-                    nscoord_MAX : (blockEnd - blockStart);
-  //XXX temporary!
-  LogicalRect rect(aWM,
-                   inlineStart - origin.I(aWM), blockStart - origin.B(aWM),
-                   inlineEnd - inlineStart, height);
-  nsRect phys = rect.GetPhysicalRect(aWM, aContainerWidth);
-  return nsFlowAreaRect(phys.x, phys.y, phys.width, phys.height, haveFloats);
+  nscoord blockSize = (blockEnd == nscoord_MAX) ?
+                       nscoord_MAX : (blockEnd - blockStart);
+  return nsFlowAreaRect(aWM,
+                        inlineStart - origin.I(aWM), blockStart - origin.B(aWM),
+                        inlineEnd - inlineStart, 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!");
--- a/layout/generic/nsFloatManager.h
+++ b/layout/generic/nsFloatManager.h
@@ -25,23 +25,25 @@ class nsPresContext;
 /**
  * The available space for content not occupied by floats is divided
  * into a sequence of rectangles in the block direction.  However, we
  * need to know not only the rectangle, but also whether it was reduced
  * (from the content rectangle) by floats that actually intruded into
  * the content rectangle.
  */
 struct nsFlowAreaRect {
-  nsRect mRect;
+  mozilla::LogicalRect mRect;
   bool mHasFloats;
 
-  nsFlowAreaRect(nscoord aICoord, nscoord aBCoord,
+  nsFlowAreaRect(mozilla::WritingMode aWritingMode,
+                 nscoord aICoord, nscoord aBCoord,
                  nscoord aISize, nscoord aBSize,
                  bool aHasFloats)
-    : mRect(aICoord, aBCoord, aISize, aBSize), mHasFloats(aHasFloats) {}
+    : mRect(aWritingMode, aICoord, aBCoord, aISize, aBSize)
+    , mHasFloats(aHasFloats) {}
 };
 
 #define NS_FLOAT_MANAGER_CACHE_SIZE 4
 
 class nsFloatManager {
 public:
   explicit nsFloatManager(nsIPresShell* aPresShell, mozilla::WritingMode aWM);
   ~nsFloatManager();
--- a/layout/generic/nsLineBox.h
+++ b/layout/generic/nsLineBox.h
@@ -441,16 +441,22 @@ public:
   void AppendFloats(nsFloatCacheFreeList& aFreeList);
   bool RemoveFloat(nsIFrame* aFrame);
 
   // Combined area is the area of the line that should influence the
   // overflow area of its parent block.  The combined area should be
   // used for painting-related things, but should never be used for
   // layout (except for handling of 'overflow').
   void SetOverflowAreas(const nsOverflowAreas& aOverflowAreas);
+  mozilla::LogicalRect GetOverflowArea(nsOverflowType aType,
+                                       mozilla::WritingMode aWM,
+                                       nscoord aContainerWidth)
+  {
+    return mozilla::LogicalRect(aWM, GetOverflowArea(aType), aContainerWidth);
+  }
   nsRect GetOverflowArea(nsOverflowType aType) {
     return mData ? mData->mOverflowAreas.Overflow(aType) : GetPhysicalBounds();
   }
   nsOverflowAreas GetOverflowAreas() {
     if (mData) {
       return mData->mOverflowAreas;
     }
     nsRect bounds = GetPhysicalBounds();
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -265,23 +265,27 @@ nsLineLayout::EndLineReflow()
 }
 
 // XXX swtich to a single mAvailLineWidth that we adjust as each frame
 // on the line is placed. Each span can still have a per-span mICoord that
 // tracks where a child frame is going in its span; they don't need a
 // per-span mIStart?
 
 void
-nsLineLayout::UpdateBand(const nsRect& aNewAvailSpace,
+nsLineLayout::UpdateBand(WritingMode aWM,
+                         const LogicalRect& aNewAvailSpace,
                          nsIFrame* aFloatFrame)
 {
   WritingMode lineWM = mRootSpan->mWritingMode;
-  LogicalRect availSpace(lineWM, aNewAvailSpace, mContainerWidth);
+  // need to convert to our writing mode, because we might have a different
+  // mode from the caller due to dir: auto
+  LogicalRect availSpace = aNewAvailSpace.ConvertTo(lineWM, aWM,
+                                                    mContainerWidth);
 #ifdef REALLY_NOISY_REFLOW
-  printf("nsLL::UpdateBand %d, %d, %d, %d, (logical %d, %d, %d, %d); frame=%p\n  will set mImpacted to true\n",
+  printf("nsLL::UpdateBand %d, %d, %d, %d, (converted to %d, %d, %d, %d); frame=%p\n  will set mImpacted to true\n",
          aNewAvailSpace.x, aNewAvailSpace.y,
          aNewAvailSpace.width, aNewAvailSpace.height,
          availSpace.IStart(lineWM), availSpace.BStart(lineWM),
          availSpace.ISize(lineWM), availSpace.BSize(lineWM),
          aFloatFrame);
 #endif
 #ifdef DEBUG
   if ((availSpace.ISize(lineWM) != NS_UNCONSTRAINEDSIZE) &&
@@ -295,31 +299,32 @@ nsLineLayout::UpdateBand(const nsRect& a
     nsFrame::ListTag(stdout, mBlockReflowState->frame);
     printf(": UpdateBand: bad caller: BSize WAS %d(0x%x)\n",
            availSpace.BSize(lineWM), availSpace.BSize(lineWM));
   }
 #endif
 
   // Compute the difference between last times width and the new width
   NS_WARN_IF_FALSE(mRootSpan->mIEnd != NS_UNCONSTRAINEDSIZE &&
-                   aNewAvailSpace.width != NS_UNCONSTRAINEDSIZE,
-                   "have unconstrained width; this should only result from "
-                   "very large sizes, not attempts at intrinsic width "
+                   availSpace.ISize(lineWM) != NS_UNCONSTRAINEDSIZE,
+                   "have unconstrained inline size; this should only result "
+                   "from very large sizes, not attempts at intrinsic width "
                    "calculation");
   // The root span's mIStart moves to aICoord
   nscoord deltaICoord = availSpace.IStart(lineWM) - mRootSpan->mIStart;
-  // The width of all spans changes by this much (the root span's
-  // mIEnd moves to aICoord + aISize, its new width is aISize)
+  // The inline size of all spans changes by this much (the root span's
+  // mIEnd moves to aICoord + aISize, its new inline size is aISize)
   nscoord deltaISize = availSpace.ISize(lineWM) -
                        (mRootSpan->mIEnd - mRootSpan->mIStart);
 #ifdef NOISY_REFLOW
   nsFrame::ListTag(stdout, mBlockReflowState->frame);
   printf(": UpdateBand: %d,%d,%d,%d deltaISize=%d deltaICoord=%d\n",
-         aNewAvailSpace.IStart(lineWM), aNewAvailSpace.BStart(lineWM),
-         aNewAvailSpace.ISize(lineWM), aNewAvailSpace.BSize(lineWM), deltaISize, deltaICoord);
+         availSpace.IStart(lineWM), availSpace.BStart(lineWM),
+         availSpace.ISize(lineWM), availSpace.BSize(lineWM),
+         deltaISize, deltaICoord);
 #endif
 
   // Update the root span position
   mRootSpan->mIStart += deltaICoord;
   mRootSpan->mIEnd += deltaICoord;
   mRootSpan->mICoord += deltaICoord;
 
   // Now update the right edges of the open spans to account for any
--- a/layout/generic/nsLineLayout.h
+++ b/layout/generic/nsLineLayout.h
@@ -57,17 +57,18 @@ public:
   /**
    * Called when a float has been placed. This method updates the
    * inline frame and span data to account for any change in positions
    * due to available space for the line boxes changing.
    * @param aX/aY/aWidth/aHeight are the new available
    * space rectangle, relative to the containing block.
    * @param aFloatFrame the float frame that was placed.
    */
-  void UpdateBand(const nsRect& aNewAvailableSpace,
+  void UpdateBand(mozilla::WritingMode aWM,
+                  const mozilla::LogicalRect& aNewAvailableSpace,
                   nsIFrame* aFloatFrame);
 
   void BeginSpan(nsIFrame* aFrame, const nsHTMLReflowState* aSpanReflowState,
                  nscoord aLeftEdge, nscoord aRightEdge, nscoord* aBaseline);
 
   // Returns the width of the span
   nscoord EndSpan(nsIFrame* aFrame);
 
@@ -145,19 +146,19 @@ public:
   void SetLineEndsInBR(bool aOn) 
   { 
     mLineEndsInBR = aOn;
   }
 
   //----------------------------------------
   // Inform the line-layout about the presence of a floating frame
   // XXX get rid of this: use get-frame-type?
-  bool AddFloat(nsIFrame* aFloat, nscoord aAvailableWidth)
+  bool AddFloat(nsIFrame* aFloat, nscoord aAvailableISize)
   {
-    return mBlockRS->AddFloat(this, aFloat, aAvailableWidth);
+    return mBlockRS->AddFloat(this, aFloat, aAvailableISize);
   }
 
   void SetTrimmableISize(nscoord aTrimmableISize) {
     mTrimmableISize = aTrimmableISize;
   }
 
   //----------------------------------------