Bug 1079151 - patch 1 - Update constraint calculations in nsHTMLReflowState to work with logical coordinates. r=smontagu
authorJonathan Kew <jkew@mozilla.com>
Fri, 05 Jun 2015 08:47:09 +0100
changeset 247328 e641f522e5ae489b6a25f235ce6a40a44e8d91e2
parent 247327 42874d3980480f966c2ddd7c7e515f5b721c23a2
child 247329 ddf49050d29e17ffd2a918e516ae0fd34fd8593f
push id28864
push userkwierso@gmail.com
push dateFri, 05 Jun 2015 21:49:37 +0000
treeherdermozilla-central@97a39c939c51 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmontagu
bugs1079151
milestone41.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 1079151 - patch 1 - Update constraint calculations in nsHTMLReflowState to work with logical coordinates. r=smontagu
layout/generic/nsHTMLReflowState.cpp
layout/generic/nsHTMLReflowState.h
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -997,55 +997,55 @@ nsHTMLReflowState::GetHypotheticalBoxCon
     for (state = parentReflowState; state && state->frame != aFrame;
          state = state->parentReflowState) {
       /* do nothing */
     }
   } else {
     state = nullptr;
   }
 
-  WritingMode wm = GetWritingMode();
+  WritingMode wm = aFrame->GetWritingMode();
   if (state) {
     WritingMode stateWM = state->GetWritingMode();
     aCBIStartEdge =
       state->ComputedLogicalBorderPadding().ConvertTo(wm, stateWM).IStart(wm);
     aCBISize = state->ComputedSize(wm).ISize(wm);
   } else {
     /* Didn't find a reflow state for aFrame.  Just compute the information we
        want, on the assumption that aFrame already knows its size.  This really
        ought to be true by now. */
     NS_ASSERTION(!(aFrame->GetStateBits() & NS_FRAME_IN_REFLOW),
                  "aFrame shouldn't be in reflow; we'll lie if it is");
     LogicalMargin borderPadding = aFrame->GetLogicalUsedBorderAndPadding(wm);
     aCBIStartEdge = borderPadding.IStart(wm);
-    aCBISize = aFrame->GetLogicalSize(wm).ISize(wm) -
-               borderPadding.IStartEnd(wm);
+    aCBISize = aFrame->ISize(wm) - borderPadding.IStartEnd(wm);
   }
 
   return aFrame;
 }
 
 // When determining the hypothetical box that would have been if the element
-// had been in the flow we may not be able to exactly determine both the left
-// and right edges. For example, if the element is a non-replaced inline-level
-// element we would have to reflow it in order to determine it desired width.
-// In that case depending on the progression direction either the left or
-// right edge would be marked as not being exact
+// had been in the flow we may not be able to exactly determine both the IStart
+// and IEnd edges. For example, if the element is a non-replaced inline-level
+// element we would have to reflow it in order to determine its desired ISize.
+// In that case depending on the progression direction either the IStart or
+// IEnd edge would be marked as not being exact.
 struct nsHypotheticalBox {
-  // offsets from left edge of containing block (which is a padding edge)
-  nscoord       mLeft, mRight;
-  // offset from top edge of containing block (which is a padding edge)
-  nscoord       mTop;
+  // offsets from inline-start edge of containing block (which is a padding edge)
+  nscoord       mIStart, mIEnd;
+  // offset from block-start edge of containing block (which is a padding edge)
+  nscoord       mBStart;
+  WritingMode   mWritingMode;
 #ifdef DEBUG
-  bool          mLeftIsExact, mRightIsExact;
+  bool          mIStartIsExact, mIEndIsExact;
 #endif
 
   nsHypotheticalBox() {
 #ifdef DEBUG
-    mLeftIsExact = mRightIsExact = false;
+    mIStartIsExact = mIEndIsExact = false;
 #endif
   }
 };
 
 static bool
 GetIntrinsicSizeFor(nsIFrame* aFrame, nsSize& aIntrinsicSize, nsIAtom* aFrameType)
 {
   // See if it is an image frame
@@ -1159,37 +1159,42 @@ static bool AreAllEarlierInFlowFramesEmp
     }
   }
   *aFound = false;
   return true;
 }
 
 // Calculate the hypothetical box that the element would have if it were in
 // the flow. The values returned are relative to the padding edge of the
-// absolute containing block
-// aContainingBlock is the placeholder's containing block (XXX rename it?)
+// absolute containing block, in the actual containing block's writing mode.
 // cbrs->frame is the actual containing block
 void
 nsHTMLReflowState::CalculateHypotheticalBox(nsPresContext*    aPresContext,
                                             nsIFrame*         aPlaceholderFrame,
-                                            nsIFrame*         aContainingBlock,
-                                            nscoord           aBlockIStartContentEdge,
-                                            nscoord           aBlockContentISize,
                                             const nsHTMLReflowState* cbrs,
                                             nsHypotheticalBox& aHypotheticalBox,
                                             nsIAtom*          aFrameType)
 {
   NS_ASSERTION(mStyleDisplay->mOriginalDisplay != NS_STYLE_DISPLAY_NONE,
                "mOriginalDisplay has not been properly initialized");
 
+  // Find the nearest containing block frame to the placeholder frame,
+  // and its inline-start edge and width.
+  nscoord blockIStartContentEdge, blockContentISize;
+  nsIFrame* containingBlock =
+    GetHypotheticalBoxContainer(aPlaceholderFrame, blockIStartContentEdge,
+                                blockContentISize);
+
   // If it's a replaced element and it has a 'auto' value for
   //'inline size', see if we can get the intrinsic size. This will allow
   // us to exactly determine both the inline edges
-  WritingMode cbWM = cbrs->GetWritingMode();
-  nsStyleCoord styleISize = mStylePosition->ISize(cbWM);
+  WritingMode wm = containingBlock->GetWritingMode();
+  aHypotheticalBox.mWritingMode = wm;
+
+  nsStyleCoord styleISize = mStylePosition->ISize(wm);
   bool isAutoISize = styleISize.GetUnit() == eStyleUnit_Auto;
   nsSize      intrinsicSize;
   bool        knowIntrinsicSize = false;
   if (NS_FRAME_IS_REPLACED(mFrameType) && isAutoISize) {
     // See if we can get the intrinsic size of the element
     knowIntrinsicSize = GetIntrinsicSizeFor(frame, intrinsicSize, aFrameType);
   }
 
@@ -1206,79 +1211,92 @@ nsHTMLReflowState::CalculateHypothetical
   } else {
     // It's either a replaced inline-level element or a block-level element
 
     // Determine the total amount of inline direction
     // border/padding/margin that the element would have had if it had
     // been in the flow. Note that we ignore any 'auto' and 'inherit'
     // values
     nscoord insideBoxSizing, outsideBoxSizing;
-    CalculateInlineBorderPaddingMargin(aBlockContentISize,
+    CalculateInlineBorderPaddingMargin(blockContentISize,
                                        &insideBoxSizing, &outsideBoxSizing);
 
     if (NS_FRAME_IS_REPLACED(mFrameType) && isAutoISize) {
       // It's a replaced element with an 'auto' inline size so the box
       // inline size is its intrinsic size plus any border/padding/margin
       if (knowIntrinsicSize) {
-        boxISize = LogicalSize(cbWM, intrinsicSize).ISize(cbWM) +
+        boxISize = LogicalSize(wm, intrinsicSize).ISize(wm) +
                    outsideBoxSizing + insideBoxSizing;
         knowBoxISize = true;
       }
 
     } else if (isAutoISize) {
       // The box inline size is the containing block inline size
-      boxISize = aBlockContentISize;
+      boxISize = blockContentISize;
       knowBoxISize = true;
 
     } else {
       // We need to compute it. It's important we do this, because if it's
       // percentage based this computed value may be different from the computed
       // value calculated using the absolute containing block width
-      boxISize = ComputeISizeValue(aBlockContentISize,
+      boxISize = ComputeISizeValue(blockContentISize,
                                    insideBoxSizing, outsideBoxSizing,
                                    styleISize) +
                  insideBoxSizing + outsideBoxSizing;
       knowBoxISize = true;
     }
   }
 
-  // Get the 'direction' of the block
-  const nsStyleVisibility* blockVis = aContainingBlock->StyleVisibility();
-
   // Get the placeholder x-offset and y-offset in the coordinate
   // space of its containing block
   // XXXbz the placeholder is not fully reflowed yet if our containing block is
   // relatively positioned...
-  nsPoint placeholderOffset = aPlaceholderFrame->GetOffsetTo(aContainingBlock);
+  WritingMode cbwm = cbrs->GetWritingMode();
+  nscoord containerWidth = containingBlock->GetStateBits() & NS_FRAME_IN_REFLOW
+    ? cbrs->ComputedWidth() +
+      cbrs->ComputedLogicalBorderPadding().LeftRight(cbwm)
+    : containingBlock->GetSize().width;
+  LogicalPoint placeholderOffset(wm, aPlaceholderFrame->GetOffsetTo(containingBlock),
+                                 containerWidth);
 
-  // First, determine the hypothetical box's mTop.  We want to check the
-  // content insertion frame of aContainingBlock for block-ness, but make
+  // XXX hack to correct for lack of LogicalPoint bidi support in vertical mode
+  if (wm.IsVertical() && !wm.IsBidiLTR()) {
+    placeholderOffset.I(wm) = cbrs->ComputedHeight() +
+      cbrs->ComputedLogicalBorderPadding().TopBottom(cbwm) -
+      placeholderOffset.I(wm);
+  }
+
+  // First, determine the hypothetical box's mBStart.  We want to check the
+  // content insertion frame of containingBlock for block-ness, but make
   // sure to compute all coordinates in the coordinate system of
-  // aContainingBlock.
+  // containingBlock.
   nsBlockFrame* blockFrame =
-    nsLayoutUtils::GetAsBlock(aContainingBlock->GetContentInsertionFrame());
+    nsLayoutUtils::GetAsBlock(containingBlock->GetContentInsertionFrame());
   if (blockFrame) {
-    nscoord blockYOffset = blockFrame->GetOffsetTo(aContainingBlock).y;
+    LogicalPoint blockOffset(wm, blockFrame->GetOffsetTo(containingBlock), 0);
     bool isValid;
     nsBlockInFlowLineIterator iter(blockFrame, aPlaceholderFrame, &isValid);
     if (!isValid) {
       // Give up.  We're probably dealing with somebody using
       // position:absolute inside native-anonymous content anyway.
-      aHypotheticalBox.mTop = placeholderOffset.y;
+      aHypotheticalBox.mBStart = placeholderOffset.B(wm);
     } else {
       NS_ASSERTION(iter.GetContainer() == blockFrame,
                    "Found placeholder in wrong block!");
       nsBlockFrame::line_iterator lineBox = iter.GetLine();
 
       // How we determine the hypothetical box depends on whether the element
       // would have been inline-level or block-level
+      LogicalRect lineBounds =
+        lineBox->GetBounds().ConvertTo(wm, lineBox->mWritingMode,
+                                       lineBox->mContainerWidth);
       if (mStyleDisplay->IsOriginalDisplayInlineOutsideStyle()) {
-        // Use the top of the inline box which the placeholder lives in
-        // as the hypothetical box's top.
-        aHypotheticalBox.mTop = lineBox->GetPhysicalBounds().y + blockYOffset;
+        // Use the block-start of the inline box which the placeholder lives in
+        // as the hypothetical box's block-start.
+        aHypotheticalBox.mBStart = lineBounds.BStart(wm) + blockOffset.B(wm);
       } else {
         // The element would have been block-level which means it would
         // be below the line containing the placeholder frame, unless
         // all the frames before it are empty.  In that case, it would
         // have been just before this line.
         // XXXbz the line box is not fully reflowed yet if our
         // containing block is relatively positioned...
         if (lineBox != iter.End()) {
@@ -1293,152 +1311,128 @@ nsHTMLReflowState::CalculateHypothetical
             firstFrame = firstFrame->GetNextSibling();
           }
           NS_ASSERTION(firstFrame, "Couldn't find placeholder!");
 
           if (allEmpty) {
             // The top of the hypothetical box is the top of the line
             // containing the placeholder, since there is nothing in the
             // line before our placeholder except empty frames.
-            aHypotheticalBox.mTop = lineBox->GetPhysicalBounds().y + blockYOffset;
+            aHypotheticalBox.mBStart = lineBounds.BStart(wm) + blockOffset.B(wm);
           } else {
             // The top of the hypothetical box is just below the line
             // containing the placeholder.
-            aHypotheticalBox.mTop = lineBox->GetPhysicalBounds().YMost() + blockYOffset;
+            aHypotheticalBox.mBStart = lineBounds.BEnd(wm) + blockOffset.B(wm);
           }
         } else {
-          // Just use the placeholder's y-offset wrt the containing block
-          aHypotheticalBox.mTop = placeholderOffset.y;
+          // Just use the placeholder's block-offset wrt the containing block
+          aHypotheticalBox.mBStart = placeholderOffset.B(wm);
         }
       }
     }
   } else {
     // The containing block is not a block, so it's probably something
     // like a XUL box, etc.
-    // Just use the placeholder's y-offset
-    aHypotheticalBox.mTop = placeholderOffset.y;
+    // Just use the placeholder's block-offset
+    aHypotheticalBox.mBStart = placeholderOffset.B(wm);
   }
 
-  // Second, determine the hypothetical box's mLeft & mRight
-  // To determine the left and right offsets we need to look at the block's 'direction'
-  if (NS_STYLE_DIRECTION_LTR == blockVis->mDirection) {
-    // How we determine the hypothetical box depends on whether the element
-    // would have been inline-level or block-level
-    if (mStyleDisplay->IsOriginalDisplayInlineOutsideStyle()) {
-      // The placeholder represents the left edge of the hypothetical box
-      aHypotheticalBox.mLeft = placeholderOffset.x;
-    } else {
-      aHypotheticalBox.mLeft = aBlockIStartContentEdge;
-    }
+  // Second, determine the hypothetical box's mIStart & mIEnd.
+  // How we determine the hypothetical box depends on whether the element
+  // would have been inline-level or block-level
+  if (mStyleDisplay->IsOriginalDisplayInlineOutsideStyle()) {
+    // The placeholder represents the left edge of the hypothetical box
+    aHypotheticalBox.mIStart = placeholderOffset.I(wm);
+  } else {
+    aHypotheticalBox.mIStart = blockIStartContentEdge;
+  }
 #ifdef DEBUG
-    aHypotheticalBox.mLeftIsExact = true;
+  aHypotheticalBox.mIStartIsExact = true;
 #endif
 
-    if (knowBoxISize) {
-      aHypotheticalBox.mRight = aHypotheticalBox.mLeft + boxISize;
+  if (knowBoxISize) {
+    aHypotheticalBox.mIEnd = aHypotheticalBox.mIStart + boxISize;
 #ifdef DEBUG
-      aHypotheticalBox.mRightIsExact = true;
+    aHypotheticalBox.mIEndIsExact = true;
 #endif
-    } else {
-      // We can't compute the right edge because we don't know the desired
-      // width. So instead use the right content edge of the block parent,
-      // but remember it's not exact
-      aHypotheticalBox.mRight = aBlockIStartContentEdge + aBlockContentISize;
-#ifdef DEBUG
-      aHypotheticalBox.mRightIsExact = false;
-#endif
-    }
-
   } else {
-    // The placeholder represents the right edge of the hypothetical box
-    if (mStyleDisplay->IsOriginalDisplayInlineOutsideStyle()) {
-      aHypotheticalBox.mRight = placeholderOffset.x;
-    } else {
-      aHypotheticalBox.mRight = aBlockIStartContentEdge + aBlockContentISize;
-    }
-#ifdef DEBUG
-    aHypotheticalBox.mRightIsExact = true;
-#endif
-
-    if (knowBoxISize) {
-      aHypotheticalBox.mLeft = aHypotheticalBox.mRight - boxISize;
+    // We can't compute the inline-end edge because we don't know the desired
+    // inline-size. So instead use the end content edge of the block parent,
+    // but remember it's not exact
+    aHypotheticalBox.mIEnd = blockIStartContentEdge + blockContentISize;
 #ifdef DEBUG
-      aHypotheticalBox.mLeftIsExact = true;
+    aHypotheticalBox.mIEndIsExact = false;
 #endif
-    } else {
-      // We can't compute the left edge because we don't know the desired
-      // width. So instead use the left content edge of the block parent,
-      // but remember it's not exact
-      aHypotheticalBox.mLeft = aBlockIStartContentEdge;
-#ifdef DEBUG
-      aHypotheticalBox.mLeftIsExact = false;
-#endif
-    }
-
   }
 
   // The current coordinate space is that of the nearest block to the placeholder.
   // Convert to the coordinate space of the absolute containing block
   // One weird thing here is that for fixed-positioned elements we want to do
   // the conversion incorrectly; specifically we want to ignore any scrolling
   // that may have happened;
   nsPoint cbOffset;
   if (mStyleDisplay->mPosition == NS_STYLE_POSITION_FIXED &&
       // Exclude cases inside -moz-transform where fixed is like absolute.
       nsLayoutUtils::IsReallyFixedPos(frame)) {
     // In this case, cbrs->frame will likely be an ancestor of
-    // aContainingBlock, so can just walk our way up the frame tree.
+    // containingBlock, so can just walk our way up the frame tree.
     // Make sure to not add positions of frames whose parent is a
     // scrollFrame, since we're doing fixed positioning, which assumes
     // everything is scrolled to (0,0).
     cbOffset.MoveTo(0, 0);
     do {
-      cbOffset += aContainingBlock->GetPositionIgnoringScrolling();
-      nsContainerFrame* parent = aContainingBlock->GetParent();
+      cbOffset += containingBlock->GetPositionIgnoringScrolling();
+      nsContainerFrame* parent = containingBlock->GetParent();
       if (!parent) {
         // Oops, our absolute containing block isn't an ancestor of the
         // placeholder's containing block. This can happen if the placeholder
         // is pushed to a different page in a printing context.  'cbOffset' is
-        // currently relative to the root frame (aContainingBlock) - so just
+        // currently relative to the root frame (containingBlock) - so just
         // subtract the offset to the absolute containing block to make it
         // relative to that.
-        cbOffset -= aContainingBlock->GetOffsetTo(cbrs->frame);
+        cbOffset -= containingBlock->GetOffsetTo(cbrs->frame);
         break;
       }
-      aContainingBlock = parent;
-    } while (aContainingBlock != cbrs->frame);
+      containingBlock = parent;
+    } while (containingBlock != cbrs->frame);
   } else {
     // XXXldb We need to either ignore scrolling for the absolute
     // positioning case too (and take the incompatibility) or figure out
     // how to make these positioned elements actually *move* when we
     // scroll, and thus avoid the resulting incremental reflow bugs.
-    cbOffset = aContainingBlock->GetOffsetTo(cbrs->frame);
+    cbOffset = containingBlock->GetOffsetTo(cbrs->frame);
   }
-  aHypotheticalBox.mLeft += cbOffset.x;
-  aHypotheticalBox.mTop += cbOffset.y;
-  aHypotheticalBox.mRight += cbOffset.x;
-  
+  nscoord cbrsWidth = cbrs->ComputedWidth() +
+                        cbrs->ComputedLogicalBorderPadding().LeftRight(cbwm);
+  LogicalPoint logCBOffs(wm, cbOffset, cbrsWidth - containerWidth);
+  aHypotheticalBox.mIStart += logCBOffs.I(wm);
+  aHypotheticalBox.mIEnd += logCBOffs.I(wm);
+  aHypotheticalBox.mBStart += logCBOffs.B(wm);
+
   // The specified offsets are relative to the absolute containing block's
   // padding edge and our current values are relative to the border edge, so
   // translate.
-  nsMargin border = cbrs->ComputedPhysicalBorderPadding() - cbrs->ComputedPhysicalPadding();
-  aHypotheticalBox.mLeft -= border.left;
-  aHypotheticalBox.mRight -= border.left;
-  aHypotheticalBox.mTop -= border.top;
+  LogicalMargin border =
+    cbrs->ComputedLogicalBorderPadding() - cbrs->ComputedLogicalPadding();
+  border = border.ConvertTo(wm, cbrs->GetWritingMode());
+  aHypotheticalBox.mIStart -= border.IStart(wm);
+  aHypotheticalBox.mIEnd -= border.IStart(wm);
+  aHypotheticalBox.mBStart -= border.BStart(wm);
 }
 
 void
 nsHTMLReflowState::InitAbsoluteConstraints(nsPresContext* aPresContext,
                                            const nsHTMLReflowState* cbrs,
                                            const LogicalSize& aCBSize,
                                            nsIAtom* aFrameType)
 {
   WritingMode wm = GetWritingMode();
-  NS_PRECONDITION(aCBSize.BSize(wm) != NS_AUTOHEIGHT,
-                  "containing block height must be constrained");
+  WritingMode cbwm = cbrs->GetWritingMode();
+  NS_PRECONDITION(aCBSize.BSize(cbwm) != NS_AUTOHEIGHT,
+                  "containing block bsize must be constrained");
 
   NS_ASSERTION(aFrameType != nsGkAtoms::tableFrame,
                "InitAbsoluteConstraints should not be called on table frames");
   NS_ASSERTION(frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW,
                "Why are we here?");
 
   // Get the placeholder frame
   nsIFrame*     placeholderFrame;
@@ -1449,296 +1443,301 @@ nsHTMLReflowState::InitAbsoluteConstrain
   // If both 'left' and 'right' are 'auto' or both 'top' and 'bottom' are
   // 'auto', then compute the hypothetical box of where the element would
   // have been if it had been in the flow
   nsHypotheticalBox hypotheticalBox;
   if (((eStyleUnit_Auto == mStylePosition->mOffset.GetLeftUnit()) &&
        (eStyleUnit_Auto == mStylePosition->mOffset.GetRightUnit())) ||
       ((eStyleUnit_Auto == mStylePosition->mOffset.GetTopUnit()) &&
        (eStyleUnit_Auto == mStylePosition->mOffset.GetBottomUnit()))) {
-    // Find the nearest containing block frame to the placeholder frame,
-    // and return its left edge and width.
-    nscoord cbIStartEdge, cbISize;
-    nsIFrame* cbFrame = GetHypotheticalBoxContainer(placeholderFrame,
-                                                    cbIStartEdge,
-                                                    cbISize);
-
-    CalculateHypotheticalBox(aPresContext, placeholderFrame, cbFrame,
-                             cbIStartEdge, cbISize, cbrs, hypotheticalBox,
-                             aFrameType);
+    CalculateHypotheticalBox(aPresContext, placeholderFrame, cbrs,
+                             hypotheticalBox, aFrameType);
   }
 
   // Initialize the 'left' and 'right' computed offsets
   // XXX Handle new 'static-position' value...
-  bool          leftIsAuto = false, rightIsAuto = false;
-  if (eStyleUnit_Auto == mStylePosition->mOffset.GetLeftUnit()) {
-    ComputedPhysicalOffsets().left = 0;
-    leftIsAuto = true;
+
+  bool iStartIsAuto = false, iEndIsAuto = false;
+  bool bStartIsAuto = false, bEndIsAuto = false;
+
+  // Size of the containing block in its writing mode
+  LogicalSize cbSize = aCBSize;
+
+  LogicalMargin offsets = ComputedLogicalOffsets().ConvertTo(cbwm, wm);
+
+  if (eStyleUnit_Auto == mStylePosition->mOffset.GetIStartUnit(cbwm)) {
+    offsets.IStart(cbwm) = 0;
+    iStartIsAuto = true;
   } else {
-    ComputedPhysicalOffsets().left = nsLayoutUtils::
-      ComputeCBDependentValue(aCBSize.ISize(wm),
-                              mStylePosition->mOffset.GetLeft());
+    offsets.IStart(cbwm) = nsLayoutUtils::
+      ComputeCBDependentValue(cbSize.ISize(cbwm),
+                              mStylePosition->mOffset.GetIStart(cbwm));
   }
-  if (eStyleUnit_Auto == mStylePosition->mOffset.GetRightUnit()) {
-    ComputedPhysicalOffsets().right = 0;
-    rightIsAuto = true;
+  if (eStyleUnit_Auto == mStylePosition->mOffset.GetIEndUnit(cbwm)) {
+    offsets.IEnd(cbwm) = 0;
+    iEndIsAuto = true;
   } else {
-    ComputedPhysicalOffsets().right = nsLayoutUtils::
-      ComputeCBDependentValue(aCBSize.ISize(wm),
-                              mStylePosition->mOffset.GetRight());
+    offsets.IEnd(cbwm) = nsLayoutUtils::
+      ComputeCBDependentValue(cbSize.ISize(cbwm),
+                              mStylePosition->mOffset.GetIEnd(cbwm));
   }
 
-  // Use the horizontal component of the hypothetical box in the cases
-  // where it's needed.
-  if (leftIsAuto && rightIsAuto) {
-    // Use the direction of the original ("static-position") containing block
-    // to dictate whether 'left' or 'right' is treated like 'static-position'.
-    if (NS_STYLE_DIRECTION_LTR == placeholderFrame->GetContainingBlock()
-                                    ->StyleVisibility()->mDirection) {
-      NS_ASSERTION(hypotheticalBox.mLeftIsExact, "should always have "
-                   "exact value on containing block's start side");
-      ComputedPhysicalOffsets().left = hypotheticalBox.mLeft;
-      leftIsAuto = false;
+  if (iStartIsAuto && iEndIsAuto) {
+    NS_ASSERTION(hypotheticalBox.mIStartIsExact, "should always have "
+                 "exact value on containing block's start side");
+    if (cbwm.IsBidiLTR() != hypotheticalBox.mWritingMode.IsBidiLTR()) {
+      offsets.IEnd(cbwm) = hypotheticalBox.mIStart;
+      iEndIsAuto = false;
     } else {
-      NS_ASSERTION(hypotheticalBox.mRightIsExact, "should always have "
-                   "exact value on containing block's start side");
-      ComputedPhysicalOffsets().right = aCBSize.ISize(wm) -
-                                        hypotheticalBox.mRight;
-      rightIsAuto = false;
+      offsets.IStart(cbwm) = hypotheticalBox.mIStart;
+      iStartIsAuto = false;
     }
   }
 
-  // Initialize the 'top' and 'bottom' computed offsets
-  bool        topIsAuto = false, bottomIsAuto = false;
-  if (eStyleUnit_Auto == mStylePosition->mOffset.GetTopUnit()) {
-    ComputedPhysicalOffsets().top = 0;
-    topIsAuto = true;
+  if (eStyleUnit_Auto == mStylePosition->mOffset.GetBStartUnit(cbwm)) {
+    offsets.BStart(cbwm) = 0;
+    bStartIsAuto = true;
   } else {
-    ComputedPhysicalOffsets().top = nsLayoutUtils::
-      ComputeBSizeDependentValue(aCBSize.BSize(wm),
-                                 mStylePosition->mOffset.GetTop());
+    offsets.BStart(cbwm) = nsLayoutUtils::
+      ComputeBSizeDependentValue(cbSize.BSize(cbwm),
+                                 mStylePosition->mOffset.GetBStart(cbwm));
   }
-  if (eStyleUnit_Auto == mStylePosition->mOffset.GetBottomUnit()) {
-    ComputedPhysicalOffsets().bottom = 0;        
-    bottomIsAuto = true;
+  if (eStyleUnit_Auto == mStylePosition->mOffset.GetBEndUnit(cbwm)) {
+    offsets.BEnd(cbwm) = 0;
+    bEndIsAuto = true;
   } else {
-    ComputedPhysicalOffsets().bottom = nsLayoutUtils::
-      ComputeBSizeDependentValue(aCBSize.BSize(wm),
-                                 mStylePosition->mOffset.GetBottom());
+    offsets.BEnd(cbwm) = nsLayoutUtils::
+      ComputeBSizeDependentValue(cbSize.BSize(cbwm),
+                                 mStylePosition->mOffset.GetBEnd(cbwm));
   }
 
-  if (topIsAuto && bottomIsAuto) {
+  if (bStartIsAuto && bEndIsAuto) {
     // Treat 'top' like 'static-position'
-    ComputedPhysicalOffsets().top = hypotheticalBox.mTop;
-    topIsAuto = false;
+    NS_ASSERTION(hypotheticalBox.mWritingMode.GetBlockDir() == cbwm.GetBlockDir(),
+                 "block direction mismatch");
+    offsets.BStart(cbwm) = hypotheticalBox.mBStart;
+    bStartIsAuto = false;
   }
 
-  bool widthIsAuto = eStyleUnit_Auto == mStylePosition->mWidth.GetUnit();
-  bool heightIsAuto = eStyleUnit_Auto == mStylePosition->mHeight.GetUnit();
+  SetComputedLogicalOffsets(offsets.ConvertTo(wm, cbwm));
+
+  bool iSizeIsAuto = eStyleUnit_Auto == mStylePosition->ISize(cbwm).GetUnit();
+  bool bSizeIsAuto = eStyleUnit_Auto == mStylePosition->BSize(cbwm).GetUnit();
 
   typedef nsIFrame::ComputeSizeFlags ComputeSizeFlags;
   ComputeSizeFlags computeSizeFlags = ComputeSizeFlags::eDefault;
-  if (leftIsAuto || rightIsAuto) {
-    computeSizeFlags =
-      ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
+  if (wm.IsOrthogonalTo(cbwm)) {
+    if (bStartIsAuto || bEndIsAuto) {
+      computeSizeFlags =
+        ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
+    }
+  } else {
+    if (iStartIsAuto || iEndIsAuto) {
+      computeSizeFlags =
+        ComputeSizeFlags(computeSizeFlags | ComputeSizeFlags::eShrinkWrap);
+    }
   }
 
+  LogicalSize computedSize(wm);
   {
     AutoMaybeDisableFontInflation an(frame);
 
-    LogicalSize size =
-      frame->ComputeSize(rendContext, wm, aCBSize,
-                         aCBSize.ISize(wm), // XXX or AvailableISize()?
+    computedSize =
+      frame->ComputeSize(rendContext, wm, cbSize.ConvertTo(wm, cbwm),
+                         cbSize.ConvertTo(wm, cbwm).ISize(wm), // XXX or AvailableISize()?
                          ComputedLogicalMargin().Size(wm) +
                            ComputedLogicalOffsets().Size(wm),
                          ComputedLogicalBorderPadding().Size(wm) -
                            ComputedLogicalPadding().Size(wm),
                          ComputedLogicalPadding().Size(wm),
                          computeSizeFlags);
-    ComputedISize() = size.ISize(wm);
-    ComputedBSize() = size.BSize(wm);
+    ComputedISize() = computedSize.ISize(wm);
+    ComputedBSize() = computedSize.BSize(wm);
+    NS_ASSERTION(ComputedISize() >= 0, "Bogus inline-size");
+    NS_ASSERTION(ComputedBSize() == NS_UNCONSTRAINEDSIZE ||
+                 ComputedBSize() >= 0, "Bogus block-size");
   }
-  NS_ASSERTION(ComputedISize() >= 0, "Bogus inline-size");
-  NS_ASSERTION(ComputedBSize() == NS_UNCONSTRAINEDSIZE ||
-               ComputedBSize() >= 0, "Bogus block-size");
+  computedSize = computedSize.ConvertTo(cbwm, wm);
 
   // XXX Now that we have ComputeSize, can we condense many of the
   // branches off of widthIsAuto?
 
-  if (leftIsAuto) {
+  LogicalMargin margin = ComputedLogicalMargin().ConvertTo(cbwm, wm);
+  const LogicalMargin borderPadding =
+    ComputedLogicalBorderPadding().ConvertTo(cbwm, wm);
+
+  if (iStartIsAuto) {
     // We know 'right' is not 'auto' anymore thanks to the hypothetical
     // box code above.
     // Solve for 'left'.
-    if (widthIsAuto) {
+    if (iSizeIsAuto) {
       // XXXldb This, and the corresponding code in
       // nsAbsoluteContainingBlock.cpp, could probably go away now that
       // we always compute widths.
-      ComputedPhysicalOffsets().left = NS_AUTOOFFSET;
+      offsets.IStart(cbwm) = NS_AUTOOFFSET;
     } else {
-      ComputedPhysicalOffsets().left = aCBSize.Width(wm) - ComputedPhysicalMargin().left -
-        ComputedPhysicalBorderPadding().left - ComputedWidth() - ComputedPhysicalBorderPadding().right -
-        ComputedPhysicalMargin().right - ComputedPhysicalOffsets().right;
-
+      offsets.IStart(cbwm) =
+        cbSize.ISize(cbwm) - offsets.IEnd(cbwm) -
+        computedSize.ISize(cbwm) - margin.IStartEnd(cbwm) -
+        borderPadding.IStartEnd(cbwm);
     }
-  } else if (rightIsAuto) {
+  } else if (iEndIsAuto) {
     // We know 'left' is not 'auto' anymore thanks to the hypothetical
     // box code above.
     // Solve for 'right'.
-    if (widthIsAuto) {
+    if (iSizeIsAuto) {
       // XXXldb This, and the corresponding code in
       // nsAbsoluteContainingBlock.cpp, could probably go away now that
       // we always compute widths.
-      ComputedPhysicalOffsets().right = NS_AUTOOFFSET;
+      offsets.IEnd(cbwm) = NS_AUTOOFFSET;
     } else {
-      ComputedPhysicalOffsets().right = aCBSize.Width(wm) - ComputedPhysicalOffsets().left -
-        ComputedPhysicalMargin().left - ComputedPhysicalBorderPadding().left - ComputedWidth() -
-        ComputedPhysicalBorderPadding().right - ComputedPhysicalMargin().right;
+      offsets.IEnd(cbwm) =
+        cbSize.ISize(cbwm) - offsets.IStart(cbwm) -
+        computedSize.ISize(cbwm) - margin.IStartEnd(cbwm) -
+        borderPadding.IStartEnd(cbwm);
     }
   } else {
     // Neither 'left' nor 'right' is 'auto'.  However, the width might
     // still not fill all the available space (even though we didn't
     // shrink-wrap) in case:
     //  * width was specified
     //  * we're dealing with a replaced element
     //  * width was constrained by min-width or max-width.
 
-    nscoord availMarginSpace = aCBSize.Width(wm) -
-                               ComputedPhysicalOffsets().LeftRight() -
-                               ComputedPhysicalMargin().LeftRight() -
-                               ComputedPhysicalBorderPadding().LeftRight() -
-                               ComputedWidth();
-    bool marginLeftIsAuto =
-      eStyleUnit_Auto == mStyleMargin->mMargin.GetLeftUnit();
-    bool marginRightIsAuto =
-      eStyleUnit_Auto == mStyleMargin->mMargin.GetRightUnit();
+    nscoord availMarginSpace =
+      aCBSize.ISize(cbwm) - offsets.IStartEnd(cbwm) - margin.IStartEnd(cbwm) -
+      borderPadding.IStartEnd(cbwm) - computedSize.ISize(cbwm);
+    bool marginIStartIsAuto =
+      eStyleUnit_Auto == mStyleMargin->mMargin.GetIStartUnit(cbwm);
+    bool marginIEndIsAuto =
+      eStyleUnit_Auto == mStyleMargin->mMargin.GetIEndUnit(cbwm);
 
-    if (marginLeftIsAuto) {
-      if (marginRightIsAuto) {
+    if (marginIStartIsAuto) {
+      if (marginIEndIsAuto) {
         if (availMarginSpace < 0) {
           // Note that this case is different from the neither-'auto'
           // case below, where the spec says to ignore 'left'/'right'.
-          if (cbrs &&
-              NS_STYLE_DIRECTION_RTL == cbrs->mStyleVisibility->mDirection) {
-            // Ignore the specified value for 'margin-left'.
-            ComputedPhysicalMargin().left = availMarginSpace;
-          } else {
-            // Ignore the specified value for 'margin-right'.
-            ComputedPhysicalMargin().right = availMarginSpace;
-          }
+          // Ignore the specified value for 'margin-right'.
+          margin.IEnd(cbwm) = availMarginSpace;
         } else {
           // Both 'margin-left' and 'margin-right' are 'auto', so they get
           // equal values
-          ComputedPhysicalMargin().left = availMarginSpace / 2;
-          ComputedPhysicalMargin().right = availMarginSpace - ComputedPhysicalMargin().left;
+          margin.IStart(cbwm) = availMarginSpace / 2;
+          margin.IEnd(cbwm) = availMarginSpace - margin.IStart(cbwm);
         }
       } else {
         // Just 'margin-left' is 'auto'
-        ComputedPhysicalMargin().left = availMarginSpace;
+        margin.IStart(cbwm) = availMarginSpace;
       }
     } else {
-      if (marginRightIsAuto) {
+      if (marginIEndIsAuto) {
         // Just 'margin-right' is 'auto'
-        ComputedPhysicalMargin().right = availMarginSpace;
+        margin.IEnd(cbwm) = availMarginSpace;
       } else {
         // We're over-constrained so use the direction of the containing
         // block to dictate which value to ignore.  (And note that the
         // spec says to ignore 'left' or 'right' rather than
         // 'margin-left' or 'margin-right'.)
         // Note that this case is different from the both-'auto' case
         // above, where the spec says to ignore
         // 'margin-left'/'margin-right'.
-        if (cbrs &&
-            NS_STYLE_DIRECTION_RTL == cbrs->mStyleVisibility->mDirection) {
-          // Ignore the specified value for 'left'.
-          ComputedPhysicalOffsets().left += availMarginSpace;
-        } else {
-          // Ignore the specified value for 'right'.
-          ComputedPhysicalOffsets().right += availMarginSpace;
-        }
+        // Ignore the specified value for 'right'.
+        offsets.IEnd(cbwm) += availMarginSpace;
       }
     }
   }
 
-  if (topIsAuto) {
-    // solve for 'top'
-    if (heightIsAuto) {
-      ComputedPhysicalOffsets().top = NS_AUTOOFFSET;
+  if (bStartIsAuto) {
+    // solve for block-start
+    if (bSizeIsAuto) {
+      offsets.BStart(cbwm) = NS_AUTOOFFSET;
     } else {
-      ComputedPhysicalOffsets().top = aCBSize.Height(wm) - ComputedPhysicalMargin().top -
-        ComputedPhysicalBorderPadding().top - ComputedHeight() - ComputedPhysicalBorderPadding().bottom - 
-        ComputedPhysicalMargin().bottom - ComputedPhysicalOffsets().bottom;
+      offsets.BStart(cbwm) = cbSize.BSize(cbwm) - margin.BStartEnd(cbwm) -
+        borderPadding.BStartEnd(cbwm) - computedSize.BSize(cbwm) -
+        offsets.BEnd(cbwm);
     }
-  } else if (bottomIsAuto) {
-    // solve for 'bottom'
-    if (heightIsAuto) {
-      ComputedPhysicalOffsets().bottom = NS_AUTOOFFSET;
+  } else if (bEndIsAuto) {
+    // solve for block-end
+    if (bSizeIsAuto) {
+      offsets.BEnd(cbwm) = NS_AUTOOFFSET;
     } else {
-      ComputedPhysicalOffsets().bottom = aCBSize.Height(wm) - ComputedPhysicalOffsets().top -
-        ComputedPhysicalMargin().top - ComputedPhysicalBorderPadding().top - ComputedHeight() -
-        ComputedPhysicalBorderPadding().bottom - ComputedPhysicalMargin().bottom;
+      offsets.BEnd(cbwm) = cbSize.BSize(cbwm) - margin.BStartEnd(cbwm) -
+        borderPadding.BStartEnd(cbwm) - computedSize.BSize(cbwm) -
+        offsets.BStart(cbwm);
     }
   } else {
-    // Neither 'top' nor 'bottom' is 'auto'.
-    nscoord autoHeight = aCBSize.Height(wm) -
-                         ComputedPhysicalOffsets().TopBottom() -
-                         ComputedPhysicalMargin().TopBottom() -
-                         ComputedPhysicalBorderPadding().TopBottom();
-    if (autoHeight < 0) {
-      autoHeight = 0;
+    // Neither block-start nor -end is 'auto'.
+    nscoord autoBSize = cbSize.BSize(cbwm) - margin.BStartEnd(cbwm) -
+      borderPadding.BStartEnd(cbwm) - offsets.BStartEnd(cbwm);
+    if (autoBSize < 0) {
+      autoBSize = 0;
     }
 
-    if (ComputedHeight() == NS_UNCONSTRAINEDSIZE) {
-      // For non-replaced elements with 'height' auto, the 'height'
+    if (computedSize.BSize(cbwm) == NS_UNCONSTRAINEDSIZE) {
+      // For non-replaced elements with block-size auto, the block-size
       // fills the remaining space.
-      ComputedHeight() = autoHeight;
+      computedSize.BSize(cbwm) = autoBSize;
 
       // XXX Do these need box-sizing adjustments?
-      if (ComputedHeight() > ComputedMaxHeight())
-        ComputedHeight() = ComputedMaxHeight();
-      if (ComputedHeight() < ComputedMinHeight())
-        ComputedHeight() = ComputedMinHeight();
+      LogicalSize maxSize =
+        LogicalSize(wm, ComputedMaxISize(),
+                    ComputedMaxBSize()).ConvertTo(cbwm, wm);
+      LogicalSize minSize =
+        LogicalSize(wm, ComputedMinISize(),
+                    ComputedMinBSize()).ConvertTo(cbwm, wm);
+      if (computedSize.BSize(cbwm) > maxSize.BSize(cbwm)) {
+        computedSize.BSize(cbwm) = maxSize.BSize(cbwm);
+      }
+      if (computedSize.BSize(cbwm) < minSize.BSize(cbwm)) {
+        computedSize.BSize(cbwm) = minSize.BSize(cbwm);
+      }
     }
 
-    // The height might still not fill all the available space in case:
-    //  * height was specified
+    // The block-size might still not fill all the available space in case:
+    //  * bsize was specified
     //  * we're dealing with a replaced element
-    //  * height was constrained by min-height or max-height.
-    nscoord availMarginSpace = autoHeight - ComputedHeight();
-    bool marginTopIsAuto =
-      eStyleUnit_Auto == mStyleMargin->mMargin.GetTopUnit();
-    bool marginBottomIsAuto =
-      eStyleUnit_Auto == mStyleMargin->mMargin.GetBottomUnit();
+    //  * bsize was constrained by min- or max-bsize.
+    nscoord availMarginSpace = autoBSize - computedSize.BSize(cbwm);
+    bool marginBStartIsAuto =
+      eStyleUnit_Auto == mStyleMargin->mMargin.GetBStartUnit(cbwm);
+    bool marginBEndIsAuto =
+      eStyleUnit_Auto == mStyleMargin->mMargin.GetBEndUnit(cbwm);
 
-    if (marginTopIsAuto) {
-      if (marginBottomIsAuto) {
+    if (marginBStartIsAuto) {
+      if (marginBEndIsAuto) {
         if (availMarginSpace < 0) {
           // FIXME: Note that the spec doesn't actually say we should do this!
-          ComputedPhysicalMargin().bottom = availMarginSpace;
+          margin.BEnd(cbwm) = availMarginSpace;
         } else {
-          // Both 'margin-top' and 'margin-bottom' are 'auto', so they get
+          // Both margin-block-start and -end are 'auto', so they get
           // equal values
-          ComputedPhysicalMargin().top = availMarginSpace / 2;
-          ComputedPhysicalMargin().bottom = availMarginSpace - ComputedPhysicalMargin().top;
+          margin.BStart(cbwm) = availMarginSpace / 2;
+          margin.BEnd(cbwm) = availMarginSpace - margin.BStart(cbwm);
         }
       } else {
-        // Just 'margin-top' is 'auto'
-        ComputedPhysicalMargin().top = availMarginSpace;
+        // Just margin-block-start is 'auto'
+        margin.BStart(cbwm) = availMarginSpace;
       }
     } else {
-      if (marginBottomIsAuto) {
-        // Just 'margin-bottom' is 'auto'
-        ComputedPhysicalMargin().bottom = availMarginSpace;
+      if (marginBEndIsAuto) {
+        // Just margin-block-end is 'auto'
+        margin.BEnd(cbwm) = availMarginSpace;
       } else {
         // We're over-constrained so ignore the specified value for
-        // 'bottom'.  (And note that the spec says to ignore 'bottom'
+        // block-end.  (And note that the spec says to ignore 'bottom'
         // rather than 'margin-bottom'.)
-        ComputedPhysicalOffsets().bottom += availMarginSpace;
+        offsets.BEnd(cbwm) += availMarginSpace;
       }
     }
   }
+  ComputedBSize() = computedSize.ConvertTo(wm, cbwm).BSize(wm);
+  ComputedISize() = computedSize.ConvertTo(wm, cbwm).ISize(wm);
+
+  SetComputedLogicalOffsets(offsets.ConvertTo(wm, cbwm));
+  SetComputedLogicalMargin(margin.ConvertTo(wm, cbwm));
 }
 
 // This will not be converted to abstract coordinates because it's only
 // used in CalcQuirkContainingBlockHeight
 nscoord
 GetBlockMarginBorderPadding(const nsHTMLReflowState* aReflowState)
 {
   nscoord result = 0;
@@ -1759,17 +1758,18 @@ GetBlockMarginBorderPadding(const nsHTML
 }
 
 /* Get the height based on the viewport of the containing block specified 
  * in aReflowState when the containing block has mComputedHeight == NS_AUTOHEIGHT
  * This will walk up the chain of containing blocks looking for a computed height
  * until it finds the canvas frame, or it encounters a frame that is not a block,
  * area, or scroll frame. This handles compatibility with IE (see bug 85016 and bug 219693)
  *
- *  When we encounter scrolledContent block frames, we skip over them, since they are guaranteed to not be useful for computing the containing block.
+ * When we encounter scrolledContent block frames, we skip over them,
+ * since they are guaranteed to not be useful for computing the containing block.
  *
  * See also IsQuirkContainingBlockHeight.
  */
 static nscoord
 CalcQuirkContainingBlockHeight(const nsHTMLReflowState* aCBReflowState)
 {
   const nsHTMLReflowState* firstAncestorRS = nullptr; // a candidate for html frame
   const nsHTMLReflowState* secondAncestorRS = nullptr; // a candidate for body frame
@@ -1833,23 +1833,25 @@ CalcQuirkContainingBlockHeight(const nsH
       result -= GetBlockMarginBorderPadding(firstAncestorRS);
       result -= GetBlockMarginBorderPadding(secondAncestorRS);
 
 #ifdef DEBUG
       // make sure the first ancestor is the HTML and the second is the BODY
       if (firstAncestorRS) {
         nsIContent* frameContent = firstAncestorRS->frame->GetContent();
         if (frameContent) {
-          NS_ASSERTION(frameContent->IsHTMLElement(nsGkAtoms::html), "First ancestor is not HTML");
+          NS_ASSERTION(frameContent->IsHTMLElement(nsGkAtoms::html),
+                       "First ancestor is not HTML");
         }
       }
       if (secondAncestorRS) {
         nsIContent* frameContent = secondAncestorRS->frame->GetContent();
         if (frameContent) {
-          NS_ASSERTION(frameContent->IsHTMLElement(nsGkAtoms::body), "Second ancestor is not BODY");
+          NS_ASSERTION(frameContent->IsHTMLElement(nsGkAtoms::body),
+                       "Second ancestor is not BODY");
         }
       }
 #endif
       
     }
     // if we got to the html frame (a block child of the canvas) ...
     else if (nsGkAtoms::blockFrame == frameType &&
              rs->parentReflowState &&
@@ -2006,25 +2008,29 @@ nsHTMLReflowState::InitConstraints(nsPre
     // XXXldb This doesn't mean what it used to!
     InitOffsets(OffsetPercentBasis(frame, wm, aContainingBlockSize),
                 aFrameType, aBorder, aPadding);
     // Override mComputedMargin since reflow roots start from the
     // frame's boundary, which is inside the margin.
     ComputedPhysicalMargin().SizeTo(0, 0, 0, 0);
     ComputedPhysicalOffsets().SizeTo(0, 0, 0, 0);
 
-    ComputedWidth() = AvailableWidth() - ComputedPhysicalBorderPadding().LeftRight();
-    if (ComputedWidth() < 0)
-      ComputedWidth() = 0;
-    if (AvailableHeight() != NS_UNCONSTRAINEDSIZE) {
-      ComputedHeight() = AvailableHeight() - ComputedPhysicalBorderPadding().TopBottom();
-      if (ComputedHeight() < 0)
-        ComputedHeight() = 0;
+    ComputedISize() =
+      AvailableISize() - ComputedLogicalBorderPadding().IStartEnd(wm);
+    if (ComputedISize() < 0) {
+      ComputedISize() = 0;
+    }
+    if (AvailableBSize() != NS_UNCONSTRAINEDSIZE) {
+      ComputedBSize() =
+        AvailableBSize() - ComputedLogicalBorderPadding().BStartEnd(wm);
+      if (ComputedBSize() < 0) {
+        ComputedBSize() = 0;
+      }
     } else {
-      ComputedHeight() = NS_UNCONSTRAINEDSIZE;
+      ComputedBSize() = NS_UNCONSTRAINEDSIZE;
     }
 
     ComputedMinWidth() = ComputedMinHeight() = 0;
     ComputedMaxWidth() = ComputedMaxHeight() = NS_UNCONSTRAINEDSIZE;
   } else {
     // Get the containing block reflow state
     const nsHTMLReflowState* cbrs = mCBReflowState;
     NS_ASSERTION(nullptr != cbrs, "no containing block");
@@ -2180,17 +2186,17 @@ nsHTMLReflowState::InitConstraints(nsPre
       }
 
       // Doesn't apply to table elements
       ComputedMinWidth() = ComputedMinHeight() = 0;
       ComputedMaxWidth() = ComputedMaxHeight() = NS_UNCONSTRAINEDSIZE;
 
     } else if (NS_FRAME_GET_TYPE(mFrameType) == NS_CSS_FRAME_TYPE_ABSOLUTE) {
       // XXX not sure if this belongs here or somewhere else - cwk
-      InitAbsoluteConstraints(aPresContext, cbrs, cbSize, aFrameType);
+      InitAbsoluteConstraints(aPresContext, cbrs, cbSize.ConvertTo(cbrs->GetWritingMode(), wm), aFrameType);
     } else {
       AutoMaybeDisableFontInflation an(frame);
 
       bool isBlock = NS_CSS_FRAME_TYPE_BLOCK == NS_FRAME_GET_TYPE(mFrameType);
       typedef nsIFrame::ComputeSizeFlags ComputeSizeFlags;
       ComputeSizeFlags computeSizeFlags =
         isBlock ? ComputeSizeFlags::eDefault : ComputeSizeFlags::eShrinkWrap;
 
--- a/layout/generic/nsHTMLReflowState.h
+++ b/layout/generic/nsHTMLReflowState.h
@@ -417,19 +417,22 @@ struct nsHTMLReflowState : public nsCSSO
                                                            GetWritingMode());
   }
 
   // XXX this will need to change when we make mComputedOffsets logical;
   // we won't be able to return a reference for the physical offsets
   const nsMargin& ComputedPhysicalOffsets() const { return mComputedOffsets; }
   nsMargin& ComputedPhysicalOffsets() { return mComputedOffsets; }
 
-  LogicalMargin ComputedLogicalOffsets() const
+  const LogicalMargin ComputedLogicalOffsets() const
     { return LogicalMargin(mWritingMode, mComputedOffsets); }
 
+  void SetComputedLogicalOffsets(const LogicalMargin& aOffsets)
+    { mComputedOffsets = aOffsets.GetPhysicalMargin(mWritingMode); }
+
 private:
   // the available width in which to reflow the frame. The space
   // represents the amount of room for the frame's margin, border,
   // padding, and content area. The frame size you choose should fit
   // within the available width.
   nscoord              mAvailableWidth;
 
   // A value of NS_UNCONSTRAINEDSIZE for the available height means
@@ -876,19 +879,16 @@ protected:
   // content area.
   // These are returned in the coordinate space of the containing block.
   nsIFrame* GetHypotheticalBoxContainer(nsIFrame* aFrame,
                                         nscoord& aCBIStartEdge,
                                         nscoord& aCBISize);
 
   void CalculateHypotheticalBox(nsPresContext*    aPresContext,
                                 nsIFrame*         aPlaceholderFrame,
-                                nsIFrame*         aContainingBlock,
-                                nscoord           aBlockIStartContentEdge,
-                                nscoord           aBlockContentISize,
                                 const nsHTMLReflowState* cbrs,
                                 nsHypotheticalBox& aHypotheticalBox,
                                 nsIAtom*          aFrameType);
 
   void InitAbsoluteConstraints(nsPresContext* aPresContext,
                                const nsHTMLReflowState* cbrs,
                                const mozilla::LogicalSize& aContainingBlockSize,
                                nsIAtom* aFrameType);