bug 735577 - pt 4.1 - use accessor functions for some physical-coordinate fields in nsHTMLReflowMetrics, in preparation for logicalization. r=smontagu
authorJonathan Kew <jkew@mozilla.com>
Fri, 27 Dec 2013 17:59:52 +0000
changeset 161816 72591e9d49a8432c45b304c7ccb86a8e09947bb1
parent 161815 10592ba2f6950f6473d6d443c6f340fbc4d6621e
child 161817 07f8896db19cbc95ac470406e0b810f8e68eed8b
push idunknown
push userunknown
push dateunknown
reviewerssmontagu
bugs735577
milestone29.0a1
bug 735577 - pt 4.1 - use accessor functions for some physical-coordinate fields in nsHTMLReflowMetrics, in preparation for logicalization. r=smontagu
layout/base/nsPresShell.cpp
layout/forms/nsComboboxControlFrame.cpp
layout/forms/nsFieldSetFrame.cpp
layout/forms/nsFormControlFrame.cpp
layout/forms/nsHTMLButtonControlFrame.cpp
layout/forms/nsMeterFrame.cpp
layout/forms/nsNumberControlFrame.cpp
layout/forms/nsProgressFrame.cpp
layout/forms/nsRangeFrame.cpp
layout/forms/nsSelectsAreaFrame.cpp
layout/forms/nsTextControlFrame.cpp
layout/generic/nsAbsoluteContainingBlock.cpp
layout/generic/nsBRFrame.cpp
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockReflowContext.cpp
layout/generic/nsBulletFrame.cpp
layout/generic/nsCanvasFrame.cpp
layout/generic/nsColumnSetFrame.cpp
layout/generic/nsContainerFrame.cpp
layout/generic/nsFirstLetterFrame.cpp
layout/generic/nsFlexContainerFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrameSetFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsHTMLCanvasFrame.cpp
layout/generic/nsHTMLReflowMetrics.cpp
layout/generic/nsHTMLReflowMetrics.h
layout/generic/nsHTMLReflowState.cpp
layout/generic/nsIFrame.h
layout/generic/nsImageFrame.cpp
layout/generic/nsInlineFrame.cpp
layout/generic/nsLeafFrame.cpp
layout/generic/nsLineLayout.cpp
layout/generic/nsObjectFrame.cpp
layout/generic/nsPageContentFrame.cpp
layout/generic/nsPageFrame.cpp
layout/generic/nsPlaceholderFrame.cpp
layout/generic/nsSimplePageSequence.cpp
layout/generic/nsSubDocumentFrame.cpp
layout/generic/nsTextFrame.cpp
layout/generic/nsVideoFrame.cpp
layout/generic/nsViewportFrame.cpp
layout/mathml/nsMathMLContainerFrame.cpp
layout/mathml/nsMathMLSelectedFrame.cpp
layout/mathml/nsMathMLTokenFrame.cpp
layout/mathml/nsMathMLmencloseFrame.cpp
layout/mathml/nsMathMLmfencedFrame.cpp
layout/mathml/nsMathMLmfracFrame.cpp
layout/mathml/nsMathMLmmultiscriptsFrame.cpp
layout/mathml/nsMathMLmoFrame.cpp
layout/mathml/nsMathMLmpaddedFrame.cpp
layout/mathml/nsMathMLmrootFrame.cpp
layout/mathml/nsMathMLmspaceFrame.cpp
layout/mathml/nsMathMLmtableFrame.cpp
layout/mathml/nsMathMLmunderoverFrame.cpp
layout/svg/SVGTextFrame.cpp
layout/svg/nsSVGForeignObjectFrame.cpp
layout/svg/nsSVGOuterSVGFrame.cpp
layout/tables/nsTableCellFrame.cpp
layout/tables/nsTableCellFrame.h
layout/tables/nsTableColFrame.cpp
layout/tables/nsTableColGroupFrame.cpp
layout/tables/nsTableFrame.cpp
layout/tables/nsTableOuterFrame.cpp
layout/tables/nsTableRowFrame.cpp
layout/tables/nsTableRowGroupFrame.cpp
layout/xul/nsBoxFrame.cpp
layout/xul/nsLeafBoxFrame.cpp
layout/xul/nsScrollbarFrame.cpp
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -8055,27 +8055,27 @@ PresShell::DoReflow(nsIFrame* target, bo
                  size.width -
                    reflowState.ComputedPhysicalBorderPadding().LeftRight(),
                "reflow state computed incorrect width");
 
   mPresContext->ReflowStarted(aInterruptible);
   mIsReflowing = true;
 
   nsReflowStatus status;
-  nsHTMLReflowMetrics desiredSize;
+  nsHTMLReflowMetrics desiredSize(reflowState.GetWritingMode());
   target->Reflow(mPresContext, desiredSize, reflowState, status);
 
   // If an incremental reflow is initiated at a frame other than the
   // root frame, then its desired size had better not change!  If it's
   // initiated at the root, then the size better not change unless its
   // height was unconstrained to start with.
-  nsRect boundsRelativeToTarget = nsRect(0, 0, desiredSize.width, desiredSize.height);
+  nsRect boundsRelativeToTarget = nsRect(0, 0, desiredSize.Width(), desiredSize.Height());
   NS_ASSERTION((target == rootFrame && size.height == NS_UNCONSTRAINEDSIZE) ||
-               (desiredSize.width == size.width &&
-                desiredSize.height == size.height),
+               (desiredSize.Width() == size.width &&
+                desiredSize.Height() == size.height),
                "non-root frame's desired size changed during an "
                "incremental reflow");
   NS_ASSERTION(target == rootFrame ||
                desiredSize.VisualOverflow().IsEqualInterior(boundsRelativeToTarget),
                "non-root reflow roots must not have visible overflow");
   NS_ASSERTION(target == rootFrame ||
                desiredSize.ScrollableOverflow().IsEqualEdges(boundsRelativeToTarget),
                "non-root reflow roots must not have scrollable overflow");
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -434,17 +434,17 @@ nsComboboxControlFrame::ReflowDropdown(n
 
   // Allow the child to move/size/change-visibility its view if it's currently
   // dropped down
   int32_t flags = NS_FRAME_NO_MOVE_FRAME | NS_FRAME_NO_VISIBILITY | NS_FRAME_NO_SIZE_VIEW;
   if (mDroppedDown) {
     flags = 0;
   }
   nsRect rect = mDropdownFrame->GetRect();
-  nsHTMLReflowMetrics desiredSize;
+  nsHTMLReflowMetrics desiredSize(aReflowState.GetWritingMode());
   nsReflowStatus ignoredStatus;
   nsresult rv = ReflowChild(mDropdownFrame, aPresContext, desiredSize,
                             kidReflowState, rect.x, rect.y, flags,
                             ignoredStatus);
 
    // Set the child's width and height to it's desired size
   FinishReflowChild(mDropdownFrame, aPresContext, &kidReflowState,
                     desiredSize, rect.x, rect.y, flags);
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -476,27 +476,27 @@ nsFieldSetFrame::Reflow(nsPresContext*  
   // get the legend's margin
   nsMargin legendMargin(0,0,0,0);
   // reflow the legend only if needed
   Maybe<nsHTMLReflowState> legendReflowState;
   if (legend) {
     legendReflowState.construct(aPresContext, aReflowState, legend, availSize);
   }
   if (reflowLegend) {
-    nsHTMLReflowMetrics legendDesiredSize;
+    nsHTMLReflowMetrics legendDesiredSize(aReflowState.GetWritingMode());
 
     ReflowChild(legend, aPresContext, legendDesiredSize, legendReflowState.ref(),
                 0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
 #ifdef NOISY_REFLOW
-    printf("  returned (%d, %d)\n", legendDesiredSize.width, legendDesiredSize.height);
+    printf("  returned (%d, %d)\n", legendDesiredSize.Width(), legendDesiredSize.Height());
 #endif
     // figure out the legend's rectangle
     legendMargin = legend->GetUsedMargin();
-    mLegendRect.width  = legendDesiredSize.width + legendMargin.left + legendMargin.right;
-    mLegendRect.height = legendDesiredSize.height + legendMargin.top + legendMargin.bottom;
+    mLegendRect.width  = legendDesiredSize.Width() + legendMargin.left + legendMargin.right;
+    mLegendRect.height = legendDesiredSize.Height() + legendMargin.top + legendMargin.bottom;
     mLegendRect.x = 0;
     mLegendRect.y = 0;
 
     nscoord oldSpace = mLegendSpace;
     mLegendSpace = 0;
     if (mLegendRect.height > border.top) {
       // center the border on the legend
       mLegendSpace = mLegendRect.height - border.top;
@@ -541,17 +541,18 @@ nsFieldSetFrame::Reflow(nsPresContext*  
         std::max(0, aReflowState.ComputedMinHeight() - mLegendSpace);
     }
 
     if (aReflowState.ComputedMaxHeight() != NS_UNCONSTRAINEDSIZE) {
       kidReflowState.ComputedMaxHeight() =
         std::max(0, aReflowState.ComputedMaxHeight() - mLegendSpace);
     }
 
-    nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.mFlags);
+    nsHTMLReflowMetrics kidDesiredSize(kidReflowState.GetWritingMode(),
+                                       aDesiredSize.mFlags);
     // Reflow the frame
     NS_ASSERTION(kidReflowState.ComputedPhysicalMargin() == nsMargin(0,0,0,0),
                  "Margins on anonymous fieldset child not supported!");
     nsPoint pt(border.left, border.top + mLegendSpace);
     ReflowChild(inner, aPresContext, kidDesiredSize, kidReflowState,
                 pt.x, pt.y, 0, aStatus);
 
     FinishReflowChild(inner, aPresContext, &kidReflowState, 
@@ -607,27 +608,27 @@ nsFieldSetFrame::Reflow(nsPresContext*  
     legendReflowState.ref().ApplyRelativePositioning(&actualLegendPos);
     legend->SetPosition(actualLegendPos);
     nsContainerFrame::PositionFrameView(legend);
     nsContainerFrame::PositionChildViews(legend);
   }
 
   // Return our size and our result
   if (aReflowState.ComputedHeight() == NS_INTRINSICSIZE) {
-    aDesiredSize.height = mLegendSpace + 
+    aDesiredSize.Height() = mLegendSpace + 
                           border.TopBottom() +
                           (inner ? inner->GetRect().height : 0);
   } else {
     nscoord min = border.TopBottom() + mLegendRect.height;
-    aDesiredSize.height =
+    aDesiredSize.Height() =
       aReflowState.ComputedHeight() + aReflowState.ComputedPhysicalBorderPadding().TopBottom();
-    if (aDesiredSize.height < min)
-      aDesiredSize.height = min;
+    if (aDesiredSize.Height() < min)
+      aDesiredSize.Height() = min;
   }
-  aDesiredSize.width = contentRect.width + border.LeftRight();
+  aDesiredSize.Width() = contentRect.width + border.LeftRight();
   aDesiredSize.SetOverflowAreasToDesiredBounds();
   if (legend)
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, legend);
   if (inner)
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, inner);
 
   // Merge overflow container bounds and status.
   aDesiredSize.mOverflowAreas.UnionWith(ocBounds);
--- a/layout/forms/nsFormControlFrame.cpp
+++ b/layout/forms/nsFormControlFrame.cpp
@@ -89,18 +89,18 @@ nsFormControlFrame::Reflow(nsPresContext
   nsresult rv = nsLeafFrame::Reflow(aPresContext, aDesiredSize, aReflowState,
                                     aStatus);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   if (nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) {
     float inflation = nsLayoutUtils::FontSizeInflationFor(this);
-    aDesiredSize.width *= inflation;
-    aDesiredSize.height *= inflation;
+    aDesiredSize.Width() *= inflation;
+    aDesiredSize.Height() *= inflation;
     aDesiredSize.UnionOverflowAreasWithDesiredBounds();
     FinishAndStoreOverflow(&aDesiredSize);
   }
   return NS_OK;
 }
 
 nsresult
 nsFormControlFrame::RegUnRegAccessKey(nsIFrame * aFrame, bool aDoReg)
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -278,17 +278,17 @@ nsHTMLButtonControlFrame::ReflowButtonCo
   nsHTMLReflowState adjustedButtonReflowState =
     CloneReflowStateWithReducedContentBox(aButtonReflowState, focusPadding);
 
   nsHTMLReflowState contentsReflowState(aPresContext,
                                         adjustedButtonReflowState,
                                         aFirstKid, availSize);
 
   nsReflowStatus contentsReflowStatus;
-  nsHTMLReflowMetrics contentsDesiredSize;
+  nsHTMLReflowMetrics contentsDesiredSize(aButtonReflowState.GetWritingMode());
   ReflowChild(aFirstKid, aPresContext,
               contentsDesiredSize, contentsReflowState,
               xoffset,
               focusPadding.top + aButtonReflowState.ComputedPhysicalBorderPadding().top,
               0, contentsReflowStatus);
   MOZ_ASSERT(NS_FRAME_IS_COMPLETE(contentsReflowStatus),
              "We gave button-contents frame unconstrained available height, "
              "so it should be complete");
@@ -297,63 +297,63 @@ nsHTMLButtonControlFrame::ReflowButtonCo
   nscoord buttonContentBoxHeight = 0;
   if (aButtonReflowState.ComputedHeight() != NS_INTRINSICSIZE) {
     // Button has a fixed height -- that's its content-box height.
     buttonContentBoxHeight = aButtonReflowState.ComputedHeight();
   } else {
     // Button is intrinsically sized -- it should shrinkwrap the
     // button-contents' height, plus any focus-padding space:
     buttonContentBoxHeight =
-      contentsDesiredSize.height + focusPadding.TopBottom();
+      contentsDesiredSize.Height() + focusPadding.TopBottom();
 
     // Make sure we obey min/max-height in the case when we're doing intrinsic
     // sizing (we get it for free when we have a non-intrinsic
     // aButtonReflowState.ComputedHeight()).  Note that we do this before
     // adjusting for borderpadding, since mComputedMaxHeight and
     // mComputedMinHeight are content heights.
     buttonContentBoxHeight =
       NS_CSS_MINMAX(buttonContentBoxHeight,
                     aButtonReflowState.ComputedMinHeight(),
                     aButtonReflowState.ComputedMaxHeight());
   }
 
   // Center child vertically in the button
   // (technically, inside of the button's focus-padding area)
   nscoord extraSpace =
     buttonContentBoxHeight - focusPadding.TopBottom() -
-    contentsDesiredSize.height;
+    contentsDesiredSize.Height();
 
   nscoord yoffset = std::max(0, extraSpace / 2);
 
   // Adjust yoffset to be in terms of the button's frame-rect, instead of
   // its focus-padding rect:
   yoffset += focusPadding.top + aButtonReflowState.ComputedPhysicalBorderPadding().top;
 
   // Place the child
   FinishReflowChild(aFirstKid, aPresContext,
                     &contentsReflowState, contentsDesiredSize,
                     xoffset, yoffset, 0);
 
   // Make sure we have a useful 'ascent' value for the child
-  if (contentsDesiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
-    contentsDesiredSize.ascent = aFirstKid->GetBaseline();
+  if (contentsDesiredSize.TopAscent() == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
+    contentsDesiredSize.SetTopAscent(aFirstKid->GetBaseline());
   }
 
   // OK, we're done with the child frame.
   // Use what we learned to populate the button frame's reflow metrics.
   //  * Button's height & width are content-box size + border-box contribution:
-  aButtonDesiredSize.width = aButtonReflowState.ComputedWidth() +
+  aButtonDesiredSize.Width() = aButtonReflowState.ComputedWidth() +
     aButtonReflowState.ComputedPhysicalBorderPadding().LeftRight();
 
-  aButtonDesiredSize.height = buttonContentBoxHeight +
+  aButtonDesiredSize.Height() = buttonContentBoxHeight +
     aButtonReflowState.ComputedPhysicalBorderPadding().TopBottom();
 
   //  * Button's ascent is its child's ascent, plus the child's y-offset
   // within our frame:
-  aButtonDesiredSize.ascent = contentsDesiredSize.ascent + yoffset;
+  aButtonDesiredSize.SetTopAscent(contentsDesiredSize.TopAscent() + yoffset);
 
   aButtonDesiredSize.SetOverflowAreasToDesiredBounds();
 }
 
 nsresult nsHTMLButtonControlFrame::SetFormProperty(nsIAtom* aName, const nsAString& aValue)
 {
   if (nsGkAtoms::value == aName) {
     return mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::value,
--- a/layout/forms/nsMeterFrame.cpp
+++ b/layout/forms/nsMeterFrame.cpp
@@ -108,19 +108,19 @@ NS_IMETHODIMP nsMeterFrame::Reflow(nsPre
     nsFormControlFrame::RegUnRegAccessKey(this, true);
   }
 
   nsIFrame* barFrame = mBarDiv->GetPrimaryFrame();
   NS_ASSERTION(barFrame, "The meter frame should have a child with a frame!");
 
   ReflowBarFrame(barFrame, aPresContext, aReflowState, aStatus);
 
-  aDesiredSize.width = aReflowState.ComputedWidth() +
+  aDesiredSize.Width() = aReflowState.ComputedWidth() +
                        aReflowState.ComputedPhysicalBorderPadding().LeftRight();
-  aDesiredSize.height = aReflowState.ComputedHeight() +
+  aDesiredSize.Height() = aReflowState.ComputedHeight() +
                         aReflowState.ComputedPhysicalBorderPadding().TopBottom();
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
   ConsiderChildOverflow(aDesiredSize.mOverflowAreas, barFrame);
   FinishAndStoreOverflow(&aDesiredSize);
 
   aStatus = NS_FRAME_COMPLETE;
 
@@ -174,17 +174,17 @@ nsMeterFrame::ReflowBarFrame(nsIFrame*  
             reflowState.ComputedPhysicalBorderPadding().LeftRight();
     size = std::max(size, 0);
     reflowState.SetComputedWidth(size);
   }
 
   xoffset += reflowState.ComputedPhysicalMargin().left;
   yoffset += reflowState.ComputedPhysicalMargin().top;
 
-  nsHTMLReflowMetrics barDesiredSize;
+  nsHTMLReflowMetrics barDesiredSize(reflowState.GetWritingMode());
   ReflowChild(aBarFrame, aPresContext, barDesiredSize, reflowState, xoffset,
               yoffset, 0, aStatus);
   FinishReflowChild(aBarFrame, aPresContext, &reflowState, barDesiredSize,
                     xoffset, yoffset, 0);
 }
 
 NS_IMETHODIMP
 nsMeterFrame::AttributeChanged(int32_t  aNameSpaceID,
--- a/layout/forms/nsNumberControlFrame.cpp
+++ b/layout/forms/nsNumberControlFrame.cpp
@@ -77,40 +77,40 @@ nsNumberControlFrame::Reflow(nsPresConte
   NS_ASSERTION(!mFrames.FirstChild() ||
                !mFrames.FirstChild()->GetNextSibling(),
                "We expect at most one direct child frame");
 
   if (mState & NS_FRAME_FIRST_REFLOW) {
     nsFormControlFrame::RegUnRegAccessKey(this, true);
   }
 
-  nsHTMLReflowMetrics wrappersDesiredSize;
+  nsHTMLReflowMetrics wrappersDesiredSize(aReflowState.GetWritingMode());
   nsIFrame* outerWrapperFrame = mOuterWrapper->GetPrimaryFrame();
   if (outerWrapperFrame) { // display:none?
     NS_ASSERTION(outerWrapperFrame == mFrames.FirstChild(), "huh?");
     nsresult rv =
       ReflowAnonymousContent(aPresContext, wrappersDesiredSize,
                              aReflowState, outerWrapperFrame);
     NS_ENSURE_SUCCESS(rv, rv);
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, outerWrapperFrame);
   }
 
   nscoord computedHeight = aReflowState.ComputedHeight();
   if (computedHeight == NS_AUTOHEIGHT) {
     computedHeight =
       outerWrapperFrame ? outerWrapperFrame->GetSize().height : 0;
   }
-  aDesiredSize.width = aReflowState.ComputedWidth() +
+  aDesiredSize.Width() = aReflowState.ComputedWidth() +
                          aReflowState.ComputedPhysicalBorderPadding().LeftRight();
-  aDesiredSize.height = computedHeight +
+  aDesiredSize.Height() = computedHeight +
                           aReflowState.ComputedPhysicalBorderPadding().TopBottom();
 
   if (outerWrapperFrame) {
-    aDesiredSize.ascent = wrappersDesiredSize.ascent +
-                            outerWrapperFrame->GetPosition().y;
+    aDesiredSize.SetTopAscent(wrappersDesiredSize.TopAscent() +
+                            outerWrapperFrame->GetPosition().y);
   }
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
 
   FinishAndStoreOverflow(&aDesiredSize);
 
   aStatus = NS_FRAME_COMPLETE;
 
--- a/layout/forms/nsProgressFrame.cpp
+++ b/layout/forms/nsProgressFrame.cpp
@@ -113,19 +113,19 @@ NS_IMETHODIMP nsProgressFrame::Reflow(ns
     nsFormControlFrame::RegUnRegAccessKey(this, true);
   }
 
   nsIFrame* barFrame = mBarDiv->GetPrimaryFrame();
   NS_ASSERTION(barFrame, "The progress frame should have a child with a frame!");
 
   ReflowBarFrame(barFrame, aPresContext, aReflowState, aStatus);
 
-  aDesiredSize.width = aReflowState.ComputedWidth() +
+  aDesiredSize.Width() = aReflowState.ComputedWidth() +
                        aReflowState.ComputedPhysicalBorderPadding().LeftRight();
-  aDesiredSize.height = aReflowState.ComputedHeight() +
+  aDesiredSize.Height() = aReflowState.ComputedHeight() +
                         aReflowState.ComputedPhysicalBorderPadding().TopBottom();
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
   ConsiderChildOverflow(aDesiredSize.mOverflowAreas, barFrame);
   FinishAndStoreOverflow(&aDesiredSize);
 
   aStatus = NS_FRAME_COMPLETE;
 
@@ -188,17 +188,17 @@ nsProgressFrame::ReflowBarFrame(nsIFrame
     // the width isn't constrained (position == -1 and !ShouldUseNativeStyle())
     // because aReflowState.ComputedHeight() - size == 0.
     yoffset += aReflowState.ComputedHeight() - reflowState.ComputedHeight();
   }
 
   xoffset += reflowState.ComputedPhysicalMargin().left;
   yoffset += reflowState.ComputedPhysicalMargin().top;
 
-  nsHTMLReflowMetrics barDesiredSize;
+  nsHTMLReflowMetrics barDesiredSize(aReflowState.GetWritingMode());
   ReflowChild(aBarFrame, aPresContext, barDesiredSize, reflowState, xoffset,
               yoffset, 0, aStatus);
   FinishReflowChild(aBarFrame, aPresContext, &reflowState, barDesiredSize,
                     xoffset, yoffset, 0);
 }
 
 NS_IMETHODIMP
 nsProgressFrame::AttributeChanged(int32_t  aNameSpaceID,
--- a/layout/forms/nsRangeFrame.cpp
+++ b/layout/forms/nsRangeFrame.cpp
@@ -265,19 +265,19 @@ nsRangeFrame::Reflow(nsPresContext*     
   if (mState & NS_FRAME_FIRST_REFLOW) {
     nsFormControlFrame::RegUnRegAccessKey(this, true);
   }
 
   nscoord computedHeight = aReflowState.ComputedHeight();
   if (computedHeight == NS_AUTOHEIGHT) {
     computedHeight = 0;
   }
-  aDesiredSize.width = aReflowState.ComputedWidth() +
+  aDesiredSize.Width() = aReflowState.ComputedWidth() +
                        aReflowState.ComputedPhysicalBorderPadding().LeftRight();
-  aDesiredSize.height = computedHeight +
+  aDesiredSize.Height() = computedHeight +
                         aReflowState.ComputedPhysicalBorderPadding().TopBottom();
 
   nsresult rv =
     ReflowAnonymousContent(aPresContext, aDesiredSize, aReflowState);
   NS_ENSURE_SUCCESS(rv, rv);
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
 
@@ -345,17 +345,17 @@ nsRangeFrame::ReflowAnonymousContent(nsP
     trackY -= trackReflowState.ComputedPhysicalBorderPadding().top +
                 trackReflowState.ComputedHeight() / 2;
 
     // Make relative to our border box instead of our content box:
     trackX += aReflowState.ComputedPhysicalBorderPadding().left;
     trackY += aReflowState.ComputedPhysicalBorderPadding().top;
 
     nsReflowStatus frameStatus;
-    nsHTMLReflowMetrics trackDesiredSize;
+    nsHTMLReflowMetrics trackDesiredSize(aReflowState.GetWritingMode());
     nsresult rv = ReflowChild(trackFrame, aPresContext, trackDesiredSize,
                               trackReflowState, trackX, trackY, 0, frameStatus);
     NS_ENSURE_SUCCESS(rv, rv);
     MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(frameStatus),
                "We gave our child unconstrained height, so it should be complete");
     rv = FinishReflowChild(trackFrame, aPresContext, &trackReflowState,
                            trackDesiredSize, trackX, trackY, 0);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -367,56 +367,56 @@ nsRangeFrame::ReflowAnonymousContent(nsP
     nsHTMLReflowState thumbReflowState(aPresContext, aReflowState, thumbFrame,
                                        nsSize(aReflowState.ComputedWidth(),
                                               NS_UNCONSTRAINEDSIZE));
 
     // Where we position the thumb depends on its size, so we first reflow
     // the thumb at {0,0} to obtain its size, then position it afterwards.
 
     nsReflowStatus frameStatus;
-    nsHTMLReflowMetrics thumbDesiredSize;
+    nsHTMLReflowMetrics thumbDesiredSize(aReflowState.GetWritingMode());
     nsresult rv = ReflowChild(thumbFrame, aPresContext, thumbDesiredSize,
                               thumbReflowState, 0, 0, 0, frameStatus);
     NS_ENSURE_SUCCESS(rv, rv);
     MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(frameStatus),
                "We gave our child unconstrained height, so it should be complete");
     rv = FinishReflowChild(thumbFrame, aPresContext, &thumbReflowState,
                            thumbDesiredSize, 0, 0, 0);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    DoUpdateThumbPosition(thumbFrame, nsSize(aDesiredSize.width,
-                                             aDesiredSize.height));
+    DoUpdateThumbPosition(thumbFrame, nsSize(aDesiredSize.Width(),
+                                             aDesiredSize.Height()));
   }
 
   nsIFrame* rangeProgressFrame = mProgressDiv->GetPrimaryFrame();
 
   if (rangeProgressFrame) { // display:none?
     nsHTMLReflowState progressReflowState(aPresContext, aReflowState,
                                           rangeProgressFrame,
                                           nsSize(aReflowState.ComputedWidth(),
                                                  NS_UNCONSTRAINEDSIZE));
 
     // We first reflow the range-progress frame at {0,0} to obtain its
     // unadjusted dimensions, then we adjust it to so that the appropriate edge
     // ends at the thumb.
 
     nsReflowStatus frameStatus;
-    nsHTMLReflowMetrics progressDesiredSize;
+    nsHTMLReflowMetrics progressDesiredSize(aReflowState.GetWritingMode());
     nsresult rv = ReflowChild(rangeProgressFrame, aPresContext,
                               progressDesiredSize, progressReflowState, 0, 0,
                               0, frameStatus);
     NS_ENSURE_SUCCESS(rv, rv);
     MOZ_ASSERT(NS_FRAME_IS_FULLY_COMPLETE(frameStatus),
                "We gave our child unconstrained height, so it should be complete");
     rv = FinishReflowChild(rangeProgressFrame, aPresContext,
                            &progressReflowState, progressDesiredSize, 0, 0, 0);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    DoUpdateRangeProgressFrame(rangeProgressFrame, nsSize(aDesiredSize.width,
-                                                          aDesiredSize.height));
+    DoUpdateRangeProgressFrame(rangeProgressFrame, nsSize(aDesiredSize.Width(),
+                                                          aDesiredSize.Height()));
   }
 
   return NS_OK;
 }
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsRangeFrame::AccessibleType()
--- a/layout/forms/nsSelectsAreaFrame.cpp
+++ b/layout/forms/nsSelectsAreaFrame.cpp
@@ -184,17 +184,17 @@ nsSelectsAreaFrame::Reflow(nsPresContext
   // Check whether we need to suppress scrollbar updates.  We want to do that if
   // we're in a possible first pass and our height of a row has changed.
   if (list->MightNeedSecondPass()) {
     nscoord newHeightOfARow = list->CalcHeightOfARow();
     // We'll need a second pass if our height of a row changed.  For
     // comboboxes, we'll also need it if our height changed.  If we're going
     // to do a second pass, suppress scrollbar updates for this pass.
     if (newHeightOfARow != mHeightOfARow ||
-        (isInDropdownMode && (oldHeight != aDesiredSize.height ||
+        (isInDropdownMode && (oldHeight != aDesiredSize.Height() ||
                               oldHeight != GetSize().height))) {
       mHeightOfARow = newHeightOfARow;
       list->SetSuppressScrollbarUpdate(true);
     }
   }
 
   return rv;
 }
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -483,37 +483,37 @@ nsTextControlFrame::Reflow(nsPresContext
   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
 
   // make sure that the form registers itself on the initial/first reflow
   if (mState & NS_FRAME_FIRST_REFLOW) {
     nsFormControlFrame::RegUnRegAccessKey(this, true);
   }
 
   // set values of reflow's out parameters
-  aDesiredSize.width = aReflowState.ComputedWidth() +
+  aDesiredSize.Width() = aReflowState.ComputedWidth() +
                        aReflowState.ComputedPhysicalBorderPadding().LeftRight();
-  aDesiredSize.height = aReflowState.ComputedHeight() +
+  aDesiredSize.Height() = aReflowState.ComputedHeight() +
                         aReflowState.ComputedPhysicalBorderPadding().TopBottom();
 
   // computation of the ascent wrt the input height
   nscoord lineHeight = aReflowState.ComputedHeight();
   float inflation = nsLayoutUtils::FontSizeInflationFor(this);
   if (!IsSingleLineTextControl()) {
     lineHeight = nsHTMLReflowState::CalcLineHeight(StyleContext(), 
                                                   NS_AUTOHEIGHT, inflation);
   }
   nsRefPtr<nsFontMetrics> fontMet;
   nsresult rv = nsLayoutUtils::GetFontMetricsForFrame(this, 
                                                       getter_AddRefs(fontMet), 
                                                       inflation);
   NS_ENSURE_SUCCESS(rv, rv);
   // now adjust for our borders and padding
-  aDesiredSize.ascent = 
+  aDesiredSize.SetTopAscent( 
         nsLayoutUtils::GetCenteredFontBaseline(fontMet, lineHeight) 
-        + aReflowState.ComputedPhysicalBorderPadding().top;
+        + aReflowState.ComputedPhysicalBorderPadding().top);
 
   // overflow handling
   aDesiredSize.SetOverflowAreasToDesiredBounds();
   // perform reflow on all kids
   nsIFrame* kid = mFrames.FirstChild();
   while (kid) {
     ReflowTextControlChild(kid, aPresContext, aReflowState, aStatus, aDesiredSize);
     kid = kid->GetNextSibling();
@@ -558,17 +558,17 @@ nsTextControlFrame::ReflowTextControlChi
 
   // compute the offsets
   nscoord xOffset = aReflowState.ComputedPhysicalBorderPadding().left
                       + kidReflowState.ComputedPhysicalMargin().left;
   nscoord yOffset = aReflowState.ComputedPhysicalBorderPadding().top
                       + kidReflowState.ComputedPhysicalMargin().top;
 
   // reflow the child
-  nsHTMLReflowMetrics desiredSize;  
+  nsHTMLReflowMetrics desiredSize(aReflowState.GetWritingMode());
   ReflowChild(aKid, aPresContext, desiredSize, kidReflowState, 
               xOffset, yOffset, 0, aStatus);
 
   // place the child
   FinishReflowChild(aKid, aPresContext, &kidReflowState, 
                     desiredSize, xOffset, yOffset, 0);
 
   // consider the overflow
--- a/layout/generic/nsAbsoluteContainingBlock.cpp
+++ b/layout/generic/nsAbsoluteContainingBlock.cpp
@@ -378,17 +378,17 @@ nsAbsoluteContainingBlock::ReflowAbsolut
   nscoord availWidth = aContainingBlock.width;
   if (availWidth == -1) {
     NS_ASSERTION(aReflowState.ComputedWidth() != NS_UNCONSTRAINEDSIZE,
                  "Must have a useful width _somewhere_");
     availWidth =
       aReflowState.ComputedWidth() + aReflowState.ComputedPhysicalPadding().LeftRight();
   }
 
-  nsHTMLReflowMetrics kidDesiredSize;
+  nsHTMLReflowMetrics kidDesiredSize(aReflowState.GetWritingMode());
   nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame,
                                    nsSize(availWidth, NS_UNCONSTRAINEDSIZE),
                                    aContainingBlock.width,
                                    aContainingBlock.height);
 
   // Send the WillReflow() notification and position the frame
   aKidFrame->WillReflow(aPresContext);
 
@@ -430,32 +430,32 @@ nsAbsoluteContainingBlock::ReflowAbsolut
     }
 
     if (NS_AUTOOFFSET == kidReflowState.ComputedPhysicalOffsets().left) {
       NS_ASSERTION(NS_AUTOOFFSET != kidReflowState.ComputedPhysicalOffsets().right,
                    "Can't solve for both left and right");
       kidReflowState.ComputedPhysicalOffsets().left = aContainingBlockWidth -
                                              kidReflowState.ComputedPhysicalOffsets().right -
                                              kidReflowState.ComputedPhysicalMargin().right -
-                                             kidDesiredSize.width -
+                                             kidDesiredSize.Width() -
                                              kidReflowState.ComputedPhysicalMargin().left;
     }
     if (NS_AUTOOFFSET == kidReflowState.ComputedPhysicalOffsets().top) {
       kidReflowState.ComputedPhysicalOffsets().top = aContainingBlockHeight -
                                             kidReflowState.ComputedPhysicalOffsets().bottom -
                                             kidReflowState.ComputedPhysicalMargin().bottom -
-                                            kidDesiredSize.height -
+                                            kidDesiredSize.Height() -
                                             kidReflowState.ComputedPhysicalMargin().top;
     }
   }
 
   // Position the child relative to our padding edge
   nsRect  rect(border.left + kidReflowState.ComputedPhysicalOffsets().left + kidReflowState.ComputedPhysicalMargin().left,
                border.top + kidReflowState.ComputedPhysicalOffsets().top + kidReflowState.ComputedPhysicalMargin().top,
-               kidDesiredSize.width, kidDesiredSize.height);
+               kidDesiredSize.Width(), kidDesiredSize.Height());
 
   // Offset the frame rect by the given origin of the absolute containing block.
   // If the frame is auto-positioned on both sides of an axis, it will be
   // positioned based on its containing block and we don't need to offset.
   if (aContainingBlock.TopLeft() != nsPoint(0, 0)) {
     if (!(kidReflowState.mStylePosition->mOffset.GetLeftUnit() == eStyleUnit_Auto &&
           kidReflowState.mStylePosition->mOffset.GetRightUnit() == eStyleUnit_Auto)) {
       rect.x += aContainingBlock.x;
--- a/layout/generic/nsBRFrame.cpp
+++ b/layout/generic/nsBRFrame.cpp
@@ -79,21 +79,21 @@ BRFrame::~BRFrame()
 NS_IMETHODIMP
 BRFrame::Reflow(nsPresContext* aPresContext,
                 nsHTMLReflowMetrics& aMetrics,
                 const nsHTMLReflowState& aReflowState,
                 nsReflowStatus& aStatus)
 {
   DO_GLOBAL_REFLOW_COUNT("BRFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
-  aMetrics.height = 0; // BR frames with height 0 are ignored in quirks
+  aMetrics.Height() = 0; // BR frames with height 0 are ignored in quirks
                        // mode by nsLineLayout::VerticalAlignFrames .
                        // However, it's not always 0.  See below.
-  aMetrics.width = 0;
-  aMetrics.ascent = 0;
+  aMetrics.Width() = 0;
+  aMetrics.SetTopAscent(0);
 
   // Only when the BR is operating in a line-layout situation will it
   // behave like a BR.
   nsLineLayout* ll = aReflowState.mLineLayout;
   if (ll) {
     // Note that the compatibility mode check excludes AlmostStandards
     // mode, since this is the inline box model.  See bug 161691.
     if ( ll->LineIsEmpty() ||
@@ -113,31 +113,30 @@ BRFrame::Reflow(nsPresContext* aPresCont
       // normal inline frame.  That line-height is used is important
       // here for cases where the line-height is less than 1.
       nsRefPtr<nsFontMetrics> fm;
       nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
         nsLayoutUtils::FontSizeInflationFor(this));
       aReflowState.rendContext->SetFont(fm); // FIXME: maybe not needed?
       if (fm) {
         nscoord logicalHeight = aReflowState.CalcLineHeight();
-        aMetrics.height = logicalHeight;
-        aMetrics.ascent =
-          nsLayoutUtils::GetCenteredFontBaseline(fm, logicalHeight);
+        aMetrics.Height() = logicalHeight;
+        aMetrics.SetTopAscent(nsLayoutUtils::GetCenteredFontBaseline(fm, logicalHeight));
       }
       else {
-        aMetrics.ascent = aMetrics.height = 0;
+        aMetrics.SetTopAscent(aMetrics.Height() = 0);
       }
 
       // XXX temporary until I figure out a better solution; see the
       // code in nsLineLayout::VerticalAlignFrames that zaps minY/maxY
       // if the width is zero.
       // XXX This also fixes bug 10036!
       // Warning: nsTextControlFrame::CalculateSizeStandard depends on
       // the following line, see bug 228752.
-      aMetrics.width = 1;
+      aMetrics.Width() = 1;
     }
 
     // Return our reflow status
     uint32_t breakType = aReflowState.mStyleDisplay->mBreakType;
     if (NS_STYLE_CLEAR_NONE == breakType) {
       breakType = NS_STYLE_CLEAR_LINE;
     }
 
@@ -146,17 +145,17 @@ BRFrame::Reflow(nsPresContext* aPresCont
     ll->SetLineEndsInBR(true);
   }
   else {
     aStatus = NS_FRAME_COMPLETE;
   }
 
   aMetrics.SetOverflowAreasToDesiredBounds();
 
-  mAscent = aMetrics.ascent;
+  mAscent = aMetrics.TopAscent();
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
   return NS_OK;
 }
 
 /* virtual */ void
 BRFrame::AddInlineMinWidth(nsRenderingContext *aRenderingContext,
                            nsIFrame::InlineMinWidthData *aData)
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1121,47 +1121,47 @@ nsBlockFrame::Reflow(nsPresContext*     
   // contains a block (example: <LI>\n<P>... ). This is where
   // the second case can happen.
   if (HasOutsideBullet() && !mLines.empty() &&
       (mLines.front()->IsBlock() ||
        (0 == mLines.front()->mBounds.height &&
         mLines.front() != mLines.back() &&
         mLines.begin().next()->IsBlock()))) {
     // Reflow the bullet
-    nsHTMLReflowMetrics metrics;
+    nsHTMLReflowMetrics metrics(aReflowState.GetWritingMode());
     // XXX Use the entire line when we fix bug 25888.
     nsLayoutUtils::LinePosition position;
     bool havePosition = nsLayoutUtils::GetFirstLinePosition(this, &position);
     nscoord lineTop = havePosition ? position.mTop
                                    : reflowState->ComputedPhysicalBorderPadding().top;
     nsIFrame* bullet = GetOutsideBullet();
     ReflowBullet(bullet, state, metrics, lineTop);
-    NS_ASSERTION(!BulletIsEmpty() || metrics.height == 0,
+    NS_ASSERTION(!BulletIsEmpty() || metrics.Height() == 0,
                  "empty bullet took up space");
 
     if (havePosition && !BulletIsEmpty()) {
       // We have some lines to align the bullet with.  
 
       // Doing the alignment using the baseline will also cater for
       // bullets that are placed next to a child block (bug 92896)
     
       // Tall bullets won't look particularly nice here...
       nsRect bbox = bullet->GetRect();
-      bbox.y = position.mBaseline - metrics.ascent;
+      bbox.y = position.mBaseline - metrics.TopAscent();
       bullet->SetRect(bbox);
     }
     // Otherwise just leave the bullet where it is, up against our top padding.
   }
 
   CheckFloats(state);
 
   // Compute our final size
   nscoord bottomEdgeOfChildren;
   ComputeFinalSize(*reflowState, state, aMetrics, &bottomEdgeOfChildren);
-  nsRect areaBounds = nsRect(0, 0, aMetrics.width, aMetrics.height);
+  nsRect areaBounds = nsRect(0, 0, aMetrics.Width(), aMetrics.Height());
   ComputeOverflowAreas(areaBounds, reflowState->mStyleDisplay,
                        bottomEdgeOfChildren, aMetrics.mOverflowAreas);
   // Factor overflow container child bounds into the overflow area
   aMetrics.mOverflowAreas.UnionWith(ocBounds);
   // Factor pushed float child bounds into the overflow area
   aMetrics.mOverflowAreas.UnionWith(fcBounds);
 
   // Let the absolutely positioned container reflow any absolutely positioned
@@ -1195,34 +1195,34 @@ nsBlockFrame::Reflow(nsPresContext*     
       if (haveInterrupt && (GetStateBits() & NS_FRAME_IS_DIRTY)) {
         absoluteContainer->MarkAllFramesDirty();
       } else {
         absoluteContainer->MarkSizeDependentFramesDirty();
       }
     } else {
       nsSize containingBlockSize =
         CalculateContainingBlockSizeForAbsolutes(*reflowState,
-                                                 nsSize(aMetrics.width,
-                                                        aMetrics.height));
+                                                 nsSize(aMetrics.Width(),
+                                                        aMetrics.Height()));
 
       // Mark frames that depend on changes we just made to this frame as dirty:
       // Now we can assume that the padding edge hasn't moved.
       // We need to reflow the absolutes if one of them depends on
       // its placeholder position, or the containing block size in a
       // direction in which the containing block size might have
       // changed.
-      bool cbWidthChanged = aMetrics.width != oldSize.width;
+      bool cbWidthChanged = aMetrics.Width() != oldSize.width;
       bool isRoot = !GetContent()->GetParent();
       // If isRoot and we have auto height, then we are the initial
       // containing block and the containing block height is the
       // viewport height, which can't change during incremental
       // reflow.
       bool cbHeightChanged =
         !(isRoot && NS_UNCONSTRAINEDSIZE == reflowState->ComputedHeight()) &&
-        aMetrics.height != oldSize.height;
+        aMetrics.Height() != oldSize.height;
 
       nsRect containingBlock(nsPoint(0, 0), containingBlockSize);
       absoluteContainer->Reflow(this, aPresContext, *reflowState,
                                 state.mReflowStatus,
                                 containingBlock, true,
                                 cbWidthChanged, cbHeightChanged,
                                 &aMetrics.mOverflowAreas);
 
@@ -1248,17 +1248,17 @@ nsBlockFrame::Reflow(nsPresContext*     
   // outside that time.
   nsLayoutUtils::AssertNoDuplicateContinuations(this, mFloats);
 
   if (gNoisyReflow) {
     IndentBy(stdout, gNoiseIndent);
     ListTag(stdout);
     printf(": status=%x (%scomplete) metrics=%d,%d carriedMargin=%d",
            aStatus, NS_FRAME_IS_COMPLETE(aStatus) ? "" : "not ",
-           aMetrics.width, aMetrics.height,
+           aMetrics.Width(), aMetrics.Height(),
            aMetrics.mCarriedOutBottomMargin.get());
     if (HasOverflowAreas()) {
       printf(" overflow-vis={%d,%d,%d,%d}",
              aMetrics.VisualOverflow().x,
              aMetrics.VisualOverflow().y,
              aMetrics.VisualOverflow().width,
              aMetrics.VisualOverflow().height);
       printf(" overflow-scr={%d,%d,%d,%d}",
@@ -1326,17 +1326,17 @@ nsBlockFrame::ComputeFinalSize(const nsH
   ListTag(stdout);
   printf(": mY=%d mIsBottomMarginRoot=%s mPrevBottomMargin=%d bp=%d,%d\n",
          aState.mY, aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? "yes" : "no",
          aState.mPrevBottomMargin,
          borderPadding.top, borderPadding.bottom);
 #endif
 
   // Compute final width
-  aMetrics.width =
+  aMetrics.Width() =
     NSCoordSaturatingAdd(NSCoordSaturatingAdd(borderPadding.left,
                                               aReflowState.ComputedWidth()), 
                          borderPadding.right);
 
   // Return bottom margin information
   // rbs says he hit this assertion occasionally (see bug 86947), so
   // just set the margin to zero and we'll figure out why later
   //NS_ASSERTION(aMetrics.mCarriedOutBottomMargin.IsZero(),
@@ -1392,22 +1392,22 @@ nsBlockFrame::ComputeFinalSize(const nsH
     ComputeFinalHeight(aReflowState, &aState.mReflowStatus,
                        aState.mY + nonCarriedOutVerticalMargin,
                        borderPadding, aMetrics, aState.mConsumedHeight);
     if (!NS_FRAME_IS_COMPLETE(aState.mReflowStatus)) {
       // Use the current height; continuations will take up the rest.
       // Do extend the height to at least consume the available
       // height, otherwise our left/right borders (for example) won't
       // extend all the way to the break.
-      aMetrics.height = std::max(aReflowState.AvailableHeight(),
+      aMetrics.Height() = std::max(aReflowState.AvailableHeight(),
                                aState.mY + nonCarriedOutVerticalMargin);
       // ... but don't take up more height than is available
       nscoord effectiveComputedHeight =
         GetEffectiveComputedHeight(aReflowState, aState.GetConsumedHeight());
-      aMetrics.height = std::min(aMetrics.height,
+      aMetrics.Height() = std::min(aMetrics.Height(),
                                borderPadding.top + effectiveComputedHeight);
       // XXX It's pretty wrong that our bottom border still gets drawn on
       // on its own on the last-in-flow, even if we ran out of height
       // here. We need GetSkipSides to check whether we ran out of content
       // height in the current frame, not whether it's last-in-flow.
     }
 
     // Don't carry out a bottom margin when our height is fixed.
@@ -1417,43 +1417,43 @@ nsBlockFrame::ComputeFinalSize(const nsH
     nscoord contentHeight = bottomEdgeOfChildren - borderPadding.top;
     nscoord autoHeight = aReflowState.ApplyMinMaxHeight(contentHeight);
     if (autoHeight != contentHeight) {
       // Our min-height or max-height made our height change.  Don't carry out
       // our kids' bottom margins.
       aMetrics.mCarriedOutBottomMargin.Zero();
     }
     autoHeight += borderPadding.top + borderPadding.bottom;
-    aMetrics.height = autoHeight;
+    aMetrics.Height() = autoHeight;
   }
   else {
     NS_ASSERTION(aReflowState.AvailableHeight() != NS_UNCONSTRAINEDSIZE,
       "Shouldn't be incomplete if availableHeight is UNCONSTRAINED.");
-    aMetrics.height = std::max(aState.mY, aReflowState.AvailableHeight());
+    aMetrics.Height() = std::max(aState.mY, aReflowState.AvailableHeight());
     if (aReflowState.AvailableHeight() == NS_UNCONSTRAINEDSIZE)
       // This should never happen, but it does. See bug 414255
-      aMetrics.height = aState.mY;
+      aMetrics.Height() = aState.mY;
   }
 
   if (IS_TRUE_OVERFLOW_CONTAINER(this) &&
       NS_FRAME_IS_NOT_COMPLETE(aState.mReflowStatus)) {
     // Overflow containers can only be overflow complete.
     // Note that auto height overflow containers have no normal children
-    NS_ASSERTION(aMetrics.height == 0, "overflow containers must be zero-height");
+    NS_ASSERTION(aMetrics.Height() == 0, "overflow containers must be zero-height");
     NS_FRAME_SET_OVERFLOW_INCOMPLETE(aState.mReflowStatus);
   }
 
   // Screen out negative heights --- can happen due to integer overflows :-(
-  aMetrics.height = std::max(0, aMetrics.height);
+  aMetrics.Height() = std::max(0, aMetrics.Height());
   *aBottomEdgeOfChildren = bottomEdgeOfChildren;
 
 #ifdef DEBUG_blocks
-  if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) {
+  if (CRAZY_WIDTH(aMetrics.Width()) || CRAZY_HEIGHT(aMetrics.Height())) {
     ListTag(stdout);
-    printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height);
+    printf(": WARNING: desired:%d,%d\n", aMetrics.Width(), aMetrics.Height());
   }
 #endif
 }
 
 void
 nsBlockFrame::ComputeOverflowAreas(const nsRect&         aBounds,
                                    const nsStyleDisplay* aDisplay,
                                    nscoord               aBottomEdgeOfChildren,
@@ -2354,45 +2354,49 @@ nsBlockFrame::ReflowDirtyLines(nsBlockRe
 
     if (NS_FRAME_IS_NOT_COMPLETE(aState.mReflowStatus)) {
       aState.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
     } //XXXfr shouldn't set this flag when nextinflow has no lines
   }
 
   // Handle an odd-ball case: a list-item with no lines
   if (HasOutsideBullet() && mLines.empty()) {
-    nsHTMLReflowMetrics metrics;
+    nsHTMLReflowMetrics metrics(aState.mReflowState.GetWritingMode());
     nsIFrame* bullet = GetOutsideBullet();
     ReflowBullet(bullet, aState, metrics,
                  aState.mReflowState.ComputedPhysicalBorderPadding().top);
-    NS_ASSERTION(!BulletIsEmpty() || metrics.height == 0,
+    NS_ASSERTION(!BulletIsEmpty() || metrics.Height() == 0,
                  "empty bullet took up space");
 
     if (!BulletIsEmpty()) {
       // There are no lines so we have to fake up some y motion so that
       // we end up with *some* height.
 
-      if (metrics.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE &&
-          !nsLayoutUtils::GetFirstLineBaseline(bullet, &metrics.ascent)) {
-        metrics.ascent = metrics.height;
+      if (metrics.TopAscent() == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
+        nscoord ascent;
+        if (nsLayoutUtils::GetFirstLineBaseline(bullet, &ascent)) {
+          metrics.SetTopAscent(ascent);
+        } else {
+          metrics.SetTopAscent(metrics.Height());
+        }
       }
 
       nsRefPtr<nsFontMetrics> fm;
       nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
         nsLayoutUtils::FontSizeInflationFor(this));
       aState.mReflowState.rendContext->SetFont(fm); // FIXME: needed?
 
       nscoord minAscent =
         nsLayoutUtils::GetCenteredFontBaseline(fm, aState.mMinLineHeight);
       nscoord minDescent = aState.mMinLineHeight - minAscent;
 
-      aState.mY += std::max(minAscent, metrics.ascent) +
-                   std::max(minDescent, metrics.height - metrics.ascent);
-
-      nscoord offset = minAscent - metrics.ascent;
+      aState.mY += std::max(minAscent, metrics.TopAscent()) +
+                   std::max(minDescent, metrics.Height() - metrics.TopAscent());
+
+      nscoord offset = minAscent - metrics.TopAscent();
       if (offset > 0) {
         bullet->SetRect(bullet->GetRect() + nsPoint(0, offset));
       }
     }
   }
 
   if (foundAnyClears) {
     AddStateBits(NS_BLOCK_HAS_CLEAR_CHILDREN);
@@ -4043,20 +4047,20 @@ nsBlockFrame::PlaceLine(nsBlockReflowSta
   // rare case: when the first line is empty.
   bool addedBullet = false;
   if (HasOutsideBullet() &&
       ((aLine == mLines.front() &&
         (!aLineLayout.IsZeroHeight() || (aLine == mLines.back()))) ||
        (mLines.front() != mLines.back() &&
         0 == mLines.front()->mBounds.height &&
         aLine == mLines.begin().next()))) {
-    nsHTMLReflowMetrics metrics;
+    nsHTMLReflowMetrics metrics(aState.mReflowState.GetWritingMode());
     nsIFrame* bullet = GetOutsideBullet();
     ReflowBullet(bullet, aState, metrics, aState.mY);
-    NS_ASSERTION(!BulletIsEmpty() || metrics.height == 0,
+    NS_ASSERTION(!BulletIsEmpty() || metrics.Height() == 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.
@@ -5878,30 +5882,30 @@ nsBlockFrame::ReflowFloat(nsBlockReflowS
   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?
-  aFloat->SetSize(nsSize(metrics.width, metrics.height));
+  aFloat->SetSize(nsSize(metrics.Width(), metrics.Height()));
   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,
                     nsDidReflowStatus::FINISHED);
 
 #ifdef NOISY_FLOAT
   printf("end ReflowFloat %p, sized to %d,%d\n",
-         aFloat, metrics.width, metrics.height);
+         aFloat, metrics.Width(), metrics.Height());
 #endif
 
   return NS_OK;
 }
 
 uint8_t
 nsBlockFrame::FindTrailingClear()
 {
@@ -6856,29 +6860,29 @@ nsBlockFrame::ReflowBullet(nsIFrame* aBu
   // the bullet at a position offset from there by the block's padding,
   // the block's border, and the bullet frame's margin.
   nscoord x;
   if (rs.mStyleVisibility->mDirection == NS_STYLE_DIRECTION_LTR) {
     // The floatAvailSpace.x gives us the content/float edge. Then we
     // subtract out the left border/padding and the bullet's width and
     // margin to offset the position.
     x = floatAvailSpace.x - rs.ComputedPhysicalBorderPadding().left
-        - reflowState.ComputedPhysicalMargin().right - aMetrics.width;
+        - reflowState.ComputedPhysicalMargin().right - aMetrics.Width();
   } else {
     // The XMost() of the available space give us offsets from the left
     // border edge.  Then we add the right border/padding and the
     // bullet's margin to offset the position.
     x = floatAvailSpace.XMost() + rs.ComputedPhysicalBorderPadding().right
         + reflowState.ComputedPhysicalMargin().left;
   }
 
   // Approximate the bullets position; vertical alignment will provide
   // the final vertical location.
   nscoord y = aState.mContentArea.y;
-  aBulletFrame->SetRect(nsRect(x, y, aMetrics.width, aMetrics.height));
+  aBulletFrame->SetRect(nsRect(x, y, aMetrics.Width(), aMetrics.Height()));
   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'
@@ -7088,42 +7092,42 @@ nsBlockFrame::ComputeFinalHeight(const n
   // Figure out how much of the computed height should be
   // applied to this frame.
   nscoord computedHeightLeftOver = GetEffectiveComputedHeight(aReflowState,
                                                               aConsumed);
   NS_ASSERTION(!( IS_TRUE_OVERFLOW_CONTAINER(this)
                   && computedHeightLeftOver ),
                "overflow container must not have computedHeightLeftOver");
 
-  aMetrics.height =
+  aMetrics.Height() =
     NSCoordSaturatingAdd(NSCoordSaturatingAdd(aBorderPadding.top,
                                               computedHeightLeftOver),
                          aBorderPadding.bottom);
 
   if (NS_FRAME_IS_NOT_COMPLETE(*aStatus)
-      && aMetrics.height < aReflowState.AvailableHeight()) {
+      && aMetrics.Height() < aReflowState.AvailableHeight()) {
     // We ran out of height on this page but we're incomplete
     // Set status to complete except for overflow
     NS_FRAME_SET_OVERFLOW_INCOMPLETE(*aStatus);
   }
 
   if (NS_FRAME_IS_COMPLETE(*aStatus)) {
     if (computedHeightLeftOver > 0 &&
         NS_UNCONSTRAINEDSIZE != aReflowState.AvailableHeight() &&
-        aMetrics.height > aReflowState.AvailableHeight()) {
+        aMetrics.Height() > aReflowState.AvailableHeight()) {
       if (ShouldAvoidBreakInside(aReflowState)) {
         *aStatus = NS_INLINE_LINE_BREAK_BEFORE();
         return;
       }
       // We don't fit and we consumed some of the computed height,
       // so we should consume all the available height and then
       // break.  If our bottom border/padding straddles the break
       // point, then this will increase our height and push the
       // border/padding to the next page/column.
-      aMetrics.height = std::max(aReflowState.AvailableHeight(),
+      aMetrics.Height() = std::max(aReflowState.AvailableHeight(),
                                  aContentHeight);
       NS_FRAME_SET_INCOMPLETE(*aStatus);
       if (!GetNextInFlow())
         *aStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
     }
   }
 }
 
--- a/layout/generic/nsBlockReflowContext.cpp
+++ b/layout/generic/nsBlockReflowContext.cpp
@@ -23,17 +23,17 @@
 #undef   REALLY_NOISY_MAX_ELEMENT_SIZE
 #undef  NOISY_VERTICAL_MARGINS
 #endif
 
 nsBlockReflowContext::nsBlockReflowContext(nsPresContext* aPresContext,
                                            const nsHTMLReflowState& aParentRS)
   : mPresContext(aPresContext),
     mOuterReflowState(aParentRS),
-    mMetrics()
+    mMetrics(aParentRS.GetWritingMode())
 {
 }
 
 static nsIFrame* DescendIntoBlockLevelFrame(nsIFrame* aFrame)
 {
   nsIAtom* type = aFrame->GetType();
   if (type == nsGkAtoms::columnSetFrame)
     return DescendIntoBlockLevelFrame(aFrame->GetFirstPrincipalChild());
@@ -247,36 +247,36 @@ nsBlockReflowContext::ReflowBlock(const 
     if ((mFrame->GetStateBits() & NS_BLOCK_FLOAT_MGR) == 0)
       aFrameRS.mBlockDelta = mOuterReflowState.mBlockDelta + ty - aLine->mBounds.y;
   }
 
   // Let frame know that we are reflowing it
   mFrame->WillReflow(mPresContext);
 
 #ifdef DEBUG
-  mMetrics.width = nscoord(0xdeadbeef);
-  mMetrics.height = nscoord(0xdeadbeef);
+  mMetrics.Width() = nscoord(0xdeadbeef);
+  mMetrics.Height() = nscoord(0xdeadbeef);
 #endif
 
   mOuterReflowState.mFloatManager->Translate(tx, ty);
   rv = mFrame->Reflow(mPresContext, mMetrics, aFrameRS, aFrameReflowStatus);
   mOuterReflowState.mFloatManager->Translate(-tx, -ty);
 
 #ifdef DEBUG
   if (!NS_INLINE_IS_BREAK_BEFORE(aFrameReflowStatus)) {
-    if (CRAZY_WIDTH(mMetrics.width) || CRAZY_HEIGHT(mMetrics.height)) {
+    if (CRAZY_WIDTH(mMetrics.Width()) || CRAZY_HEIGHT(mMetrics.Height())) {
       printf("nsBlockReflowContext: ");
       nsFrame::ListTag(stdout, mFrame);
-      printf(" metrics=%d,%d!\n", mMetrics.width, mMetrics.height);
+      printf(" metrics=%d,%d!\n", mMetrics.Width(), mMetrics.Height());
     }
-    if ((mMetrics.width == nscoord(0xdeadbeef)) ||
-        (mMetrics.height == nscoord(0xdeadbeef))) {
+    if ((mMetrics.Width() == nscoord(0xdeadbeef)) ||
+        (mMetrics.Height() == nscoord(0xdeadbeef))) {
       printf("nsBlockReflowContext: ");
       nsFrame::ListTag(stdout, mFrame);
-      printf(" didn't set w/h %d,%d!\n", mMetrics.width, mMetrics.height);
+      printf(" didn't set w/h %d,%d!\n", mMetrics.Width(), mMetrics.Height());
     }
   }
 #endif
 
   if (!mFrame->HasOverflowAreas()) {
     mMetrics.SetOverflowAreasToDesiredBounds();
   }
 
@@ -334,17 +334,17 @@ nsBlockReflowContext::PlaceBlock(const n
   // margin. See CSS 2.1 section 8.3.1; those rules seem to match
   // nsBlockFrame::IsEmpty(). Any such block must have zero height so
   // check that first. Note that a block can have clearance and still
   // have adjoining top/bottom margins, because the clearance goes
   // above the top margin.
   // Mark the frame as non-dirty; it has been reflowed (or we wouldn't
   // be here), and we don't want to assert in CachedIsEmpty()
   mFrame->RemoveStateBits(NS_FRAME_IS_DIRTY);
-  bool empty = 0 == mMetrics.height && aLine->CachedIsEmpty();
+  bool empty = 0 == mMetrics.Height() && aLine->CachedIsEmpty();
   if (empty) {
     // Collapse the bottom margin with the top margin that was already
     // applied.
     aBottomMarginResult.Include(mTopMargin);
 
 #ifdef NOISY_VERTICAL_MARGINS
     printf("  ");
     nsFrame::ListTag(stdout, mOuterReflowState.frame);
@@ -371,28 +371,28 @@ nsBlockReflowContext::PlaceBlock(const n
     // line's YMost, and it must place the next line at a different
     // point from where this empty block will be.
     backupContainingBlockAdvance = mTopMargin.get();
   }
 
   // See if the frame fit. If it's the first frame or empty then it
   // always fits. If the height is unconstrained then it always fits,
   // even if there's some sort of integer overflow that makes y +
-  // mMetrics.height appear to go beyond the available height.
+  // mMetrics.Height() appear to go beyond the available height.
   if (!empty && !aForceFit && mSpace.height != NS_UNCONSTRAINEDSIZE) {
-    nscoord yMost = position.y - backupContainingBlockAdvance + mMetrics.height;
+    nscoord yMost = position.y - backupContainingBlockAdvance + mMetrics.Height();
     if (yMost > mSpace.YMost()) {
       // didn't fit, we must acquit.
       mFrame->DidReflow(mPresContext, &aReflowState, nsDidReflowStatus::FINISHED);
       return false;
     }
   }
 
   aInFlowBounds = nsRect(position.x, position.y - backupContainingBlockAdvance,
-                         mMetrics.width, mMetrics.height);
+                         mMetrics.Width(), mMetrics.Height());
   
   aReflowState.ApplyRelativePositioning(&position);
   
   // Now place the frame and complete the reflow process
   nsContainerFrame::FinishReflowChild(mFrame, mPresContext, &aReflowState,
                                       mMetrics, position.x, position.y, 0);
 
   aOverflowAreas = mMetrics.mOverflowAreas + position;
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -1533,18 +1533,18 @@ nsBulletFrame::GetDesiredSize(nsPresCont
   RemoveStateBits(BULLET_FRAME_IMAGE_LOADING);
 
   if (myList->GetListStyleImage() && mImageRequest) {
     uint32_t status;
     mImageRequest->GetImageStatus(&status);
     if (status & imgIRequest::STATUS_SIZE_AVAILABLE &&
         !(status & imgIRequest::STATUS_ERROR)) {
       // auto size the image
-      aMetrics.width = mIntrinsicSize.width;
-      aMetrics.ascent = aMetrics.height = mIntrinsicSize.height;
+      aMetrics.Width() = mIntrinsicSize.width;
+      aMetrics.SetTopAscent(aMetrics.Height() = mIntrinsicSize.height);
 
       AddStateBits(BULLET_FRAME_IMAGE_LOADING);
 
       return;
     }
   }
 
   // If we're getting our desired size and don't have an image, reset
@@ -1558,29 +1558,29 @@ nsBulletFrame::GetDesiredSize(nsPresCont
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
                                         aFontSizeInflation);
   nscoord bulletSize;
 
   nsAutoString text;
   switch (myList->mListStyleType) {
     case NS_STYLE_LIST_STYLE_NONE:
-      aMetrics.width = 0;
-      aMetrics.ascent = aMetrics.height = 0;
+      aMetrics.Width() = aMetrics.Height() = 0;
+      aMetrics.SetTopAscent(0);
       break;
 
     case NS_STYLE_LIST_STYLE_DISC:
     case NS_STYLE_LIST_STYLE_CIRCLE:
     case NS_STYLE_LIST_STYLE_SQUARE:
       ascent = fm->MaxAscent();
       bulletSize = std::max(nsPresContext::CSSPixelsToAppUnits(MIN_BULLET_SIZE),
                           NSToCoordRound(0.8f * (float(ascent) / 2.0f)));
       mPadding.bottom = NSToCoordRound(float(ascent) / 8.0f);
-      aMetrics.width = aMetrics.height = bulletSize;
-      aMetrics.ascent = bulletSize + mPadding.bottom;
+      aMetrics.Width() = aMetrics.Height() = bulletSize;
+      aMetrics.SetTopAscent(bulletSize + mPadding.bottom);
       break;
 
     default:
     case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO:
     case NS_STYLE_LIST_STYLE_DECIMAL:
     case NS_STYLE_LIST_STYLE_CJK_DECIMAL:
     case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
     case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
@@ -1631,22 +1631,22 @@ nsBulletFrame::GetDesiredSize(nsPresCont
     case NS_STYLE_LIST_STYLE_MOZ_HANGUL:
     case NS_STYLE_LIST_STYLE_MOZ_HANGUL_CONSONANT:
     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME:
     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_NUMERIC:
     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_AM:
     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ER:
     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET:
       GetListItemText(*myList, text);
-      aMetrics.height = fm->MaxHeight();
+      aMetrics.Height() = fm->MaxHeight();
       aRenderingContext->SetFont(fm);
-      aMetrics.width =
+      aMetrics.Width() =
         nsLayoutUtils::GetStringWidth(this, aRenderingContext,
                                       text.get(), text.Length());
-      aMetrics.ascent = fm->MaxAscent();
+      aMetrics.SetTopAscent(fm->MaxAscent());
       break;
   }
 }
 
 NS_IMETHODIMP
 nsBulletFrame::Reflow(nsPresContext* aPresContext,
                       nsHTMLReflowMetrics& aMetrics,
                       const nsHTMLReflowState& aReflowState,
@@ -1670,47 +1670,47 @@ nsBulletFrame::Reflow(nsPresContext* aPr
   if (!mSuppressPadding ||
       aPresContext->HasAuthorSpecifiedRules(this,
                                             NS_AUTHOR_SPECIFIED_PADDING)) {
     mPadding.top += NSToCoordRound(borderPadding.top * inflation);
     mPadding.right += NSToCoordRound(borderPadding.right * inflation);
     mPadding.bottom += NSToCoordRound(borderPadding.bottom * inflation);
     mPadding.left += NSToCoordRound(borderPadding.left * inflation);
   }
-  aMetrics.width += mPadding.left + mPadding.right;
-  aMetrics.height += mPadding.top + mPadding.bottom;
-  aMetrics.ascent += mPadding.top;
+  aMetrics.Width() += mPadding.left + mPadding.right;
+  aMetrics.Height() += mPadding.top + mPadding.bottom;
+  aMetrics.SetTopAscent(aMetrics.TopAscent() + mPadding.top);
 
   // XXX this is a bit of a hack, we're assuming that no glyphs used for bullets
   // overflow their font-boxes. It'll do for now; to fix it for real, we really
   // should rewrite all the text-handling code here to use gfxTextRun (bug
   // 397294).
   aMetrics.SetOverflowAreasToDesiredBounds();
 
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
   return NS_OK;
 }
 
 /* virtual */ nscoord
 nsBulletFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
 {
-  nsHTMLReflowMetrics metrics;
-  DISPLAY_MIN_WIDTH(this, metrics.width);
+  nsHTMLReflowMetrics metrics(GetWritingMode());
+  DISPLAY_MIN_WIDTH(this, metrics.Width());
   GetDesiredSize(PresContext(), aRenderingContext, metrics, 1.0f);
-  return metrics.width;
+  return metrics.Width();
 }
 
 /* virtual */ nscoord
 nsBulletFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
 {
-  nsHTMLReflowMetrics metrics;
-  DISPLAY_PREF_WIDTH(this, metrics.width);
+  nsHTMLReflowMetrics metrics(GetWritingMode());
+  DISPLAY_PREF_WIDTH(this, metrics.Width());
   GetDesiredSize(PresContext(), aRenderingContext, metrics, 1.0f);
-  return metrics.width;
+  return metrics.Width();
 }
 
 NS_IMETHODIMP
 nsBulletFrame::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
 {
   if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
     nsCOMPtr<imgIContainer> image;
     aRequest->GetImage(getter_AddRefs(image));
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -487,20 +487,20 @@ nsCanvasFrame::Reflow(nsPresContext*    
 
   // Reflow our one and only normal child frame. It's either the root
   // element's frame or a placeholder for that frame, if the root element
   // is abs-pos or fixed-pos. We may have additional children which
   // are placeholders for continuations of fixed-pos content, but those
   // don't need to be reflowed. The normal child is always comes before
   // the fixed-pos placeholders, because we insert it at the start
   // of the child list, above.
-  nsHTMLReflowMetrics kidDesiredSize;
+  nsHTMLReflowMetrics kidDesiredSize(aReflowState.GetWritingMode());
   if (mFrames.IsEmpty()) {
     // We have no child frame, so return an empty size
-    aDesiredSize.width = aDesiredSize.height = 0;
+    aDesiredSize.Width() = aDesiredSize.Height() = 0;
   } else {
     nsIFrame* kidFrame = mFrames.FirstChild();
     bool kidDirty = (kidFrame->GetStateBits() & NS_FRAME_IS_DIRTY) != 0;
 
     nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
                                      nsSize(aReflowState.AvailableWidth(),
                                             aReflowState.AvailableHeight()));
 
@@ -555,22 +555,22 @@ nsCanvasFrame::Reflow(nsPresContext*    
       // which doesn't need to be painted.
       nsIFrame* viewport = PresContext()->GetPresShell()->GetRootFrame();
       viewport->InvalidateFrame();
     }
     
     // Return our desired size. Normally it's what we're told, but
     // sometimes we can be given an unconstrained height (when a window
     // is sizing-to-content), and we should compute our desired height.
-    aDesiredSize.width = aReflowState.ComputedWidth();
+    aDesiredSize.Width() = aReflowState.ComputedWidth();
     if (aReflowState.ComputedHeight() == NS_UNCONSTRAINEDSIZE) {
-      aDesiredSize.height = kidFrame->GetRect().height +
+      aDesiredSize.Height() = kidFrame->GetRect().height +
         kidReflowState.ComputedPhysicalMargin().TopBottom();
     } else {
-      aDesiredSize.height = aReflowState.ComputedHeight();
+      aDesiredSize.Height() = aReflowState.ComputedHeight();
     }
 
     aDesiredSize.SetOverflowAreasToDesiredBounds();
     aDesiredSize.mOverflowAreas.UnionWith(
       kidDesiredSize.mOverflowAreas + kidPt);
   }
 
   if (prevCanvasFrame) {
--- a/layout/generic/nsColumnSetFrame.cpp
+++ b/layout/generic/nsColumnSetFrame.cpp
@@ -558,17 +558,18 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
       // Note if the column's next in flow is not being changed by this incremental reflow.
       // This may allow the current column to avoid trying to pull lines from the next column.
       if (child->GetNextSibling() &&
           !(GetStateBits() & NS_FRAME_IS_DIRTY) &&
         !(child->GetNextSibling()->GetStateBits() & NS_FRAME_IS_DIRTY)) {
         kidReflowState.mFlags.mNextInFlowUntouched = true;
       }
     
-      nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.mFlags);
+      nsHTMLReflowMetrics kidDesiredSize(aReflowState.GetWritingMode(),
+                                         aDesiredSize.mFlags);
 
       // XXX it would be cool to consult the float manager for the
       // previous block to figure out the region of floats from the
       // previous column that extend into this column, and subtract
       // that region from the new float manager.  So you could stick a
       // really big float in the first column and text in following
       // columns would flow around it.
 
@@ -577,17 +578,17 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
                   childOrigin.x + kidReflowState.ComputedPhysicalMargin().left,
                   childOrigin.y + kidReflowState.ComputedPhysicalMargin().top,
                   0, aStatus);
 
       reflowNext = (aStatus & NS_FRAME_REFLOW_NEXTINFLOW) != 0;
     
 #ifdef DEBUG_roc
       printf("*** Reflowed child #%d %p: status = %d, desiredSize=%d,%d CarriedOutBottomMargin=%d\n",
-             columnCount, (void*)child, aStatus, kidDesiredSize.width, kidDesiredSize.height,
+             columnCount, (void*)child, aStatus, kidDesiredSize.Width(), kidDesiredSize.Height(),
              kidDesiredSize.mCarriedOutBottomMargin.get());
 #endif
 
       NS_FRAME_TRACE_REFLOW_OUT("Column::Reflow", aStatus);
 
       *aBottomMarginCarriedOut = kidDesiredSize.mCarriedOutBottomMargin;
       
       FinishReflowChild(child, PresContext(), &kidReflowState, 
@@ -744,19 +745,19 @@ nsColumnSetFrame::ReflowChildren(nsHTMLR
                                                         aConfig.mConsumedHeight);
   }
   if (aReflowState.ComputedWidth() != NS_INTRINSICSIZE) {
     contentSize.width = aReflowState.ComputedWidth();
   } else {
     contentSize.width = aReflowState.ApplyMinMaxWidth(contentSize.width);
   }
 
-  aDesiredSize.height = contentSize.height +
+  aDesiredSize.Height() = contentSize.height +
                         borderPadding.TopBottom();
-  aDesiredSize.width = contentSize.width +
+  aDesiredSize.Width() = contentSize.width +
                        borderPadding.LeftRight();
   aDesiredSize.mOverflowAreas = overflowRects;
   aDesiredSize.UnionOverflowAreasWithDesiredBounds();
 
 #ifdef DEBUG_roc
   printf("*** DONE PASS feasible=%d\n", allFit && NS_FRAME_IS_FULLY_COMPLETE(aStatus)
          && !NS_FRAME_IS_TRUNCATED(aStatus));
 #endif
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -1038,19 +1038,19 @@ nsContainerFrame::FinishReflowChild(nsIF
                                     const nsHTMLReflowMetrics& aDesiredSize,
                                     nscoord                    aX,
                                     nscoord                    aY,
                                     uint32_t                   aFlags)
 {
   nsPoint curOrigin = aKidFrame->GetPosition();
 
   if (NS_FRAME_NO_MOVE_FRAME != (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
-    aKidFrame->SetRect(nsRect(aX, aY, aDesiredSize.width, aDesiredSize.height));
+    aKidFrame->SetRect(nsRect(aX, aY, aDesiredSize.Width(), aDesiredSize.Height()));
   } else {
-    aKidFrame->SetSize(nsSize(aDesiredSize.width, aDesiredSize.height));
+    aKidFrame->SetSize(nsSize(aDesiredSize.Width(), aDesiredSize.Height()));
   }
 
   if (aKidFrame->HasView()) {
     nsView* view = aKidFrame->GetView();
     // Make sure the frame's view is properly sized and positioned and has
     // things like opacity correct
     SyncFrameViewAfterReflow(aPresContext, aKidFrame, view,
                              aDesiredSize.VisualOverflow(), aFlags);
@@ -1142,27 +1142,27 @@ nsContainerFrame::ReflowOverflowContaine
       NS_ASSERTION(prevInFlow,
                    "overflow container frame must have a prev-in-flow");
       NS_ASSERTION(frame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER,
                    "overflow container frame must have overflow container bit set");
       nsRect prevRect = prevInFlow->GetRect();
 
       // Initialize reflow params
       nsSize availSpace(prevRect.width, aReflowState.AvailableHeight());
-      nsHTMLReflowMetrics desiredSize;
+      nsHTMLReflowMetrics desiredSize(aReflowState.GetWritingMode());
       nsHTMLReflowState frameState(aPresContext, aReflowState,
                                    frame, availSpace);
       nsReflowStatus frameStatus;
 
       // Reflow
       rv = ReflowChild(frame, aPresContext, desiredSize, frameState,
                        prevRect.x, 0, aFlags, frameStatus, &tracker);
       NS_ENSURE_SUCCESS(rv, rv);
       //XXXfr Do we need to override any shrinkwrap effects here?
-      // e.g. desiredSize.width = prevRect.width;
+      // e.g. desiredSize.Width() = prevRect.width;
       rv = FinishReflowChild(frame, aPresContext, &frameState, desiredSize,
                              prevRect.x, 0, aFlags);
       NS_ENSURE_SUCCESS(rv, rv);
 
       // Handle continuations
       if (!NS_FRAME_IS_FULLY_COMPLETE(frameStatus)) {
         if (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
           // Abspos frames can't cause their parent to be incomplete,
--- a/layout/generic/nsFirstLetterFrame.cpp
+++ b/layout/generic/nsFirstLetterFrame.cpp
@@ -210,39 +210,39 @@ nsFirstLetterFrame::Reflow(nsPresContext
     kid->WillReflow(aPresContext);
     kid->Reflow(aPresContext, aMetrics, rs, aReflowStatus);
 
     ll.EndLineReflow();
     ll.SetInFirstLetter(false);
 
     // In the floating first-letter case, we need to set this ourselves;
     // nsLineLayout::BeginSpan will set it in the other case
-    mBaseline = aMetrics.ascent;
+    mBaseline = aMetrics.TopAscent();
   }
   else {
     // Pretend we are a span and reflow the child frame
     nsLineLayout* ll = aReflowState.mLineLayout;
     bool          pushedFrame;
 
     ll->SetInFirstLetter(
       mStyleContext->GetPseudo() == nsCSSPseudoElements::firstLetter);
     ll->BeginSpan(this, &aReflowState, bp.left, availSize.width, &mBaseline);
     ll->ReflowFrame(kid, aReflowStatus, &aMetrics, pushedFrame);
     ll->EndSpan(this);
     ll->SetInFirstLetter(false);
   }
 
   // Place and size the child and update the output metrics
-  kid->SetRect(nsRect(bp.left, bp.top, aMetrics.width, aMetrics.height));
+  kid->SetRect(nsRect(bp.left, bp.top, aMetrics.Width(), aMetrics.Height()));
   kid->FinishAndStoreOverflow(&aMetrics);
   kid->DidReflow(aPresContext, nullptr, nsDidReflowStatus::FINISHED);
 
-  aMetrics.width += lr;
-  aMetrics.height += tb;
-  aMetrics.ascent += bp.top;
+  aMetrics.Width() += lr;
+  aMetrics.Height() += tb;
+  aMetrics.SetTopAscent(aMetrics.TopAscent() + bp.top);
 
   // Ensure that the overflow rect contains the child textframe's overflow rect.
   // Note that if this is floating, the overline/underline drawable area is in
   // the overflow rect of the child textframe.
   aMetrics.UnionOverflowAreasWithDesiredBounds();
   ConsiderChildOverflow(aMetrics.mOverflowAreas, kid);
 
   if (!NS_INLINE_IS_BREAK_BEFORE(aReflowStatus)) {
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -923,17 +923,17 @@ nsFlexContainerFrame::
   // being vertically resized.
   // (Note: We don't have to do this for width, because InitResizeFlags
   // will always turn on mHResize on when it sees that the computed width
   // is different from current width, and that's all we need.)
   if (!aFlexItem.IsFrozen()) {  // Are we flexible?
     childRSForMeasuringHeight.mFlags.mVResize = true;
   }
 
-  nsHTMLReflowMetrics childDesiredSize;
+  nsHTMLReflowMetrics childDesiredSize(childRSForMeasuringHeight.GetWritingMode());
   nsReflowStatus childReflowStatus;
   const uint32_t flags = NS_FRAME_NO_MOVE_FRAME;
   nsresult rv = ReflowChild(aFlexItem.Frame(), aPresContext,
                             childDesiredSize, childRSForMeasuringHeight,
                             0, 0, flags, childReflowStatus);
   NS_ENSURE_SUCCESS(rv, rv);
 
   MOZ_ASSERT(NS_FRAME_IS_COMPLETE(childReflowStatus),
@@ -942,17 +942,17 @@ nsFlexContainerFrame::
 
   rv = FinishReflowChild(aFlexItem.Frame(), aPresContext,
                          &childRSForMeasuringHeight, childDesiredSize,
                          0, 0, flags);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Subtract border/padding in vertical axis, to get _just_
   // the effective computed value of the "height" property.
-  nscoord childDesiredHeight = childDesiredSize.height -
+  nscoord childDesiredHeight = childDesiredSize.Height() -
     childRSForMeasuringHeight.ComputedPhysicalBorderPadding().TopBottom();
   childDesiredHeight = std::max(0, childDesiredHeight);
 
   aFlexItem.SetFlexBaseSizeAndMainSize(childDesiredHeight);
   aFlexItem.SetHadMeasuringReflow();
 
   return NS_OK;
 }
@@ -2437,21 +2437,23 @@ FlexLine::PositionItemsInMainAxis(uint8_
 }
 
 // Helper method to take care of children who ASK_FOR_BASELINE, when
 // we need their baseline.
 static void
 ResolveReflowedChildAscent(nsIFrame* aFrame,
                            nsHTMLReflowMetrics& aChildDesiredSize)
 {
-  if (aChildDesiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
+  if (aChildDesiredSize.TopAscent() == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
     // Use GetFirstLineBaseline(), or just GetBaseline() if that fails.
-    if (!nsLayoutUtils::GetFirstLineBaseline(aFrame,
-                                             &aChildDesiredSize.ascent)) {
-      aChildDesiredSize.ascent = aFrame->GetBaseline();
+    nscoord ascent;
+    if (nsLayoutUtils::GetFirstLineBaseline(aFrame, &ascent)) {
+      aChildDesiredSize.SetTopAscent(ascent);
+    } else {
+      aChildDesiredSize.SetTopAscent(aFrame->GetBaseline());
     }
   }
 }
 
 nsresult
 nsFlexContainerFrame::SizeItemInCrossAxis(
   nsPresContext* aPresContext,
   const FlexboxAxisTracker& aAxisTracker,
@@ -2479,17 +2481,17 @@ nsFlexContainerFrame::SizeItemInCrossAxi
   if (aItem.GetAlignSelf() == NS_STYLE_ALIGN_ITEMS_STRETCH) {
     // This item's got "align-self: stretch", so we probably imposed a
     // stretched computed height on it during its previous reflow. We're
     // not imposing that height for *this* measuring reflow, so we need to
     // tell it to treat this reflow as a vertical resize (regardless of
     // whether any of its ancestors are being resized).
     aChildReflowState.mFlags.mVResize = true;
   }
-  nsHTMLReflowMetrics childDesiredSize;
+  nsHTMLReflowMetrics childDesiredSize(aChildReflowState.GetWritingMode());
   nsReflowStatus childReflowStatus;
   const uint32_t flags = NS_FRAME_NO_MOVE_FRAME;
   nsresult rv = ReflowChild(aItem.Frame(), aPresContext,
                             childDesiredSize, aChildReflowState,
                             0, 0, flags, childReflowStatus);
   aItem.SetHadMeasuringReflow();
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -2511,35 +2513,35 @@ nsFlexContainerFrame::SizeItemInCrossAxi
 
   // Tentatively store the child's desired content-box cross-size.
   // Note that childDesiredSize is the border-box size, so we have to
   // subtract border & padding to get the content-box size.
   // (Note that at this point in the code, we know our cross axis is vertical,
   // so we don't bother with making aAxisTracker pick the cross-axis component
   // for us.)
   nscoord crossAxisBorderPadding = aItem.GetBorderPadding().TopBottom();
-  if (childDesiredSize.height < crossAxisBorderPadding) {
+  if (childDesiredSize.Height() < crossAxisBorderPadding) {
     // Child's requested size isn't large enough for its border/padding!
     // This is OK for the trivial nsFrame::Reflow() impl, but other frame
     // classes should know better. So, if we get here, the child had better be
     // an instance of nsFrame (i.e. it should return null from GetType()).
     // XXXdholbert Once we've fixed bug 765861, we should upgrade this to an
     // assertion that trivially passes if bug 765861's flag has been flipped.
     NS_WARN_IF_FALSE(!aItem.Frame()->GetType(),
                      "Child should at least request space for border/padding");
     aItem.SetCrossSize(0);
   } else {
     // (normal case)
-    aItem.SetCrossSize(childDesiredSize.height - crossAxisBorderPadding);
+    aItem.SetCrossSize(childDesiredSize.Height() - crossAxisBorderPadding);
   }
 
   // If we need to do baseline-alignment, store the child's ascent.
   if (aItem.GetAlignSelf() == NS_STYLE_ALIGN_ITEMS_BASELINE) {
     ResolveReflowedChildAscent(aItem.Frame(), childDesiredSize);
-    aItem.SetAscent(childDesiredSize.ascent);
+    aItem.SetAscent(childDesiredSize.TopAscent());
   }
 
   return NS_OK;
 }
 
 void
 FlexLine::PositionItemsInCrossAxis(nscoord aLineStartPosition,
                                    const FlexboxAxisTracker& aAxisTracker)
@@ -2816,17 +2818,17 @@ nsFlexContainerFrame::Reflow(nsPresConte
         if (didOverrideComputedHeight) {
           childReflowState.mFlags.mVResize = true;
         }
       }
       // NOTE: Be very careful about doing anything else with childReflowState
       // after this point, because some of its methods (e.g. SetComputedWidth)
       // internally call InitResizeFlags and stomp on mVResize & mHResize.
 
-      nsHTMLReflowMetrics childDesiredSize;
+      nsHTMLReflowMetrics childDesiredSize(childReflowState.GetWritingMode());
       nsReflowStatus childReflowStatus;
       nsresult rv = ReflowChild(curItem.Frame(), aPresContext,
                                 childDesiredSize, childReflowState,
                                 physicalPosn.x, physicalPosn.y,
                                 0, childReflowStatus);
       NS_ENSURE_SUCCESS(rv, rv);
 
       // XXXdholbert Once we do pagination / splitting, we'll need to actually
@@ -2849,65 +2851,65 @@ nsFlexContainerFrame::Reflow(nsPresConte
       // children), then use this child's baseline as the container's baseline.
       if (lineIdx == 0 && i == 0 && flexContainerAscent == nscoord_MIN) {
         ResolveReflowedChildAscent(curItem.Frame(), childDesiredSize);
 
         // (We use GetNormalPosition() instead of physicalPosn because we don't
         // want relative positioning on the child to affect the baseline that we
         // read from it).
         flexContainerAscent = curItem.Frame()->GetNormalPosition().y +
-          childDesiredSize.ascent;
+          childDesiredSize.TopAscent();
       }
     }
   }
 
   nsSize desiredContentBoxSize =
     axisTracker.PhysicalSizeFromLogicalSizes(contentBoxMainSize,
                                              contentBoxCrossSize);
 
-  aDesiredSize.width = desiredContentBoxSize.width +
+  aDesiredSize.Width() = desiredContentBoxSize.width +
     containerBorderPadding.LeftRight();
   // Does *NOT* include bottom border/padding yet (we add that a bit lower down)
-  aDesiredSize.height = desiredContentBoxSize.height +
+  aDesiredSize.Height() = desiredContentBoxSize.height +
     containerBorderPadding.top;
 
   if (flexContainerAscent == nscoord_MIN) {
     // Still don't have our baseline set -- this happens if we have no
     // children (or if our children are huge enough that they have nscoord_MIN
     // as their baseline... in which case, we'll use the wrong baseline, but no
     // big deal)
     NS_WARN_IF_FALSE(lines[0].mItems.IsEmpty(),
                      "Have flex items but didn't get an ascent - that's odd "
                      "(or there are just gigantic sizes involved)");
     // Per spec, just use the bottom of content-box.
-    flexContainerAscent = aDesiredSize.height;
+    flexContainerAscent = aDesiredSize.Height();
   }
-  aDesiredSize.ascent = flexContainerAscent;
+  aDesiredSize.SetTopAscent(flexContainerAscent);
 
   // Now: If we're complete, add bottom border/padding to desired height
   // (unless that pushes us over available height, in which case we become
   // incomplete (unless we already weren't asking for any height, in which case
   // we stay complete to avoid looping forever)).
   // NOTE: If we're auto-height, we allow our bottom border/padding to push us
   // over the available height without requesting a continuation, for
   // consistency with the behavior of "display:block" elements.
   if (NS_FRAME_IS_COMPLETE(aStatus)) {
     // NOTE: We can't use containerBorderPadding.bottom for this, because if
     // we're auto-height, ApplySkipSides will have zeroed it (because it
     // assumed we might get a continuation). We have the correct value in
     // aReflowState.ComputedPhyiscalBorderPadding().bottom, though, so we use that.
     nscoord desiredHeightWithBottomBP =
-      aDesiredSize.height + aReflowState.ComputedPhysicalBorderPadding().bottom;
+      aDesiredSize.Height() + aReflowState.ComputedPhysicalBorderPadding().bottom;
 
     if (aReflowState.AvailableHeight() == NS_UNCONSTRAINEDSIZE ||
-        aDesiredSize.height == 0 ||
+        aDesiredSize.Height() == 0 ||
         desiredHeightWithBottomBP <= aReflowState.AvailableHeight() ||
         aReflowState.ComputedHeight() == NS_INTRINSICSIZE) {
       // Update desired height to include bottom border/padding
-      aDesiredSize.height = desiredHeightWithBottomBP;
+      aDesiredSize.Height() = desiredHeightWithBottomBP;
     } else {
       // We couldn't fit bottom border/padding, so we'll need a continuation.
       NS_FRAME_SET_INCOMPLETE(aStatus);
     }
   }
 
   // Overflow area = union(my overflow area, kids' overflow areas)
   aDesiredSize.SetOverflowAreasToDesiredBounds();
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -4178,19 +4178,19 @@ nsFrame::ReflowAbsoluteFrames(nsPresCont
 
     // Let the absolutely positioned container reflow any absolutely positioned
     // child frames that need to be reflowed
 
     // The containing block for the abs pos kids is formed by our padding edge.
     nsMargin computedBorder =
       aReflowState.ComputedPhysicalBorderPadding() - aReflowState.ComputedPhysicalPadding();
     nscoord containingBlockWidth =
-      aDesiredSize.width - computedBorder.LeftRight();
+      aDesiredSize.Width() - computedBorder.LeftRight();
     nscoord containingBlockHeight =
-      aDesiredSize.height - computedBorder.TopBottom();
+      aDesiredSize.Height() - computedBorder.TopBottom();
 
     nsContainerFrame* container = do_QueryFrame(this);
     NS_ASSERTION(container, "Abs-pos children only supported on container frames for now");
 
     nsRect containingBlock(0, 0, containingBlockWidth, containingBlockHeight);
     absoluteContainer->Reflow(container, aPresContext, aReflowState, aStatus,
                               containingBlock,
                               aConstrainHeight, true, true, // XXX could be optimized
@@ -4208,18 +4208,18 @@ nsFrame::CanContinueTextRun() const
 
 NS_IMETHODIMP
 nsFrame::Reflow(nsPresContext*          aPresContext,
                 nsHTMLReflowMetrics&     aDesiredSize,
                 const nsHTMLReflowState& aReflowState,
                 nsReflowStatus&          aStatus)
 {
   DO_GLOBAL_REFLOW_COUNT("nsFrame");
-  aDesiredSize.width = 0;
-  aDesiredSize.height = 0;
+  aDesiredSize.Width() = 0;
+  aDesiredSize.Height() = 0;
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo)
 {
@@ -5149,19 +5149,19 @@ bool
 nsFrame::IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
                             nsHTMLReflowMetrics& aMetrics,
                             nsReflowStatus& aStatus)
 {
   if (aReflowState.mReflowDepth >  MAX_FRAME_DEPTH) {
     NS_WARNING("frame tree too deep; setting zero size and returning");
     mState |= NS_FRAME_TOO_DEEP_IN_FRAME_TREE;
     ClearOverflowRects();
-    aMetrics.width = 0;
-    aMetrics.height = 0;
-    aMetrics.ascent = 0;
+    aMetrics.Width() = 0;
+    aMetrics.Height() = 0;
+    aMetrics.SetTopAscent(0);
     aMetrics.mCarriedOutBottomMargin.Zero();
     aMetrics.mOverflowAreas.Clear();
 
     if (GetNextInFlow()) {
       // Reflow depth might vary between reflows, so we might have
       // successfully reflowed and split this frame before.  If so, we
       // shouldn't delete its continuations.
       aStatus = NS_FRAME_NOT_COMPLETE;
@@ -7461,17 +7461,19 @@ nsFrame::RefreshSizeCache(nsBoxLayoutSta
 
       metrics->mBlockPrefSize.width =
         GetPrefWidth(rendContext) + bp.LeftRight();
       metrics->mBlockMinSize.width =
         GetMinWidth(rendContext) + bp.LeftRight();
     }
 
     // do the nasty.
-    nsHTMLReflowMetrics desiredSize;
+    const WritingMode wm = aState.OuterReflowState() ?
+      aState.OuterReflowState()->GetWritingMode() : GetWritingMode();
+    nsHTMLReflowMetrics desiredSize(wm);
     rv = BoxReflow(aState, presContext, desiredSize, rendContext,
                    rect.x, rect.y,
                    metrics->mBlockPrefSize.width, NS_UNCONSTRAINEDSIZE);
 
     metrics->mBlockMinSize.height = 0;
     // ok we need the max ascent of the items on the line. So to do this
     // ask the block for its line iterator. Get the max ascent.
     nsAutoLineIterator lines = GetLineIterator();
@@ -7488,26 +7490,26 @@ nsFrame::RefreshSizeCache(nsBoxLayoutSta
          lines->GetLine(count, &firstFrame, &framesOnLine, lineBounds, &lineFlags);
 
          if (lineBounds.height > metrics->mBlockMinSize.height)
            metrics->mBlockMinSize.height = lineBounds.height;
 
          count++;
       } while(firstFrame);
     } else {
-      metrics->mBlockMinSize.height = desiredSize.height;
+      metrics->mBlockMinSize.height = desiredSize.Height();
     }
 
     metrics->mBlockPrefSize.height = metrics->mBlockMinSize.height;
 
-    if (desiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
+    if (desiredSize.TopAscent() == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
       if (!nsLayoutUtils::GetFirstLineBaseline(this, &metrics->mBlockAscent))
         metrics->mBlockAscent = GetBaseline();
     } else {
-      metrics->mBlockAscent = desiredSize.ascent;
+      metrics->mBlockAscent = desiredSize.TopAscent();
     }
 
 #ifdef DEBUG_adaptor
     printf("min=(%d,%d), pref=(%d,%d), ascent=%d\n", metrics->mBlockMinSize.width,
                                                      metrics->mBlockMinSize.height,
                                                      metrics->mBlockPrefSize.width,
                                                      metrics->mBlockPrefSize.height,
                                                      metrics->mBlockAscent);
@@ -7647,58 +7649,60 @@ nsFrame::GetBoxAscent(nsBoxLayoutState& 
 
 nsresult
 nsFrame::DoLayout(nsBoxLayoutState& aState)
 {
   nsRect ourRect(mRect);
 
   nsRenderingContext* rendContext = aState.GetRenderingContext();
   nsPresContext* presContext = aState.PresContext();
-  nsHTMLReflowMetrics desiredSize;
+  const WritingMode wm = aState.OuterReflowState() ?
+    aState.OuterReflowState()->GetWritingMode() : GetWritingMode();
+  nsHTMLReflowMetrics desiredSize(wm);
   nsresult rv = NS_OK;
  
   if (rendContext) {
 
     rv = BoxReflow(aState, presContext, desiredSize, rendContext,
                    ourRect.x, ourRect.y, ourRect.width, ourRect.height);
 
     if (IsCollapsed()) {
       SetSize(nsSize(0, 0));
     } else {
 
       // if our child needs to be bigger. This might happend with
       // wrapping text. There is no way to predict its height until we
       // reflow it. Now that we know the height reshuffle upward.
-      if (desiredSize.width > ourRect.width ||
-          desiredSize.height > ourRect.height) {
+      if (desiredSize.Width() > ourRect.width ||
+          desiredSize.Height() > ourRect.height) {
 
 #ifdef DEBUG_GROW
         DumpBox(stdout);
         printf(" GREW from (%d,%d) -> (%d,%d)\n",
                ourRect.width, ourRect.height,
-               desiredSize.width, desiredSize.height);
+               desiredSize.Width(), desiredSize.Height());
 #endif
 
-        if (desiredSize.width > ourRect.width)
-          ourRect.width = desiredSize.width;
-
-        if (desiredSize.height > ourRect.height)
-          ourRect.height = desiredSize.height;
+        if (desiredSize.Width() > ourRect.width)
+          ourRect.width = desiredSize.Width();
+
+        if (desiredSize.Height() > ourRect.height)
+          ourRect.height = desiredSize.Height();
       }
 
       // ensure our size is what we think is should be. Someone could have
       // reset the frame to be smaller or something dumb like that. 
       SetSize(ourRect.Size());
     }
   }
 
   // Should we do this if IsCollapsed() is true?
   nsSize size(GetSize());
-  desiredSize.width = size.width;
-  desiredSize.height = size.height;
+  desiredSize.Width() = size.width;
+  desiredSize.Height() = size.height;
   desiredSize.UnionOverflowAreasWithDesiredBounds();
 
   if (HasAbsolutelyPositionedChildren()) {
     // Set up a |reflowState| to pass into ReflowAbsoluteFrames
     nsHTMLReflowState reflowState(aState.PresContext(), this,
                                   aState.GetRenderingContext(),
                                   nsSize(size.width, NS_UNCONSTRAINEDSIZE),
                                   nsHTMLReflowState::DUMMY_PARENT_REFLOW_STATE);
@@ -7748,22 +7752,22 @@ nsFrame::BoxReflow(nsBoxLayoutState&    
   // lets see if we are already that size. Yes? then don't even reflow. We are done.
   if (!needsReflow) {
       
       if (aWidth != NS_INTRINSICSIZE && aHeight != NS_INTRINSICSIZE) {
       
           // if the new calculated size has a 0 width or a 0 height
           if ((metrics->mLastSize.width == 0 || metrics->mLastSize.height == 0) && (aWidth == 0 || aHeight == 0)) {
                needsReflow = false;
-               aDesiredSize.width = aWidth; 
-               aDesiredSize.height = aHeight; 
-               SetSize(nsSize(aDesiredSize.width, aDesiredSize.height));
+               aDesiredSize.Width() = aWidth; 
+               aDesiredSize.Height() = aHeight; 
+               SetSize(nsSize(aDesiredSize.Width(), aDesiredSize.Height()));
           } else {
-            aDesiredSize.width = metrics->mLastSize.width;
-            aDesiredSize.height = metrics->mLastSize.height;
+            aDesiredSize.Width() = metrics->mLastSize.width;
+            aDesiredSize.Height() = metrics->mLastSize.height;
 
             // remove the margin. The rect of our child does not include it but our calculated size does.
             // don't reflow if we are already the right size
             if (metrics->mLastSize.width == aWidth && metrics->mLastSize.height == aHeight)
                   needsReflow = false;
             else
                   needsReflow = true;
    
@@ -7773,18 +7777,18 @@ nsFrame::BoxReflow(nsBoxLayoutState&    
           // we don't know what it should be.
          needsReflow = true;
       }
   }
                              
   // ok now reflow the child into the spacers calculated space
   if (needsReflow) {
 
-    aDesiredSize.width = 0;
-    aDesiredSize.height = 0;
+    aDesiredSize.Width() = 0;
+    aDesiredSize.Height() = 0;
 
     // create a reflow state to tell our child to flow at the given size.
 
     // Construct a bogus parent reflow state so that there's a usable
     // containing block reflow state.
     nsMargin margin(0,0,0,0);
     GetMargin(margin);
 
@@ -7920,50 +7924,50 @@ nsFrame::BoxReflow(nsBoxLayoutState&    
     uint32_t layoutFlags = aState.LayoutFlags();
     nsContainerFrame::FinishReflowChild(this, aPresContext, &reflowState,
                                         aDesiredSize, aX, aY, layoutFlags | NS_FRAME_NO_MOVE_FRAME);
 
     // Save the ascent.  (bug 103925)
     if (IsCollapsed()) {
       metrics->mAscent = 0;
     } else {
-      if (aDesiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
+      if (aDesiredSize.TopAscent() == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
         if (!nsLayoutUtils::GetFirstLineBaseline(this, &metrics->mAscent))
           metrics->mAscent = GetBaseline();
       } else
-        metrics->mAscent = aDesiredSize.ascent;
+        metrics->mAscent = aDesiredSize.TopAscent();
     }
 
   } else {
-    aDesiredSize.ascent = metrics->mBlockAscent;
+    aDesiredSize.SetTopAscent(metrics->mBlockAscent);
   }
 
 #ifdef DEBUG_REFLOW
-  if (aHeight != NS_INTRINSICSIZE && aDesiredSize.height != aHeight)
+  if (aHeight != NS_INTRINSICSIZE && aDesiredSize.Height() != aHeight)
   {
           nsAdaptorAddIndents();
           printf("*****got taller!*****\n");
          
   }
-  if (aWidth != NS_INTRINSICSIZE && aDesiredSize.width != aWidth)
+  if (aWidth != NS_INTRINSICSIZE && aDesiredSize.Width() != aWidth)
   {
           nsAdaptorAddIndents();
           printf("*****got wider!******\n");
          
   }
 #endif
 
   if (aWidth == NS_INTRINSICSIZE)
-     aWidth = aDesiredSize.width;
+     aWidth = aDesiredSize.Width();
 
   if (aHeight == NS_INTRINSICSIZE)
-     aHeight = aDesiredSize.height;
-
-  metrics->mLastSize.width = aDesiredSize.width;
-  metrics->mLastSize.height = aDesiredSize.height;
+     aHeight = aDesiredSize.Height();
+
+  metrics->mLastSize.width = aDesiredSize.Width();
+  metrics->mLastSize.height = aDesiredSize.Height();
 
 #ifdef DEBUG_REFLOW
   gIndent2--;
 #endif
 
   return NS_OK;
 }
 
@@ -9142,18 +9146,18 @@ void nsFrame::DisplayReflowExit(nsPresCo
   DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode;
   if (treeNode->mDisplay) {
     DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
 
     char width[16];
     char height[16];
     char x[16];
     char y[16];
-    DR_state->PrettyUC(aMetrics.width, width);
-    DR_state->PrettyUC(aMetrics.height, height);
+    DR_state->PrettyUC(aMetrics.Width(), width);
+    DR_state->PrettyUC(aMetrics.Height(), height);
     printf("Reflow d=%s,%s", width, height);
 
     if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
       printf(" status=0x%x", aStatus);
     }
     if (aFrame->HasOverflowAreas()) {
       DR_state->PrettyUC(aMetrics.VisualOverflow().x, x);
       DR_state->PrettyUC(aMetrics.VisualOverflow().y, y);
@@ -9179,18 +9183,18 @@ void nsFrame::DisplayReflowExit(nsPresCo
       DR_state->PrettyUC(storedOverflow.y, y);
       DR_state->PrettyUC(storedOverflow.width, width);
       DR_state->PrettyUC(storedOverflow.height, height);
       printf(" scr-sto=(%s,%s) %s x %s", x, y, width, height);
     }
     printf("\n");
     if (DR_state->mDisplayPixelErrors) {
       int32_t p2t = aPresContext->AppUnitsPerDevPixel();
-      CheckPixelError(aMetrics.width, p2t);
-      CheckPixelError(aMetrics.height, p2t);
+      CheckPixelError(aMetrics.Width(), p2t);
+      CheckPixelError(aMetrics.Height(), p2t);
     }
   }
   DR_state->DeleteTreeNode(*treeNode);
 }
 
 void nsFrame::DisplayLayoutExit(nsIFrame*            aFrame,
                                 void*                aFrameTreeNode)
 {
--- a/layout/generic/nsFrameSetFrame.cpp
+++ b/layout/generic/nsFrameSetFrame.cpp
@@ -618,29 +618,29 @@ void
 nsHTMLFramesetFrame::GetDesiredSize(nsPresContext*           aPresContext,
                                     const nsHTMLReflowState& aReflowState,
                                     nsHTMLReflowMetrics&     aDesiredSize)
 {
   nsHTMLFramesetFrame* framesetParent = do_QueryFrame(GetParent());
   if (nullptr == framesetParent) {
     if (aPresContext->IsPaginated()) {
       // XXX This needs to be changed when framesets paginate properly
-      aDesiredSize.width = aReflowState.AvailableWidth();
-      aDesiredSize.height = aReflowState.AvailableHeight();
+      aDesiredSize.Width() = aReflowState.AvailableWidth();
+      aDesiredSize.Height() = aReflowState.AvailableHeight();
     } else {
       nsRect area = aPresContext->GetVisibleArea();
 
-      aDesiredSize.width = area.width;
-      aDesiredSize.height= area.height;
+      aDesiredSize.Width() = area.width;
+      aDesiredSize.Height() = area.height;
     }
   } else {
     nsSize size;
     framesetParent->GetSizeOfChild(this, size);
-    aDesiredSize.width  = size.width;
-    aDesiredSize.height = size.height;
+    aDesiredSize.Width() = size.width;
+    aDesiredSize.Height() = size.height;
   }
 }
 
 // only valid for non border children
 void nsHTMLFramesetFrame::GetSizeOfChildAt(int32_t  aIndexInParent,
                                            nsSize&  aSize,
                                            nsIntPoint& aCellIndex)
 {
@@ -734,28 +734,28 @@ nsHTMLFramesetFrame::ReflowPlaceChild(ns
                                       nsPoint&                 aOffset,
                                       nsSize&                  aSize,
                                       nsIntPoint*              aCellIndex)
 {
   // reflow the child
   nsHTMLReflowState reflowState(aPresContext, aReflowState, aChild, aSize);
   reflowState.SetComputedWidth(std::max(0, aSize.width - reflowState.ComputedPhysicalBorderPadding().LeftRight()));
   reflowState.SetComputedHeight(std::max(0, aSize.height - reflowState.ComputedPhysicalBorderPadding().TopBottom()));
-  nsHTMLReflowMetrics metrics;
-  metrics.width = aSize.width;
-  metrics.height= aSize.height;
+  nsHTMLReflowMetrics metrics(aReflowState.GetWritingMode());
+  metrics.Width() = aSize.width;
+  metrics.Height() = aSize.height;
   nsReflowStatus status;
 
   ReflowChild(aChild, aPresContext, metrics, reflowState, aOffset.x,
               aOffset.y, 0, status);
   NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "bad status");
 
   // Place and size the child
-  metrics.width = aSize.width;
-  metrics.height = aSize.height;
+  metrics.Width() = aSize.width;
+  metrics.Height() = aSize.height;
   FinishReflowChild(aChild, aPresContext, nullptr, metrics, aOffset.x, aOffset.y, 0);
 }
 
 static
 nsFrameborder GetFrameBorderHelper(nsGenericHTMLElement* aContent)
 {
   if (nullptr != aContent) {
     const nsAttrValue* attr = aContent->GetParsedAttr(nsGkAtoms::frameborder);
@@ -851,20 +851,20 @@ nsHTMLFramesetFrame::Reflow(nsPresContex
   nsStyleSet *styleSet = shell->StyleSet();
 
   mParent->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
 
   //printf("FramesetFrame2::Reflow %X (%d,%d) \n", this, aReflowState.AvailableWidth(), aReflowState.AvailableHeight());
   // Always get the size so that the caller knows how big we are
   GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
 
-  nscoord width  = (aDesiredSize.width <= aReflowState.AvailableWidth())
-    ? aDesiredSize.width : aReflowState.AvailableWidth();
-  nscoord height = (aDesiredSize.height <= aReflowState.AvailableHeight())
-    ? aDesiredSize.height : aReflowState.AvailableHeight();
+  nscoord width  = (aDesiredSize.Width() <= aReflowState.AvailableWidth())
+    ? aDesiredSize.Width() : aReflowState.AvailableWidth();
+  nscoord height = (aDesiredSize.Height() <= aReflowState.AvailableHeight())
+    ? aDesiredSize.Height() : aReflowState.AvailableHeight();
 
   bool firstTime = (GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
   if (firstTime) {
     Preferences::RegisterCallback(FrameResizePrefCallback,
                                   kFrameResizePref, this);
     mForceFrameResizability = Preferences::GetBool(kFrameResizePref);
   }
 
@@ -965,17 +965,17 @@ nsHTMLFramesetFrame::Reflow(nsPresContex
         // set the neighbors for determining drag boundaries
         borderFrame->mPrevNeighbor = lastRow;
         borderFrame->mNextNeighbor = cellIndex.y;
       } else {
         borderFrame = (nsHTMLFramesetBorderFrame*)mFrames.FrameAt(borderChildX);
         borderFrame->mWidth = borderWidth;
         borderChildX++;
       }
-      nsSize borderSize(aDesiredSize.width, borderWidth);
+      nsSize borderSize(aDesiredSize.Width(), borderWidth);
       ReflowPlaceChild(borderFrame, aPresContext, aReflowState, offset, borderSize);
       borderFrame = nullptr;
       offset.y += borderWidth;
     } else {
       if (cellIndex.x > 0) {  // moved to next col in same row
         if (0 == cellIndex.y) { // in 1st row
           if (firstTime) { // create vertical border
 
@@ -995,17 +995,17 @@ nsHTMLFramesetFrame::Reflow(nsPresContex
             // set the neighbors for determining drag boundaries
             borderFrame->mPrevNeighbor = lastCol;
             borderFrame->mNextNeighbor = cellIndex.x;
           } else {
             borderFrame = (nsHTMLFramesetBorderFrame*)mFrames.FrameAt(borderChildX);
             borderFrame->mWidth = borderWidth;
             borderChildX++;
           }
-          nsSize borderSize(borderWidth, aDesiredSize.height);
+          nsSize borderSize(borderWidth, aDesiredSize.Height());
           ReflowPlaceChild(borderFrame, aPresContext, aReflowState, offset, borderSize);
           borderFrame = nullptr;
         }
         offset.x += borderWidth;
       }
     }
 
     ReflowPlaceChild(child, aPresContext, aReflowState, offset, size, &cellIndex);
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -324,19 +324,19 @@ nsHTMLScrollFrame::TryLayout(ScrollReflo
   }
   nscoord hScrollbarDesiredHeight = aAssumeHScroll ? hScrollbarPrefSize.height : 0;
   nscoord hScrollbarMinWidth = aAssumeHScroll ? hScrollbarMinSize.width : 0;
 
   // First, compute our inside-border size and scrollport size
   // XXXldb Can we depend more on ComputeSize here?
   nsSize desiredInsideBorderSize;
   desiredInsideBorderSize.width = vScrollbarDesiredWidth +
-    std::max(aKidMetrics->width, hScrollbarMinWidth);
+    std::max(aKidMetrics->Width(), hScrollbarMinWidth);
   desiredInsideBorderSize.height = hScrollbarDesiredHeight +
-    std::max(aKidMetrics->height, vScrollbarMinHeight);
+    std::max(aKidMetrics->Height(), vScrollbarMinHeight);
   aState->mInsideBorderSize =
     ComputeInsideBorderSize(aState, desiredInsideBorderSize);
   nsSize scrollPortSize = nsSize(std::max(0, aState->mInsideBorderSize.width - vScrollbarDesiredWidth),
                                  std::max(0, aState->mInsideBorderSize.height - hScrollbarDesiredHeight));
 
   if (!aForce) {
     nsRect scrolledRect =
       mHelper.GetScrolledRectInternal(aState->mContentsOverflowAreas.ScrollableOverflow(),
@@ -547,17 +547,17 @@ nsHTMLScrollFrame::InInitialReflow() con
   // assumption, because our initial reflow is no longer synchronous).
   return !mHelper.mIsRoot && (GetStateBits() & NS_FRAME_FIRST_REFLOW);
 }
 
 nsresult
 nsHTMLScrollFrame::ReflowContents(ScrollReflowState* aState,
                                   const nsHTMLReflowMetrics& aDesiredSize)
 {
-  nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.mFlags);
+  nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.GetWritingMode(), aDesiredSize.mFlags);
   nsresult rv = ReflowScrolledFrame(aState, GuessHScrollbarNeeded(*aState),
       GuessVScrollbarNeeded(*aState), &kidDesiredSize, true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // There's an important special case ... if the child appears to fit
   // in the inside-border rect (but overflows the scrollport), we
   // should try laying it out without a vertical scrollbar. It will
   // usually fit because making the available-width wider will not
@@ -576,17 +576,17 @@ nsHTMLScrollFrame::ReflowContents(Scroll
 
   // XXX Is this check really sufficient to catch all the incremental cases
   // where the ideal case doesn't have a scrollbar?
   if ((aState->mReflowedContentsWithHScrollbar || aState->mReflowedContentsWithVScrollbar) &&
       aState->mStyles.mVertical != NS_STYLE_OVERFLOW_SCROLL &&
       aState->mStyles.mHorizontal != NS_STYLE_OVERFLOW_SCROLL) {
     nsSize insideBorderSize =
       ComputeInsideBorderSize(aState,
-                              nsSize(kidDesiredSize.width, kidDesiredSize.height));
+                              nsSize(kidDesiredSize.Width(), kidDesiredSize.Height()));
     nsRect scrolledRect =
       mHelper.GetScrolledRectInternal(kidDesiredSize.ScrollableOverflow(),
                                      insideBorderSize);
     if (nsRect(nsPoint(0, 0), insideBorderSize).Contains(scrolledRect)) {
       // Let's pretend we had no scrollbars coming in here
       rv = ReflowScrolledFrame(aState, false, false,
                                &kidDesiredSize, false);
       NS_ENSURE_SUCCESS(rv, rv);
@@ -830,19 +830,19 @@ nsHTMLScrollFrame::Reflow(nsPresContext*
                state.mInsideBorderSize);
       mHelper.LayoutScrollbars(state.mBoxState, insideBorderArea,
                               oldScrollAreaBounds);
     } else {
       mHelper.mSkippedScrollbarLayout = true;
     }
   }
 
-  aDesiredSize.width = state.mInsideBorderSize.width +
+  aDesiredSize.Width() = state.mInsideBorderSize.width +
     state.mComputedBorder.LeftRight();
-  aDesiredSize.height = state.mInsideBorderSize.height +
+  aDesiredSize.Height() = state.mInsideBorderSize.height +
     state.mComputedBorder.TopBottom();
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
   if (mHelper.IsIgnoringViewportClipping()) {
     aDesiredSize.mOverflowAreas.UnionWith(
       state.mContentsOverflowAreas + mHelper.mScrolledFrame->GetPosition());
   }
 
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -181,50 +181,50 @@ nsHTMLCanvasFrame::Reflow(nsPresContext*
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                   ("enter nsHTMLCanvasFrame::Reflow: availSize=%d,%d",
                   aReflowState.AvailableWidth(), aReflowState.AvailableHeight()));
 
   NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow");
 
   aStatus = NS_FRAME_COMPLETE;
 
-  aMetrics.width = aReflowState.ComputedWidth();
-  aMetrics.height = aReflowState.ComputedHeight();
+  aMetrics.Width() = aReflowState.ComputedWidth();
+  aMetrics.Height() = aReflowState.ComputedHeight();
 
   // stash this away so we can compute our inner area later
   mBorderPadding   = aReflowState.ComputedPhysicalBorderPadding();
 
-  aMetrics.width += mBorderPadding.left + mBorderPadding.right;
-  aMetrics.height += mBorderPadding.top + mBorderPadding.bottom;
+  aMetrics.Width() += mBorderPadding.left + mBorderPadding.right;
+  aMetrics.Height() += mBorderPadding.top + mBorderPadding.bottom;
 
   if (GetPrevInFlow()) {
-    nscoord y = GetContinuationOffset(&aMetrics.width);
-    aMetrics.height -= y + mBorderPadding.top;
-    aMetrics.height = std::max(0, aMetrics.height);
+    nscoord y = GetContinuationOffset(&aMetrics.Width());
+    aMetrics.Height() -= y + mBorderPadding.top;
+    aMetrics.Height() = std::max(0, aMetrics.Height());
   }
 
   aMetrics.SetOverflowAreasToDesiredBounds();
   FinishAndStoreOverflow(&aMetrics);
 
   // Reflow the single anon block child.
   nsReflowStatus childStatus;
   nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE);
   nsIFrame* childFrame = mFrames.FirstChild();
   NS_ASSERTION(!childFrame->GetNextSibling(), "HTML canvas should have 1 kid");
-  nsHTMLReflowMetrics childDesiredSize(aMetrics.mFlags);
+  nsHTMLReflowMetrics childDesiredSize(aReflowState.GetWritingMode(), aMetrics.mFlags);
   nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame,
                                      availSize);
   ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState,
               0, 0, 0, childStatus, nullptr);
   FinishReflowChild(childFrame, aPresContext, &childReflowState,
                     childDesiredSize, 0, 0, 0);
 
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                   ("exit nsHTMLCanvasFrame::Reflow: size=%d,%d",
-                  aMetrics.width, aMetrics.height));
+                  aMetrics.Width(), aMetrics.Height()));
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
 
   return NS_OK;
 }
 
 // FIXME taken from nsImageFrame, but then had splittable frame stuff
 // removed.  That needs to be fixed.
 nsRect 
--- a/layout/generic/nsHTMLReflowMetrics.cpp
+++ b/layout/generic/nsHTMLReflowMetrics.cpp
@@ -34,23 +34,23 @@ nsOverflowAreas::SetAllTo(const nsRect& 
     mRects[otype] = aRect;
   }
 }
 
 void
 nsHTMLReflowMetrics::SetOverflowAreasToDesiredBounds()
 {
   NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
-    mOverflowAreas.Overflow(otype).SetRect(0, 0, width, height);
+    mOverflowAreas.Overflow(otype).SetRect(0, 0, Width(), Height());
   }
 }
 
 void
 nsHTMLReflowMetrics::UnionOverflowAreasWithDesiredBounds()
 {
   // FIXME: We should probably change scrollable overflow to use
   // UnionRectIncludeEmpty (but leave visual overflow using UnionRect).
-  nsRect rect(0, 0, width, height);
+  nsRect rect(0, 0, Width(), Height());
   NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
     nsRect& o = mOverflowAreas.Overflow(otype);
     o.UnionRect(o, rect);
   }
 }
--- a/layout/generic/nsHTMLReflowMetrics.h
+++ b/layout/generic/nsHTMLReflowMetrics.h
@@ -5,16 +5,17 @@
 
 /* struct containing the output from nsIFrame::Reflow */
 
 #ifndef nsHTMLReflowMetrics_h___
 #define nsHTMLReflowMetrics_h___
 
 #include "nsRect.h"
 #include "nsBoundingMetrics.h"
+#include "WritingModes.h"
 
 //----------------------------------------------------------------------
 
 // Option flags
 #define NS_REFLOW_CALC_BOUNDING_METRICS  0x0001
 
 /**
  * When we store overflow areas as an array of scrollable and visual
@@ -188,21 +189,40 @@ struct nsCollapsingMargin {
 };
 
 /**
  * Reflow metrics used to return the frame's desired size and alignment
  * information.
  *
  * @see #Reflow()
  */
-struct nsHTMLReflowMetrics {
-  nscoord width, height;    // [OUT] desired width and height (border-box)
-  nscoord ascent;           // [OUT] baseline (from top), or ASK_FOR_BASELINE
+class nsHTMLReflowMetrics {
+public:
+  // XXXldb Should |aFlags| generally be passed from parent to child?
+  // Some places do it, and some don't.  |aFlags| should perhaps go away
+  // entirely.
+  // XXX width/height/ascent are OUT parameters and so they shouldn't
+  // have to be initialized, but there are some bad frame classes that
+  // aren't properly setting them when returning from Reflow()...
+  nsHTMLReflowMetrics(mozilla::WritingMode aWritingMode, uint32_t aFlags = 0)
+    : mWidth(0)
+    , mHeight(0)
+    , mAscent(ASK_FOR_BASELINE)
+    , mFlags(aFlags)
+    , mWritingMode(aWritingMode)
+  {}
 
-  uint32_t mFlags;
+  const nscoord& Width() const { return mWidth; }
+  const nscoord& Height() const { return mHeight; }
+  const nscoord& TopAscent() const { return mAscent; }
+
+  nscoord& Width() { return mWidth; }
+  nscoord& Height() { return mHeight; }
+
+  void SetTopAscent(nscoord aAscent) { mAscent = aAscent; }
 
   enum { ASK_FOR_BASELINE = nscoord_MAX };
 
   // Metrics that _exactly_ enclose the text to allow precise MathML placements.
   // If the NS_REFLOW_CALC_BOUNDING_METRICS flag is set, then the caller is 
   // requesting that you also compute additional details about your inner
   // bounding box and italic correction. For example, the bounding box of
   // msup is the smallest rectangle that _exactly_ encloses both the text
@@ -233,20 +253,22 @@ struct nsHTMLReflowMetrics {
     { return mOverflowAreas.ScrollableOverflow(); }
 
   // Set all of mOverflowAreas to (0, 0, width, height).
   void SetOverflowAreasToDesiredBounds();
 
   // Union all of mOverflowAreas with (0, 0, width, height).
   void UnionOverflowAreasWithDesiredBounds();
 
-  // XXXldb Should |aFlags| generally be passed from parent to child?
-  // Some places do it, and some don't.  |aFlags| should perhaps go away
-  // entirely.
-  // XXX width/height/ascent are OUT parameters and so they shouldn't
-  // have to be initialized, but there are some bad frame classes that
-  // aren't properly setting them when returning from Reflow()...
-  nsHTMLReflowMetrics(uint32_t aFlags = 0)
-    : width(0), height(0), ascent(ASK_FOR_BASELINE), mFlags(aFlags)
-  {}
+  mozilla::WritingMode GetWritingMode() const { return mWritingMode; }
+
+private:
+  nscoord mWidth, mHeight; // [OUT] desired width and height (border-box)
+  nscoord mAscent;         // [OUT] baseline (from top), or ASK_FOR_BASELINE
+
+public:
+  uint32_t mFlags;
+
+private:
+  mozilla::WritingMode mWritingMode;
 };
 
 #endif /* nsHTMLReflowMetrics_h___ */
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -2621,17 +2621,17 @@ nsHTMLReflowState::ComputeMinMaxValues(n
   }
 }
 
 void
 nsHTMLReflowState::SetTruncated(const nsHTMLReflowMetrics& aMetrics,
                                 nsReflowStatus* aStatus) const
 {
   if (AvailableHeight() != NS_UNCONSTRAINEDSIZE &&
-      AvailableHeight() < aMetrics.height &&
+      AvailableHeight() < aMetrics.Height() &&
       !mFlags.mIsTopOfPage) {
     *aStatus |= NS_FRAME_TRUNCATED;
   } else {
     *aStatus &= ~NS_FRAME_TRUNCATED;
   }
 }
 
 bool
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -2434,17 +2434,17 @@ public:
    * be retrieved later without reflowing the frame. Returns true if either of
    * the overflow areas changed.
    */
   bool FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
                               nsSize aNewSize, nsSize* aOldSize = nullptr);
 
   bool FinishAndStoreOverflow(nsHTMLReflowMetrics* aMetrics) {
     return FinishAndStoreOverflow(aMetrics->mOverflowAreas,
-                                  nsSize(aMetrics->width, aMetrics->height));
+                                  nsSize(aMetrics->Width(), aMetrics->Height()));
   }
 
   /**
    * Returns whether the frame has an overflow rect that is different from
    * its border-box.
    */
   bool HasOverflowAreas() const {
     return mOverflow.mType != NS_FRAME_OVERFLOW_NONE;
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -824,28 +824,28 @@ nsImageFrame::Reflow(nsPresContext*     
   // middle of the initial reflow); remove IMAGE_GOTINITIALREFLOW.
   if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
     mState |= IMAGE_GOTINITIALREFLOW;
   }
 
   mComputedSize = 
     nsSize(aReflowState.ComputedWidth(), aReflowState.ComputedHeight());
 
-  aMetrics.width = mComputedSize.width;
-  aMetrics.height = mComputedSize.height;
+  aMetrics.Width() = mComputedSize.width;
+  aMetrics.Height() = mComputedSize.height;
 
   // add borders and padding
-  aMetrics.width  += aReflowState.ComputedPhysicalBorderPadding().LeftRight();
-  aMetrics.height += aReflowState.ComputedPhysicalBorderPadding().TopBottom();
+  aMetrics.Width()  += aReflowState.ComputedPhysicalBorderPadding().LeftRight();
+  aMetrics.Height() += aReflowState.ComputedPhysicalBorderPadding().TopBottom();
   
   if (GetPrevInFlow()) {
-    aMetrics.width = GetPrevInFlow()->GetSize().width;
+    aMetrics.Width() = GetPrevInFlow()->GetSize().width;
     nscoord y = GetContinuationOffset();
-    aMetrics.height -= y + aReflowState.ComputedPhysicalBorderPadding().top;
-    aMetrics.height = std::max(0, aMetrics.height);
+    aMetrics.Height() -= y + aReflowState.ComputedPhysicalBorderPadding().top;
+    aMetrics.Height() = std::max(0, aMetrics.Height());
   }
 
 
   // we have to split images if we are:
   //  in Paginated mode, we need to have a constrained height, and have a height larger than our available height
   uint32_t loadStatus = imgIRequest::STATUS_NONE;
   nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
   NS_ASSERTION(imageLoader, "No content node??");
@@ -855,20 +855,20 @@ nsImageFrame::Reflow(nsPresContext*     
                             getter_AddRefs(currentRequest));
     if (currentRequest) {
       currentRequest->GetImageStatus(&loadStatus);
     }
   }
   if (aPresContext->IsPaginated() &&
       ((loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE) || (mState & IMAGE_SIZECONSTRAINED)) &&
       NS_UNCONSTRAINEDSIZE != aReflowState.AvailableHeight() && 
-      aMetrics.height > aReflowState.AvailableHeight()) { 
+      aMetrics.Height() > aReflowState.AvailableHeight()) { 
     // our desired height was greater than 0, so to avoid infinite
     // splitting, use 1 pixel as the min
-    aMetrics.height = std::max(nsPresContext::CSSPixelsToAppUnits(1), aReflowState.AvailableHeight());
+    aMetrics.Height() = std::max(nsPresContext::CSSPixelsToAppUnits(1), aReflowState.AvailableHeight());
     aStatus = NS_FRAME_NOT_COMPLETE;
   }
 
   aMetrics.SetOverflowAreasToDesiredBounds();
   nsEventStates contentState = mContent->AsElement()->State();
   bool imageOK = IMAGE_OK(contentState, true);
 
   // Determine if the size is available
@@ -893,17 +893,17 @@ nsImageFrame::Reflow(nsPresContext*     
   if ((GetStateBits() & NS_FRAME_FIRST_REFLOW) && !mReflowCallbackPosted) {
     nsIPresShell* shell = PresContext()->PresShell();
     mReflowCallbackPosted = true;
     shell->PostReflowCallback(this);
   }
 
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                   ("exit nsImageFrame::Reflow: size=%d,%d",
-                  aMetrics.width, aMetrics.height));
+                  aMetrics.Width(), aMetrics.Height()));
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
   return NS_OK;
 }
 
 bool
 nsImageFrame::ReflowFinished()
 {
   mReflowCallbackPosted = false;
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -643,39 +643,39 @@ nsInlineFrame::ReflowFrames(nsPresContex
 
   // If after reflowing our children they take up no area then make
   // sure that we don't either.
   //
   // Note: CSS demands that empty inline elements still affect the
   // line-height calculations. However, continuations of an inline
   // that are empty we force to empty so that things like collapsed
   // whitespace in an inline element don't affect the line-height.
-  aMetrics.width = lineLayout->EndSpan(this);
+  aMetrics.Width() = lineLayout->EndSpan(this);
 
   // Compute final width.
 
   // Make sure to not include our start border and padding if we have a prev
   // continuation or if we're in a part of an {ib} split other than the first
   // one.
   if (!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) {
-    aMetrics.width += ltr ? aReflowState.ComputedPhysicalBorderPadding().left
+    aMetrics.Width() += ltr ? aReflowState.ComputedPhysicalBorderPadding().left
                           : aReflowState.ComputedPhysicalBorderPadding().right;
   }
 
   /*
    * We want to only apply the end border and padding if we're the last
    * continuation and either not in an {ib} split or the last part of it.  To
    * be the last continuation we have to be complete (so that we won't get a
    * next-in-flow) and have no non-fluid continuations on our continuation
    * chain.
    */
   if (NS_FRAME_IS_COMPLETE(aStatus) &&
       !LastInFlow()->GetNextContinuation() &&
       !FrameIsNonLastInIBSplit()) {
-    aMetrics.width += ltr ? aReflowState.ComputedPhysicalBorderPadding().right
+    aMetrics.Width() += ltr ? aReflowState.ComputedPhysicalBorderPadding().right
                           : aReflowState.ComputedPhysicalBorderPadding().left;
   }
 
   nsRefPtr<nsFontMetrics> fm;
   float inflation = nsLayoutUtils::FontSizeInflationFor(this);
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm), inflation);
   aReflowState.rendContext->SetFont(fm);
 
@@ -685,34 +685,34 @@ nsInlineFrame::ReflowFrames(nsPresContex
     // Do things the standard css2 way -- though it's hard to find it
     // in the css2 spec! It's actually found in the css1 spec section
     // 4.4 (you will have to read between the lines to really see
     // it).
     //
     // The height of our box is the sum of our font size plus the top
     // and bottom border and padding. The height of children do not
     // affect our height.
-    aMetrics.ascent = fm->MaxAscent();
-    aMetrics.height = fm->MaxHeight();
+    aMetrics.SetTopAscent(fm->MaxAscent());
+    aMetrics.Height() = fm->MaxHeight();
   } else {
     NS_WARNING("Cannot get font metrics - defaulting sizes to 0");
-    aMetrics.ascent = aMetrics.height = 0;
+    aMetrics.SetTopAscent(aMetrics.Height() = 0);
   }
-  aMetrics.ascent += aReflowState.ComputedPhysicalBorderPadding().top;
-  aMetrics.height += aReflowState.ComputedPhysicalBorderPadding().top +
+  aMetrics.SetTopAscent(aMetrics.TopAscent() + aReflowState.ComputedPhysicalBorderPadding().top);
+  aMetrics.Height() += aReflowState.ComputedPhysicalBorderPadding().top +
     aReflowState.ComputedPhysicalBorderPadding().bottom;
 
   // For now our overflow area is zero. The real value will be
   // computed in |nsLineLayout::RelativePositionFrames|.
   aMetrics.mOverflowAreas.Clear();
 
 #ifdef NOISY_FINAL_SIZE
   ListTag(stdout);
   printf(": metrics=%d,%d ascent=%d\n",
-         aMetrics.width, aMetrics.height, aMetrics.ascent);
+         aMetrics.Width(), aMetrics.Height(), aMetrics.TopAscent());
 #endif
 
   return rv;
 }
 
 nsresult
 nsInlineFrame::ReflowInlineFrame(nsPresContext* aPresContext,
                                  const nsHTMLReflowState& aReflowState,
--- a/layout/generic/nsLeafFrame.cpp
+++ b/layout/generic/nsLeafFrame.cpp
@@ -69,25 +69,25 @@ nsLeafFrame::DoReflow(nsPresContext* aPr
 {
   NS_ASSERTION(aReflowState.ComputedWidth() != NS_UNCONSTRAINEDSIZE,
                "Shouldn't have unconstrained stuff here "
                "Thanks to the rules of reflow");
   NS_ASSERTION(NS_INTRINSICSIZE != aReflowState.ComputedHeight(),
                "Shouldn't have unconstrained stuff here "
                "thanks to ComputeAutoSize");  
 
-  aMetrics.width = aReflowState.ComputedWidth();
-  aMetrics.height = aReflowState.ComputedHeight();
+  aMetrics.Width() = aReflowState.ComputedWidth();
+  aMetrics.Height() = aReflowState.ComputedHeight();
   
   AddBordersAndPadding(aReflowState, aMetrics);
   aStatus = NS_FRAME_COMPLETE;
 
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                  ("exit nsLeafFrame::DoReflow: size=%d,%d",
-                  aMetrics.width, aMetrics.height));
+                  aMetrics.Width(), aMetrics.Height()));
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
 
   aMetrics.SetOverflowAreasToDesiredBounds();
 
   return NS_OK;
 }
 
 nscoord
@@ -98,21 +98,21 @@ nsLeafFrame::GetIntrinsicHeight()
 }
 
 // XXX how should border&padding effect baseline alignment?
 // => descent = borderPadding.bottom for example
 void
 nsLeafFrame::AddBordersAndPadding(const nsHTMLReflowState& aReflowState,
                                   nsHTMLReflowMetrics& aMetrics)
 {
-  aMetrics.width += aReflowState.ComputedPhysicalBorderPadding().LeftRight();
-  aMetrics.height += aReflowState.ComputedPhysicalBorderPadding().TopBottom();
+  aMetrics.Width() += aReflowState.ComputedPhysicalBorderPadding().LeftRight();
+  aMetrics.Height() += aReflowState.ComputedPhysicalBorderPadding().TopBottom();
 }
 
 void
 nsLeafFrame::SizeToAvailSize(const nsHTMLReflowState& aReflowState,
                              nsHTMLReflowMetrics& aDesiredSize)
 {
-  aDesiredSize.width  = aReflowState.AvailableWidth(); // FRAME
-  aDesiredSize.height = aReflowState.AvailableHeight();
+  aDesiredSize.Width() = aReflowState.AvailableWidth(); // FRAME
+  aDesiredSize.Height() = aReflowState.AvailableHeight();
   aDesiredSize.SetOverflowAreasToDesiredBounds();
   FinishAndStoreOverflow(&aDesiredSize);  
 }
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -807,20 +807,20 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
   }
 
   // Let frame know that are reflowing it. Note that we don't bother
   // positioning the frame yet, because we're probably going to end up
   // moving it when we do the vertical alignment
   aFrame->WillReflow(mPresContext);
 
   // Adjust spacemanager coordinate system for the frame.
-  nsHTMLReflowMetrics metrics;
+  nsHTMLReflowMetrics metrics(mBlockReflowState->GetWritingMode());
 #ifdef DEBUG
-  metrics.width = nscoord(0xdeadbeef);
-  metrics.height = nscoord(0xdeadbeef);
+  metrics.Width() = nscoord(0xdeadbeef);
+  metrics.Height() = nscoord(0xdeadbeef);
 #endif
   nscoord tx = pfd->mBounds.x;
   nscoord ty = pfd->mBounds.y;
   mFloatManager->Translate(tx, ty);
 
   int32_t savedOptionalBreakOffset;
   gfxBreakPriority savedOptionalBreakPriority;
   nsIContent* savedOptionalBreakContent =
@@ -906,51 +906,51 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
       } else {
         isEmpty = pfd->mFrame->IsEmpty();
       }
     }
   }
 
   mFloatManager->Translate(-tx, -ty);
 
-  NS_ASSERTION(metrics.width>=0, "bad width");
-  NS_ASSERTION(metrics.height>=0,"bad height");
-  if (metrics.width<0) metrics.width=0;
-  if (metrics.height<0) metrics.height=0;
+  NS_ASSERTION(metrics.Width() >= 0, "bad width");
+  NS_ASSERTION(metrics.Height() >= 0,"bad height");
+  if (metrics.Width() < 0) metrics.Width() = 0;
+  if (metrics.Height() < 0) metrics.Height() = 0;
 
 #ifdef DEBUG
   // Note: break-before means ignore the reflow metrics since the
   // frame will be reflowed another time.
   if (!NS_INLINE_IS_BREAK_BEFORE(aReflowStatus)) {
-    if (CRAZY_WIDTH(metrics.width) || CRAZY_HEIGHT(metrics.height)) {
+    if (CRAZY_WIDTH(metrics.Width()) || CRAZY_HEIGHT(metrics.Height())) {
       printf("nsLineLayout: ");
       nsFrame::ListTag(stdout, aFrame);
-      printf(" metrics=%d,%d!\n", metrics.width, metrics.height);
+      printf(" metrics=%d,%d!\n", metrics.Width(), metrics.Height());
     }
-    if ((metrics.width == nscoord(0xdeadbeef)) ||
-        (metrics.height == nscoord(0xdeadbeef))) {
+    if ((metrics.Width() == nscoord(0xdeadbeef)) ||
+        (metrics.Height() == nscoord(0xdeadbeef))) {
       printf("nsLineLayout: ");
       nsFrame::ListTag(stdout, aFrame);
-      printf(" didn't set w/h %d,%d!\n", metrics.width, metrics.height);
+      printf(" didn't set w/h %d,%d!\n", metrics.Width(), metrics.Height());
     }
   }
 #endif
 
   // Unlike with non-inline reflow, the overflow area here does *not*
   // include the accumulation of the frame's bounds and its inline
   // descendants' bounds. Nor does it include the outline area; it's
   // just the union of the bounds of any absolute children. That is
   // added in later by nsLineLayout::ReflowInlineFrames.
   pfd->mOverflowAreas = metrics.mOverflowAreas;
 
-  pfd->mBounds.width = metrics.width;
-  pfd->mBounds.height = metrics.height;
+  pfd->mBounds.width = metrics.Width();
+  pfd->mBounds.height = metrics.Height();
 
   // Size the frame, but |RelativePositionFrames| will size the view.
-  aFrame->SetSize(nsSize(metrics.width, metrics.height));
+  aFrame->SetSize(nsSize(metrics.Width(), metrics.Height()));
 
   // Tell the frame that we're done reflowing it
   aFrame->DidReflow(mPresContext,
                     isText ? nullptr : reflowStateHolder.addr(),
                     nsDidReflowStatus::FINISHED);
 
   if (aMetrics) {
     *aMetrics = metrics;
@@ -1293,20 +1293,20 @@ nsLineLayout::PlaceFrame(PerFrameData* p
   bool emptyFrame = false;
   if ((0 == pfd->mBounds.width) && (0 == pfd->mBounds.height)) {
     pfd->mBounds.x = psd->mX;
     pfd->mBounds.y = mTopEdge;
     emptyFrame = true;
   }
 
   // Record ascent and update max-ascent and max-descent values
-  if (aMetrics.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE)
+  if (aMetrics.TopAscent() == nsHTMLReflowMetrics::ASK_FOR_BASELINE)
     pfd->mAscent = pfd->mFrame->GetBaseline();
   else
-    pfd->mAscent = aMetrics.ascent;
+    pfd->mAscent = aMetrics.TopAscent();
 
   bool ltr = (NS_STYLE_DIRECTION_LTR == pfd->mFrame->StyleVisibility()->mDirection);
   // Advance to next X coordinate
   psd->mX = pfd->mBounds.XMost() + (ltr ? pfd->mMargin.right : pfd->mMargin.left);
 
   // Count the number of non-empty frames on the line...
   if (!emptyFrame) {
     mTotalPlacedFrames++;
@@ -1330,20 +1330,20 @@ nsLineLayout::AddBulletFrame(nsIFrame* a
 
   PerFrameData* pfd = NewPerFrameData();
   mRootSpan->AppendFrame(pfd);
   pfd->mFrame = aFrame;
   pfd->mMargin.SizeTo(0, 0, 0, 0);
   pfd->mBorderPadding.SizeTo(0, 0, 0, 0);
   pfd->mFlags = 0;  // all flags default to false
   pfd->SetFlag(PFD_ISBULLET, true);
-  if (aMetrics.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE)
+  if (aMetrics.TopAscent() == nsHTMLReflowMetrics::ASK_FOR_BASELINE)
     pfd->mAscent = aFrame->GetBaseline();
   else
-    pfd->mAscent = aMetrics.ascent;
+    pfd->mAscent = aMetrics.TopAscent();
 
   // Note: y value will be updated during vertical alignment
   pfd->mBounds = aFrame->GetRect();
   pfd->mOverflowAreas = aMetrics.mOverflowAreas;
 }
 
 #ifdef DEBUG
 void
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -437,65 +437,65 @@ nsObjectFrame::GetPrefWidth(nsRenderingC
 }
 
 void
 nsObjectFrame::GetDesiredSize(nsPresContext* aPresContext,
                               const nsHTMLReflowState& aReflowState,
                               nsHTMLReflowMetrics& aMetrics)
 {
   // By default, we have no area
-  aMetrics.width = 0;
-  aMetrics.height = 0;
+  aMetrics.Width() = 0;
+  aMetrics.Height() = 0;
 
   if (IsHidden(false)) {
     return;
   }
   
-  aMetrics.width = aReflowState.ComputedWidth();
-  aMetrics.height = aReflowState.ComputedHeight();
+  aMetrics.Width() = aReflowState.ComputedWidth();
+  aMetrics.Height() = aReflowState.ComputedHeight();
 
   // for EMBED and APPLET, default to 240x200 for compatibility
   nsIAtom *atom = mContent->Tag();
   if (atom == nsGkAtoms::applet || atom == nsGkAtoms::embed) {
-    if (aMetrics.width == NS_UNCONSTRAINEDSIZE) {
-      aMetrics.width = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH),
+    if (aMetrics.Width() == NS_UNCONSTRAINEDSIZE) {
+      aMetrics.Width() = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH),
                                aReflowState.ComputedMinWidth(),
                                aReflowState.ComputedMaxWidth());
     }
-    if (aMetrics.height == NS_UNCONSTRAINEDSIZE) {
-      aMetrics.height = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_HEIGHT),
+    if (aMetrics.Height() == NS_UNCONSTRAINEDSIZE) {
+      aMetrics.Height() = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_HEIGHT),
                                 aReflowState.ComputedMinHeight(),
                                 aReflowState.ComputedMaxHeight());
     }
 
 #if defined(MOZ_WIDGET_GTK)
     // We need to make sure that the size of the object frame does not
     // exceed the maximum size of X coordinates.  See bug #225357 for
     // more information.  In theory Gtk2 can handle large coordinates,
     // but underlying plugins can't.
-    aMetrics.height = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.height);
-    aMetrics.width = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.width);
+    aMetrics.Height() = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.Height());
+    aMetrics.Width() = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.Width());
 #endif
   }
 
   // At this point, the width has an unconstrained value only if we have
   // nothing to go on (no width set, no information from the plugin, nothing).
   // Make up a number.
-  if (aMetrics.width == NS_UNCONSTRAINEDSIZE) {
-    aMetrics.width =
+  if (aMetrics.Width() == NS_UNCONSTRAINEDSIZE) {
+    aMetrics.Width() =
       (aReflowState.ComputedMinWidth() != NS_UNCONSTRAINEDSIZE) ?
         aReflowState.ComputedMinWidth() : 0;
   }
 
   // At this point, the height has an unconstrained value only in two cases:
   // a) We are in standards mode with percent heights and parent is auto-height
   // b) We have no height information at all.
   // In either case, we have to make up a number.
-  if (aMetrics.height == NS_UNCONSTRAINEDSIZE) {
-    aMetrics.height =
+  if (aMetrics.Height() == NS_UNCONSTRAINEDSIZE) {
+    aMetrics.Height() =
       (aReflowState.ComputedMinHeight() != NS_UNCONSTRAINEDSIZE) ?
         aReflowState.ComputedMinHeight() : 0;
   }
 
   // XXXbz don't add in the border and padding, because we screw up our
   // plugin's size and positioning if we do...  Eventually we _do_ want to
   // paint borders, though!  At that point, we will need to adjust the desired
   // size either here or in Reflow....  Further, we will need to fix Paint() to
@@ -525,17 +525,17 @@ nsObjectFrame::Reflow(nsPresContext*    
   }
 
   // if we are printing or print previewing, bail for now
   if (aPresContext->Medium() == nsGkAtoms::print) {
     aStatus = NS_FRAME_COMPLETE;
     return NS_OK;
   }
 
-  nsRect r(0, 0, aMetrics.width, aMetrics.height);
+  nsRect r(0, 0, aMetrics.Width(), aMetrics.Height());
   r.Deflate(aReflowState.ComputedPhysicalBorderPadding());
 
   if (mInnerView) {
     nsViewManager* vm = mInnerView->GetViewManager();
     vm->MoveViewTo(mInnerView, r.x, r.y);
     vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), r.Size()), true);
   }
 
--- a/layout/generic/nsPageContentFrame.cpp
+++ b/layout/generic/nsPageContentFrame.cpp
@@ -67,17 +67,17 @@ nsPageContentFrame::Reflow(nsPresContext
     // This is for shrink-to-fit, and therefore we want to use the
     // scrollable overflow, since the purpose of shrink to fit is to
     // make the content that ought to be reachable (represented by the
     // scrollable overflow) fit in the page.
     if (frame->HasOverflowAreas()) {
       // The background covers the content area and padding area, so check
       // for children sticking outside the child frame's padding edge
       nscoord xmost = aDesiredSize.ScrollableOverflow().XMost();
-      if (xmost > aDesiredSize.width) {
+      if (xmost > aDesiredSize.Width()) {
         mPD->mPageContentXMost =
           xmost +
           kidReflowState.mStyleBorder->GetComputedBorderWidth(NS_SIDE_RIGHT) +
           padding.right;
       }
     }
 
     // Place and size the child
@@ -88,19 +88,19 @@ nsPageContentFrame::Reflow(nsPresContext
   }
 
   // Reflow our fixed frames
   nsReflowStatus fixedStatus = NS_FRAME_COMPLETE;
   ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, fixedStatus);
   NS_ASSERTION(NS_FRAME_IS_COMPLETE(fixedStatus), "fixed frames can be truncated, but not incomplete");
 
   // Return our desired size
-  aDesiredSize.width = aReflowState.ComputedWidth();
+  aDesiredSize.Width() = aReflowState.ComputedWidth();
   if (aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE) {
-    aDesiredSize.height = aReflowState.ComputedHeight();
+    aDesiredSize.Height() = aReflowState.ComputedHeight();
   }
 
   FinishAndStoreOverflow(&aDesiredSize);
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -78,18 +78,18 @@ NS_IMETHODIMP nsPageFrame::Reflow(nsPres
       maxSize.height = NSToCoordCeil(maxSize.height / scale);
     }
     // Get the number of Twips per pixel from the PresContext
     nscoord onePixelInTwips = nsPresContext::CSSPixelsToAppUnits(1);
     // insurance against infinite reflow, when reflowing less than a pixel
     // XXX Shouldn't we do something more friendly when invalid margins
     //     are set?
     if (maxSize.width < onePixelInTwips || maxSize.height < onePixelInTwips) {
-      aDesiredSize.width  = 0;
-      aDesiredSize.height = 0;
+      aDesiredSize.Width() = 0;
+      aDesiredSize.Height() = 0;
       NS_WARNING("Reflow aborted; no space for content");
       return NS_OK;
     }
 
     nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, maxSize);
     kidReflowState.mFlags.mIsTopOfPage = true;
     kidReflowState.mFlags.mTableIsSplittable = true;
 
@@ -139,22 +139,22 @@ NS_IMETHODIMP nsPageFrame::Reflow(nsPres
 
     // Place and size the child
     FinishReflowChild(frame, aPresContext, &kidReflowState, aDesiredSize, xc, yc, 0);
 
     NS_ASSERTION(!NS_FRAME_IS_FULLY_COMPLETE(aStatus) ||
                  !frame->GetNextInFlow(), "bad child flow list");
   }
   PR_PL(("PageFrame::Reflow %p ", this));
-  PR_PL(("[%d,%d][%d,%d]\n", aDesiredSize.width, aDesiredSize.height, aReflowState.AvailableWidth(), aReflowState.AvailableHeight()));
+  PR_PL(("[%d,%d][%d,%d]\n", aDesiredSize.Width(), aDesiredSize.Height(), aReflowState.AvailableWidth(), aReflowState.AvailableHeight()));
 
   // Return our desired size
-  aDesiredSize.width = aReflowState.AvailableWidth();
+  aDesiredSize.Width() = aReflowState.AvailableWidth();
   if (aReflowState.AvailableHeight() != NS_UNCONSTRAINEDSIZE) {
-    aDesiredSize.height = aReflowState.AvailableHeight();
+    aDesiredSize.Height() = aReflowState.AvailableHeight();
   }
 
   aDesiredSize.SetOverflowAreasToDesiredBounds();
   FinishAndStoreOverflow(&aDesiredSize);
 
   PR_PL(("PageFrame::Reflow %p ", this));
   PR_PL(("[%d,%d]\n", aReflowState.AvailableWidth(), aReflowState.AvailableHeight()));
 
@@ -656,22 +656,22 @@ nsPageBreakFrame::Reflow(nsPresContext* 
                          const nsHTMLReflowState& aReflowState,
                          nsReflowStatus&          aStatus)
 {
   DO_GLOBAL_REFLOW_COUNT("nsPageBreakFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
 
   // Override reflow, since we don't want to deal with what our
   // computed values are.
-  aDesiredSize.width = GetIntrinsicWidth();
-  aDesiredSize.height = (aReflowState.AvailableHeight() == NS_UNCONSTRAINEDSIZE ?
+  aDesiredSize.Width() = GetIntrinsicWidth();
+  aDesiredSize.Height() = (aReflowState.AvailableHeight() == NS_UNCONSTRAINEDSIZE ?
                          0 : aReflowState.AvailableHeight());
   // round the height down to the nearest pixel
-  aDesiredSize.height -=
-    aDesiredSize.height % nsPresContext::CSSPixelsToAppUnits(1);
+  aDesiredSize.Height() -=
+    aDesiredSize.Height() % nsPresContext::CSSPixelsToAppUnits(1);
 
   // Note: not using NS_FRAME_FIRST_REFLOW here, since it's not clear whether
   // DidReflow will always get called before the next Reflow() call.
   mHaveReflowed = true;
   aStatus = NS_FRAME_COMPLETE; 
   return NS_OK;
 }
 
--- a/layout/generic/nsPlaceholderFrame.cpp
+++ b/layout/generic/nsPlaceholderFrame.cpp
@@ -127,18 +127,18 @@ nsPlaceholderFrame::Reflow(nsPresContext
     } else {
       NS_ERROR("Out-of-flow frame got reflowed before its placeholder");
     }
   }
 #endif
 
   DO_GLOBAL_REFLOW_COUNT("nsPlaceholderFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
-  aDesiredSize.width = 0;
-  aDesiredSize.height = 0;
+  aDesiredSize.Width() = 0;
+  aDesiredSize.Height() = 0;
 
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 void
 nsPlaceholderFrame::DestroyFrom(nsIFrame* aDestructRoot)
--- a/layout/generic/nsSimplePageSequence.cpp
+++ b/layout/generic/nsSimplePageSequence.cpp
@@ -106,19 +106,19 @@ nsSimplePageSequenceFrame::SetDesiredSiz
                                           const nsHTMLReflowState& aReflowState,
                                           nscoord aWidth,
                                           nscoord aHeight)
 {
     // Aim to fill the whole size of the document, not only so we
     // can act as a background in print preview but also handle overflow
     // in child page frames correctly.
     // Use availableWidth so we don't cause a needless horizontal scrollbar.
-    aDesiredSize.width = std::max(aReflowState.AvailableWidth(),
+    aDesiredSize.Width() = std::max(aReflowState.AvailableWidth(),
                                 nscoord(aWidth * PresContext()->GetPrintPreviewScale()));
-    aDesiredSize.height = std::max(aReflowState.ComputedHeight(),
+    aDesiredSize.Height() = std::max(aReflowState.ComputedHeight(),
                                  nscoord(aHeight * PresContext()->GetPrintPreviewScale()));
 }
 
 NS_IMETHODIMP
 nsSimplePageSequenceFrame::Reflow(nsPresContext*          aPresContext,
                                   nsHTMLReflowMetrics&     aDesiredSize,
                                   const nsHTMLReflowState& aReflowState,
                                   nsReflowStatus&          aStatus)
@@ -195,17 +195,17 @@ nsSimplePageSequenceFrame::Reflow(nsPres
 
   // We use the CSS "margin" property on the -moz-page pseudoelement
   // to determine the space between each page in print preview.
   // Keep a running y-offset for each page.
   nscoord y = 0;
   nscoord maxXMost = 0;
 
   // Tile the pages vertically
-  nsHTMLReflowMetrics kidSize;
+  nsHTMLReflowMetrics kidSize(aReflowState.GetWritingMode());
   for (nsIFrame* kidFrame = mFrames.FirstChild(); nullptr != kidFrame; ) {
     // Set the shared data into the page frame before reflow
     nsPageFrame * pf = static_cast<nsPageFrame*>(kidFrame);
     pf->SetSharedPageData(mPageData);
 
     // Reflow the page
     nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
                                      pageSize);
@@ -219,20 +219,20 @@ nsSimplePageSequenceFrame::Reflow(nsPres
     y += pageCSSMargin.top;
     const nscoord x = pageCSSMargin.left;
 
     // Place and size the page. If the page is narrower than our
     // max width then center it horizontally
     ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, x, y, 0, status);
 
     FinishReflowChild(kidFrame, aPresContext, nullptr, kidSize, x, y, 0);
-    y += kidSize.height;
+    y += kidSize.Height();
     y += pageCSSMargin.bottom;
 
-    maxXMost = std::max(maxXMost, x + kidSize.width + pageCSSMargin.right);
+    maxXMost = std::max(maxXMost, x + kidSize.Width() + pageCSSMargin.right);
 
     // Is the page complete?
     nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow();
 
     if (NS_FRAME_IS_FULLY_COMPLETE(status)) {
       NS_ASSERTION(!kidNextInFlow, "bad child flow list");
     } else if (!kidNextInFlow) {
       // The page isn't complete and it doesn't have a next-in-flow, so
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -649,17 +649,17 @@ nsSubDocumentFrame::Reflow(nsPresContext
                                       aStatus);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // "offset" is the offset of our content area from our frame's
   // top-left corner.
   nsPoint offset = nsPoint(aReflowState.ComputedPhysicalBorderPadding().left,
                            aReflowState.ComputedPhysicalBorderPadding().top);
 
-  nsSize innerSize(aDesiredSize.width, aDesiredSize.height);
+  nsSize innerSize(aDesiredSize.Width(), aDesiredSize.Height());
   innerSize.width  -= aReflowState.ComputedPhysicalBorderPadding().LeftRight();
   innerSize.height -= aReflowState.ComputedPhysicalBorderPadding().TopBottom();
 
   if (mInnerView) {
     nsViewManager* vm = mInnerView->GetViewManager();
     vm->MoveViewTo(mInnerView, offset.x, offset.y);
     vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), innerSize), true);
   }
@@ -675,21 +675,21 @@ nsSubDocumentFrame::Reflow(nsPresContext
   FinishAndStoreOverflow(&aDesiredSize);
 
   if (!aPresContext->IsPaginated() && !mPostedReflowCallback) {
     PresContext()->PresShell()->PostReflowCallback(this);
     mPostedReflowCallback = true;
   }
 
   // printf("OuterFrame::Reflow DONE %X (%d,%d)\n", this,
-  //        aDesiredSize.width, aDesiredSize.height);
+  //        aDesiredSize.Width(), aDesiredSize.Height());
 
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
      ("exit nsSubDocumentFrame::Reflow: size=%d,%d status=%x",
-      aDesiredSize.width, aDesiredSize.height, aStatus));
+      aDesiredSize.Width(), aDesiredSize.Height(), aStatus));
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 bool
 nsSubDocumentFrame::ReflowFinished()
 {
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -2711,19 +2711,19 @@ static bool IsJustifiableCharacter(const
      ))
     return true;
   return false;
 }
 
 void
 nsTextFrame::ClearMetrics(nsHTMLReflowMetrics& aMetrics)
 {
-  aMetrics.width = 0;
-  aMetrics.height = 0;
-  aMetrics.ascent = 0;
+  aMetrics.Width() = 0;
+  aMetrics.Height() = 0;
+  aMetrics.SetTopAscent(0);
   mAscent = 0;
 }
 
 static int32_t FindChar(const nsTextFragment* frag,
                         int32_t aOffset, int32_t aLength, PRUnichar ch)
 {
   int32_t i = 0;
   if (frag->Is2b()) {
@@ -7991,41 +7991,41 @@ nsTextFrame::ReflowText(nsLineLayout& aL
   // for good drop-cap effects
   if (GetStateBits() & TEXT_FIRST_LETTER) {
     textMetrics.mAscent = std::max(gfxFloat(0.0), -textMetrics.mBoundingBox.Y());
     textMetrics.mDescent = std::max(gfxFloat(0.0), textMetrics.mBoundingBox.YMost());
   }
 
   // Setup metrics for caller
   // Disallow negative widths
-  aMetrics.width = NSToCoordCeil(std::max(gfxFloat(0.0), textMetrics.mAdvanceWidth));
+  aMetrics.Width() = NSToCoordCeil(std::max(gfxFloat(0.0), textMetrics.mAdvanceWidth));
 
   if (transformedCharsFit == 0 && !usedHyphenation) {
-    aMetrics.ascent = 0;
-    aMetrics.height = 0;
+    aMetrics.SetTopAscent(0);
+    aMetrics.Height() = 0;
   } else if (boundingBoxType != gfxFont::LOOSE_INK_EXTENTS) {
     // Use actual text metrics for floating first letter frame.
-    aMetrics.ascent = NSToCoordCeil(textMetrics.mAscent);
-    aMetrics.height = aMetrics.ascent + NSToCoordCeil(textMetrics.mDescent);
+    aMetrics.SetTopAscent(NSToCoordCeil(textMetrics.mAscent));
+    aMetrics.Height() = aMetrics.TopAscent() + NSToCoordCeil(textMetrics.mDescent);
   } else {
     // Otherwise, ascent should contain the overline drawable area.
     // And also descent should contain the underline drawable area.
     // nsFontMetrics::GetMaxAscent/GetMaxDescent contains them.
     nsFontMetrics* fm = provider.GetFontMetrics();
     nscoord fontAscent = fm->MaxAscent();
     nscoord fontDescent = fm->MaxDescent();
-    aMetrics.ascent = std::max(NSToCoordCeil(textMetrics.mAscent), fontAscent);
+    aMetrics.SetTopAscent(std::max(NSToCoordCeil(textMetrics.mAscent), fontAscent));
     nscoord descent = std::max(NSToCoordCeil(textMetrics.mDescent), fontDescent);
-    aMetrics.height = aMetrics.ascent + descent;
-  }
-
-  NS_ASSERTION(aMetrics.ascent >= 0, "Negative ascent???");
-  NS_ASSERTION(aMetrics.height - aMetrics.ascent >= 0, "Negative descent???");
-
-  mAscent = aMetrics.ascent;
+    aMetrics.Height() = aMetrics.TopAscent() + descent;
+  }
+
+  NS_ASSERTION(aMetrics.TopAscent() >= 0, "Negative ascent???");
+  NS_ASSERTION(aMetrics.Height() - aMetrics.TopAscent() >= 0, "Negative descent???");
+
+  mAscent = aMetrics.TopAscent();
 
   // Handle text that runs outside its normal bounds.
   nsRect boundingBox = RoundOut(textMetrics.mBoundingBox) + nsPoint(0, mAscent);
   aMetrics.SetOverflowAreasToDesiredBounds();
   aMetrics.VisualOverflow().UnionRect(aMetrics.VisualOverflow(), boundingBox);
 
   // When we have text decorations, we don't need to compute their overflow now
   // because we're guaranteed to do it later
@@ -8134,17 +8134,17 @@ nsTextFrame::ReflowText(nsLineLayout& aL
 
   SetLength(contentLength, &aLineLayout, ALLOW_FRAME_CREATION_AND_DESTRUCTION);
 
   InvalidateFrame();
 
 #ifdef NOISY_REFLOW
   ListTag(stdout);
   printf(": desiredSize=%d,%d(b=%d) status=%x\n",
-         aMetrics.width, aMetrics.height, aMetrics.ascent,
+         aMetrics.Width(), aMetrics.Height(), aMetrics.TopAscent(),
          aStatus);
 #endif
 }
 
 /* virtual */ bool
 nsTextFrame::CanContinueTextRun() const
 {
   // We can continue a text run through a text frame
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -248,42 +248,42 @@ nsVideoFrame::Reflow(nsPresContext*     
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                   ("enter nsVideoFrame::Reflow: availSize=%d,%d",
                   aReflowState.AvailableWidth(), aReflowState.AvailableHeight()));
 
   NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow");
 
   aStatus = NS_FRAME_COMPLETE;
 
-  aMetrics.width = aReflowState.ComputedWidth();
-  aMetrics.height = aReflowState.ComputedHeight();
+  aMetrics.Width() = aReflowState.ComputedWidth();
+  aMetrics.Height() = aReflowState.ComputedHeight();
 
   // stash this away so we can compute our inner area later
   mBorderPadding   = aReflowState.ComputedPhysicalBorderPadding();
 
-  aMetrics.width += mBorderPadding.left + mBorderPadding.right;
-  aMetrics.height += mBorderPadding.top + mBorderPadding.bottom;
+  aMetrics.Width() += mBorderPadding.left + mBorderPadding.right;
+  aMetrics.Height() += mBorderPadding.top + mBorderPadding.bottom;
 
   // Reflow the child frames. We may have up to two, an image frame
   // which is the poster, and a box frame, which is the video controls.
   for (nsIFrame *child = mFrames.FirstChild();
        child;
        child = child->GetNextSibling()) {
     if (child->GetContent() == mPosterImage) {
       // Reflow the poster frame.
       nsImageFrame* imageFrame = static_cast<nsImageFrame*>(child);
-      nsHTMLReflowMetrics kidDesiredSize;
+      nsHTMLReflowMetrics kidDesiredSize(aReflowState.GetWritingMode());
       nsSize availableSize = nsSize(aReflowState.AvailableWidth(),
                                     aReflowState.AvailableHeight());
       nsHTMLReflowState kidReflowState(aPresContext,
                                        aReflowState,
                                        imageFrame,
                                        availableSize,
-                                       aMetrics.width,
-                                       aMetrics.height);
+                                       aMetrics.Width(),
+                                       aMetrics.Height());
 
       uint32_t posterHeight, posterWidth;
       nsSize scaledPosterSize(0, 0);
       nsSize computedArea(aReflowState.ComputedWidth(), aReflowState.ComputedHeight());
       nsPoint posterTopLeft(0, 0);
 
       nsCOMPtr<nsIDOMHTMLImageElement> posterImage = do_QueryInterface(mPosterImage);
       NS_ENSURE_TRUE(posterImage, NS_ERROR_FAILURE);
@@ -318,25 +318,25 @@ nsVideoFrame::Reflow(nsPresContext*     
                                        aReflowState.ComputedWidth(),
                                        aReflowState.ComputedHeight()));
       if (child->GetSize() != size) {
         nsRefPtr<nsRunnable> event = new DispatchResizeToControls(child->GetContent());
         nsContentUtils::AddScriptRunner(event);
       }
     } else if (child->GetContent() == mCaptionDiv) {
       // Reflow to caption div
-      nsHTMLReflowMetrics kidDesiredSize;
+      nsHTMLReflowMetrics kidDesiredSize(aReflowState.GetWritingMode());
       nsSize availableSize = nsSize(aReflowState.AvailableWidth(),
                                     aReflowState.AvailableHeight());
       nsHTMLReflowState kidReflowState(aPresContext,
                                        aReflowState,
                                        child,
                                        availableSize,
-                                       aMetrics.width,
-                                       aMetrics.height);
+                                       aMetrics.Width(),
+                                       aMetrics.Height());
       nsSize size(aReflowState.ComputedWidth(), aReflowState.ComputedHeight());
       size.width -= kidReflowState.ComputedPhysicalBorderPadding().LeftRight();
       size.height -= kidReflowState.ComputedPhysicalBorderPadding().TopBottom();
 
       kidReflowState.SetComputedWidth(std::max(size.width, 0));
       kidReflowState.SetComputedHeight(std::max(size.height, 0));
 
       ReflowChild(child, aPresContext, kidDesiredSize, kidReflowState,
@@ -347,17 +347,17 @@ nsVideoFrame::Reflow(nsPresContext*     
     }
   }
   aMetrics.SetOverflowAreasToDesiredBounds();
 
   FinishAndStoreOverflow(&aMetrics);
 
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                   ("exit nsVideoFrame::Reflow: size=%d,%d",
-                  aMetrics.width, aMetrics.height));
+                  aMetrics.Width(), aMetrics.Height()));
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
 
   return NS_OK;
 }
 
 class nsDisplayVideo : public nsDisplayItem {
 public:
   nsDisplayVideo(nsDisplayListBuilder* aBuilder, nsVideoFrame* aFrame)
--- a/layout/generic/nsViewportFrame.cpp
+++ b/layout/generic/nsViewportFrame.cpp
@@ -205,63 +205,63 @@ ViewportFrame::Reflow(nsPresContext*    
   if (mFrames.NotEmpty()) {
     // Deal with a non-incremental reflow or an incremental reflow
     // targeted at our one-and-only principal child frame.
     if (aReflowState.ShouldReflowAllKids() ||
         aReflowState.mFlags.mVResize ||
         NS_SUBTREE_DIRTY(mFrames.FirstChild())) {
       // Reflow our one-and-only principal child frame
       nsIFrame*           kidFrame = mFrames.FirstChild();
-      nsHTMLReflowMetrics kidDesiredSize;
+      nsHTMLReflowMetrics kidDesiredSize(aReflowState.GetWritingMode());
       nsSize              availableSpace(aReflowState.AvailableWidth(),
                                          aReflowState.AvailableHeight());
       nsHTMLReflowState   kidReflowState(aPresContext, aReflowState,
                                          kidFrame, availableSpace);
 
       // Reflow the frame
       kidReflowState.SetComputedHeight(aReflowState.ComputedHeight());
       rv = ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState,
                        0, 0, 0, aStatus);
-      kidHeight = kidDesiredSize.height;
+      kidHeight = kidDesiredSize.Height();
 
       FinishReflowChild(kidFrame, aPresContext, nullptr, kidDesiredSize, 0, 0, 0);
     } else {
       kidHeight = mFrames.FirstChild()->GetSize().height;
     }
   }
 
   NS_ASSERTION(aReflowState.AvailableWidth() != NS_UNCONSTRAINEDSIZE,
                "shouldn't happen anymore");
 
   // Return the max size as our desired size
-  aDesiredSize.width = aReflowState.AvailableWidth();
+  aDesiredSize.Width() = aReflowState.AvailableWidth();
   // Being flowed initially at an unconstrained height means we should
   // return our child's intrinsic size.
-  aDesiredSize.height = aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE
+  aDesiredSize.Height() = aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE
                           ? aReflowState.ComputedHeight()
                           : kidHeight;
   aDesiredSize.SetOverflowAreasToDesiredBounds();
 
   if (mFrames.NotEmpty()) {
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, mFrames.FirstChild());
   }
 
   if (IsAbsoluteContainer()) {
     // Make a copy of the reflow state and change the computed width and height
     // to reflect the available space for the fixed items
     nsHTMLReflowState reflowState(aReflowState);
 
     if (reflowState.AvailableHeight() == NS_UNCONSTRAINEDSIZE) {
       // We have an intrinsic-height document with abs-pos/fixed-pos children.
       // Set the available height and mComputedHeight to our chosen height.
-      reflowState.AvailableHeight() = aDesiredSize.height;
+      reflowState.AvailableHeight() = aDesiredSize.Height();
       // Not having border/padding simplifies things
       NS_ASSERTION(reflowState.ComputedPhysicalBorderPadding() == nsMargin(0,0,0,0),
                    "Viewports can't have border/padding");
-      reflowState.SetComputedHeight(aDesiredSize.height);
+      reflowState.SetComputedHeight(aDesiredSize.Height());
     }
 
     nsRect rect = AdjustReflowStateAsContainingBlock(&reflowState);
 
     // Just reflow all the fixed-pos frames.
     rv = GetAbsoluteContainingBlock()->Reflow(this, aPresContext, reflowState, aStatus,
                                               rect,
                                               false, true, true, // XXX could be optimized
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -51,20 +51,20 @@ nsMathMLContainerFrame::ReflowError(nsRe
   aRenderingContext.SetFont(fm);
 
   // bounding metrics
   nsAutoString errorMsg; errorMsg.AssignLiteral("invalid-markup");
   mBoundingMetrics =
     aRenderingContext.GetBoundingMetrics(errorMsg.get(), errorMsg.Length());
 
   // reflow metrics
-  aDesiredSize.ascent = fm->MaxAscent();
+  aDesiredSize.SetTopAscent(fm->MaxAscent());
   nscoord descent = fm->MaxDescent();
-  aDesiredSize.height = aDesiredSize.ascent + descent;
-  aDesiredSize.width = mBoundingMetrics.width;
+  aDesiredSize.Height() = aDesiredSize.TopAscent() + descent;
+  aDesiredSize.Width() = mBoundingMetrics.width;
 
   // Also return our bounding metrics
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
 
   return NS_OK;
 }
 
 class nsDisplayMathMLError : public nsDisplayItem {
@@ -190,17 +190,17 @@ nsMathMLContainerFrame::GetPreferredStre
                                                 nsBoundingMetrics&   aPreferredStretchSize)
 {
   if (aOptions & STRETCH_CONSIDER_ACTUAL_SIZE) {
     // when our actual size is ok, just use it
     aPreferredStretchSize = mBoundingMetrics;
   }
   else if (aOptions & STRETCH_CONSIDER_EMBELLISHMENTS) {
     // compute our up-to-date size using Place()
-    nsHTMLReflowMetrics metrics;
+    nsHTMLReflowMetrics metrics(GetWritingMode()); // ???
     Place(aRenderingContext, false, metrics);
     aPreferredStretchSize = metrics.mBoundingMetrics;
   }
   else {
     // compute a size that doesn't include embellishements
     bool stretchAll =
       NS_MATHML_WILL_STRETCH_ALL_CHILDREN_VERTICALLY(mPresentationData.flags) ||
       NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(mPresentationData.flags);
@@ -228,17 +228,17 @@ nsMathMLContainerFrame::GetPreferredStre
           nsIMathMLFrame* mathMLchildFrame = do_QueryFrame(presentationData.baseFrame);
           if (mathMLchildFrame) {
             mathMLFrame = mathMLchildFrame;
           }
         }
         mathMLFrame->GetBoundingMetrics(bmChild);
       }
       else {
-        nsHTMLReflowMetrics unused;
+        nsHTMLReflowMetrics unused(GetWritingMode());
         GetReflowAndBoundingMetricsFor(childFrame, unused, bmChild);
       }
 
       if (firstTime) {
         firstTime = false;
         bm = bmChild;
         if (!stretchAll) {
           // we may get here for cases such as <msup><mo>...</mo> ... </msup>,
@@ -398,17 +398,17 @@ nsMathMLContainerFrame::Stretch(nsRender
           // (we fetch values from the core since they may use units that depend
           // on style data, and style changes could have occurred in the core since
           // our last visit there)
           nsEmbellishData coreData;
           GetEmbellishDataFrom(mEmbellishData.coreFrame, coreData);
 
           mBoundingMetrics.width +=
             coreData.leadingSpace + coreData.trailingSpace;
-          aDesiredStretchSize.width = mBoundingMetrics.width;
+          aDesiredStretchSize.Width() = mBoundingMetrics.width;
           aDesiredStretchSize.mBoundingMetrics.width = mBoundingMetrics.width;
 
           nscoord dx = (StyleVisibility()->mDirection ?
                         coreData.trailingSpace : coreData.leadingSpace);
           if (dx != 0) {
             mBoundingMetrics.leftBearing += dx;
             mBoundingMetrics.rightBearing += dx;
             aDesiredStretchSize.mBoundingMetrics.leftBearing += dx;
@@ -804,17 +804,17 @@ nsMathMLContainerFrame::GatherAndStoreOv
 {
   // nsIFrame::FinishAndStoreOverflow likes the overflow area to include the
   // frame rectangle.
   aMetrics->SetOverflowAreasToDesiredBounds();
 
   // All non-child-frame content such as nsMathMLChars (and most child-frame
   // content) is included in mBoundingMetrics.
   nsRect boundingBox(mBoundingMetrics.leftBearing,
-                     aMetrics->ascent - mBoundingMetrics.ascent,
+                     aMetrics->TopAscent() - mBoundingMetrics.ascent,
                      mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing,
                      mBoundingMetrics.ascent + mBoundingMetrics.descent);
 
   // REVIEW: Maybe this should contribute only to visual overflow
   // and not scrollable?
   aMetrics->mOverflowAreas.UnionAllWith(boundingBox);
 
   // mBoundingMetrics does not necessarily include content of <mpadded>
@@ -865,57 +865,61 @@ nsMathMLContainerFrame::ReflowChild(nsIF
   
   nsresult rv = nsContainerFrame::
          ReflowChild(aChildFrame, aPresContext, aDesiredSize, aReflowState,
                      0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
 
   if (NS_FAILED(rv))
     return rv;
 
-  if (aDesiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
+  if (aDesiredSize.TopAscent() == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
     // This will be suitable for inline frames, which are wrapped in a block.
-    if(!nsLayoutUtils::GetLastLineBaseline(aChildFrame,
-                                           &aDesiredSize.ascent)) {
+    nscoord ascent;
+    if (!nsLayoutUtils::GetLastLineBaseline(aChildFrame,
+                                            &ascent)) {
       // We don't expect any other block children so just place the frame on
       // the baseline instead of going through DidReflow() and
       // GetBaseline().  This is what nsFrame::GetBaseline() will do anyway.
-      aDesiredSize.ascent = aDesiredSize.height;
+      aDesiredSize.SetTopAscent(aDesiredSize.Height());
+    } else {
+      aDesiredSize.SetTopAscent(ascent);
     }
   }
   if (IsForeignChild(aChildFrame)) {
     // use ComputeTightBounds API as aDesiredSize.mBoundingMetrics is not set.
     nsRect r = aChildFrame->ComputeTightBounds(aReflowState.rendContext->ThebesContext());
     aDesiredSize.mBoundingMetrics.leftBearing = r.x;
     aDesiredSize.mBoundingMetrics.rightBearing = r.XMost();
-    aDesiredSize.mBoundingMetrics.ascent = aDesiredSize.ascent - r.y;
-    aDesiredSize.mBoundingMetrics.descent = r.YMost() - aDesiredSize.ascent;
-    aDesiredSize.mBoundingMetrics.width = aDesiredSize.width;
+    aDesiredSize.mBoundingMetrics.ascent = aDesiredSize.TopAscent() - r.y;
+    aDesiredSize.mBoundingMetrics.descent = r.YMost() - aDesiredSize.TopAscent();
+    aDesiredSize.mBoundingMetrics.width = aDesiredSize.Width();
   }
   return rv;
 }
 
 NS_IMETHODIMP
 nsMathMLContainerFrame::Reflow(nsPresContext*           aPresContext,
                                nsHTMLReflowMetrics&     aDesiredSize,
                                const nsHTMLReflowState& aReflowState,
                                nsReflowStatus&          aStatus)
 {
-  aDesiredSize.width = aDesiredSize.height = 0;
-  aDesiredSize.ascent = 0;
+  aDesiredSize.Width() = aDesiredSize.Height() = 0;
+  aDesiredSize.SetTopAscent(0);
   aDesiredSize.mBoundingMetrics = nsBoundingMetrics();
 
   /////////////
   // Reflow children
   // Asking each child to cache its bounding metrics
 
   nsReflowStatus childStatus;
   nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE);
   nsIFrame* childFrame = mFrames.FirstChild();
   while (childFrame) {
-    nsHTMLReflowMetrics childDesiredSize(aDesiredSize.mFlags);
+    nsHTMLReflowMetrics childDesiredSize(aReflowState.GetWritingMode(), // ???
+                                         aDesiredSize.mFlags);
     nsHTMLReflowState childReflowState(aPresContext, aReflowState,
                                        childFrame, availSize);
     nsresult rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
                               childReflowState, childStatus);
     //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
     if (NS_FAILED(rv)) {
       // Call DidReflow() for the child frames we successfully did reflow.
       DidReflowChildren(mFrames.FirstChild(), childFrame);
@@ -953,17 +957,17 @@ nsMathMLContainerFrame::Reflow(nsPresCon
                             containerSize);
 
     // fire the stretch on each child
     childFrame = mFrames.FirstChild();
     while (childFrame) {
       nsIMathMLFrame* mathMLFrame = do_QueryFrame(childFrame);
       if (mathMLFrame) {
         // retrieve the metrics that was stored at the previous pass
-        nsHTMLReflowMetrics childDesiredSize;
+        nsHTMLReflowMetrics childDesiredSize(aReflowState.GetWritingMode());
         GetReflowAndBoundingMetricsFor(childFrame,
           childDesiredSize, childDesiredSize.mBoundingMetrics);
 
         mathMLFrame->Stretch(*aReflowState.rendContext, stretchDir,
                              containerSize, childDesiredSize);
         // store the updated metrics
         SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
                                         childDesiredSize.mBoundingMetrics);
@@ -981,58 +985,58 @@ nsMathMLContainerFrame::Reflow(nsPresCon
   return NS_OK;
 }
 
 /* virtual */ nscoord
 nsMathMLContainerFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
 {
   nscoord result;
   DISPLAY_MIN_WIDTH(this, result);
-  nsHTMLReflowMetrics desiredSize;
+  nsHTMLReflowMetrics desiredSize(GetWritingMode());
   GetIntrinsicWidthMetrics(aRenderingContext, desiredSize);
   nsBoundingMetrics bm = desiredSize.mBoundingMetrics;
   // We include the overflow to compensate for FixInterFrameSpacing.
   result = std::max(bm.width, bm.rightBearing) - std::min(0, bm.leftBearing);
   return result;
 }
 
 /* virtual */ nscoord
 nsMathMLContainerFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
 {
   nscoord result;
   DISPLAY_MIN_WIDTH(this, result);
-  nsHTMLReflowMetrics desiredSize;
+  nsHTMLReflowMetrics desiredSize(GetWritingMode());
   GetIntrinsicWidthMetrics(aRenderingContext, desiredSize);
   nsBoundingMetrics bm = desiredSize.mBoundingMetrics;
   // We include the overflow to compensate for FixInterFrameSpacing.
   result = std::max(bm.width, bm.rightBearing) - std::min(0, bm.leftBearing);
   return result;
 }
 
 /* virtual */ void
 nsMathMLContainerFrame::GetIntrinsicWidthMetrics(nsRenderingContext* aRenderingContext, nsHTMLReflowMetrics& aDesiredSize)
 {
   // Get child widths
   nsIFrame* childFrame = mFrames.FirstChild();
   while (childFrame) {
-    nsHTMLReflowMetrics childDesiredSize;
+    nsHTMLReflowMetrics childDesiredSize(GetWritingMode()); // ???
 
     nsMathMLContainerFrame* containerFrame = do_QueryFrame(childFrame);
     if (containerFrame) {
       containerFrame->GetIntrinsicWidthMetrics(aRenderingContext,
                                                childDesiredSize);
     } else {
       // XXX This includes margin while Reflow currently doesn't consider
       // margin, so we may end up with too much space, but, with stretchy
       // characters, this is an approximation anyway.
       nscoord width =
         nsLayoutUtils::IntrinsicForContainer(aRenderingContext, childFrame,
                                              nsLayoutUtils::PREF_WIDTH);
 
-      childDesiredSize.width = width;
+      childDesiredSize.Width() = width;
       childDesiredSize.mBoundingMetrics.width = width;
       childDesiredSize.mBoundingMetrics.leftBearing = 0;
       childDesiredSize.mBoundingMetrics.rightBearing = width;
 
       nscoord x, xMost;
       if (NS_SUCCEEDED(childFrame->GetPrefWidthTightBounds(aRenderingContext,
                                                            &x, &xMost))) {
         childDesiredSize.mBoundingMetrics.leftBearing = x;
@@ -1173,16 +1177,17 @@ static nscoord GetThinSpace(const nsStyl
 {
   return NSToCoordRound(float(aStyleFont->mFont.size)*float(3) / float(18));
 }
 
 class nsMathMLContainerFrame::RowChildFrameIterator {
 public:
   explicit RowChildFrameIterator(nsMathMLContainerFrame* aParentFrame) :
     mParentFrame(aParentFrame),
+    mSize(aParentFrame->GetWritingMode()), // ???
     mX(0),
     mCarrySpace(0),
     mFromFrameType(eMathMLFrameType_UNKNOWN),
     mRTL(aParentFrame->StyleVisibility()->mDirection)
   {
     if (!mRTL) {
       mChildFrame = aParentFrame->mFrames.FirstChild();
     } else {
@@ -1220,18 +1225,18 @@ public:
                            &mFromFrameType, &mCarrySpace);
     mX += space * GetThinSpace(font);
     return *this;
   }
 
   nsIFrame* Frame() const { return mChildFrame; }
   nscoord X() const { return mX; }
   const nsHTMLReflowMetrics& ReflowMetrics() const { return mSize; }
-  nscoord Ascent() const { return mSize.ascent; }
-  nscoord Descent() const { return mSize.height - mSize.ascent; }
+  nscoord Ascent() const { return mSize.TopAscent(); }
+  nscoord Descent() const { return mSize.Height() - mSize.TopAscent(); }
   const nsBoundingMetrics& BoundingMetrics() const {
     return mSize.mBoundingMetrics;
   }
 
 private:
   const nsMathMLContainerFrame* mParentFrame;
   nsIFrame* mChildFrame;
   nsHTMLReflowMetrics mSize;
@@ -1289,29 +1294,29 @@ nsMathMLContainerFrame::Place(nsRenderin
     ++child;
   }
   // Add the italic correction at the end (including the last child).
   // This gives a nice gap between math and non-math frames, and still
   // gives the same math inter-spacing in case this frame connects to
   // another math frame
   mBoundingMetrics.width = child.X();
 
-  aDesiredSize.width = std::max(0, mBoundingMetrics.width);
-  aDesiredSize.height = ascent + descent;
-  aDesiredSize.ascent = ascent;
+  aDesiredSize.Width() = std::max(0, mBoundingMetrics.width);
+  aDesiredSize.Height() = ascent + descent;
+  aDesiredSize.SetTopAscent(ascent);
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
 
   mReference.x = 0;
-  mReference.y = aDesiredSize.ascent;
+  mReference.y = aDesiredSize.TopAscent();
 
   //////////////////
   // Place Children
 
   if (aPlaceOrigin) {
-    PositionRowChildFrames(0, aDesiredSize.ascent);
+    PositionRowChildFrames(0, aDesiredSize.TopAscent());
   }
 
   return NS_OK;
 }
 
 void
 nsMathMLContainerFrame::PositionRowChildFrames(nscoord aOffsetX,
                                                nscoord aBaseline)
@@ -1415,20 +1420,20 @@ nsMathMLContainerFrame::FixInterFrameSpa
       nsIFrame* childFrame = mFrames.FirstChild();
       while (childFrame) {
         childFrame->SetPosition(childFrame->GetPosition() + nsPoint(gap, 0));
         childFrame = childFrame->GetNextSibling();
       }
       mBoundingMetrics.leftBearing += gap;
       mBoundingMetrics.rightBearing += gap;
       mBoundingMetrics.width += gap;
-      aDesiredSize.width += gap;
+      aDesiredSize.Width() += gap;
     }
     mBoundingMetrics.width += italicCorrection;
-    aDesiredSize.width += italicCorrection;
+    aDesiredSize.Width() += italicCorrection;
   }
   return gap;
 }
 
 /* static */ void
 nsMathMLContainerFrame::DidReflowChildren(nsIFrame* aFirst, nsIFrame* aStop)
 
 {
--- a/layout/mathml/nsMathMLSelectedFrame.cpp
+++ b/layout/mathml/nsMathMLSelectedFrame.cpp
@@ -102,18 +102,18 @@ nsMathMLSelectedFrame::BuildDisplayList(
 NS_IMETHODIMP
 nsMathMLSelectedFrame::Reflow(nsPresContext*          aPresContext,
                               nsHTMLReflowMetrics&     aDesiredSize,
                               const nsHTMLReflowState& aReflowState,
                               nsReflowStatus&          aStatus)
 {
   nsresult rv = NS_OK;
   aStatus = NS_FRAME_COMPLETE;
-  aDesiredSize.width = aDesiredSize.height = 0;
-  aDesiredSize.ascent = 0;
+  aDesiredSize.Width() = aDesiredSize.Height() = 0;
+  aDesiredSize.SetTopAscent(0);
   mBoundingMetrics = nsBoundingMetrics();
   nsIFrame* childFrame = GetSelectedFrame();
   if (childFrame) {
     nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE);
     nsHTMLReflowState childReflowState(aPresContext, aReflowState,
                                        childFrame, availSize);
     rv = ReflowChild(childFrame, aPresContext, aDesiredSize,
                      childReflowState, aStatus);
@@ -133,22 +133,22 @@ nsMathMLSelectedFrame::Place(nsRendering
                              nsHTMLReflowMetrics& aDesiredSize)
 {
   nsIFrame* childFrame = GetSelectedFrame();
 
   if (mInvalidMarkup) {
     return ReflowError(aRenderingContext, aDesiredSize);
   }
 
-  aDesiredSize.width = aDesiredSize.height = 0;
-  aDesiredSize.ascent = 0;
+  aDesiredSize.Width() = aDesiredSize.Height() = 0;
+  aDesiredSize.SetTopAscent(0);
   mBoundingMetrics = nsBoundingMetrics();
   if (childFrame) {
     GetReflowAndBoundingMetricsFor(childFrame, aDesiredSize, mBoundingMetrics);
     if (aPlaceOrigin) {
       FinishReflowChild(childFrame, PresContext(), nullptr, aDesiredSize, 0, 0, 0);
     }
     mReference.x = 0;
-    mReference.y = aDesiredSize.ascent;
+    mReference.y = aDesiredSize.TopAscent();
   }
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
   return NS_OK;
 }
--- a/layout/mathml/nsMathMLTokenFrame.cpp
+++ b/layout/mathml/nsMathMLTokenFrame.cpp
@@ -135,25 +135,26 @@ nsresult
 nsMathMLTokenFrame::Reflow(nsPresContext*          aPresContext,
                            nsHTMLReflowMetrics&     aDesiredSize,
                            const nsHTMLReflowState& aReflowState,
                            nsReflowStatus&          aStatus)
 {
   nsresult rv = NS_OK;
 
   // initializations needed for empty markup like <mtag></mtag>
-  aDesiredSize.width = aDesiredSize.height = 0;
-  aDesiredSize.ascent = 0;
+  aDesiredSize.Width() = aDesiredSize.Height() = 0;
+  aDesiredSize.SetTopAscent(0);
   aDesiredSize.mBoundingMetrics = nsBoundingMetrics();
 
   nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE);
   nsIFrame* childFrame = GetFirstPrincipalChild();
   while (childFrame) {
     // ask our children to compute their bounding metrics
-    nsHTMLReflowMetrics childDesiredSize(aDesiredSize.mFlags
+    nsHTMLReflowMetrics childDesiredSize(aReflowState.GetWritingMode(),
+                                         aDesiredSize.mFlags
                                          | NS_REFLOW_CALC_BOUNDING_METRICS);
     nsHTMLReflowState childReflowState(aPresContext, aReflowState,
                                        childFrame, availSize);
     rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
                      childReflowState, aStatus);
     //NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
     if (NS_FAILED(rv)) {
       // Call DidReflow() for the child frames we successfully did reflow.
@@ -182,46 +183,46 @@ nsMathMLTokenFrame::Reflow(nsPresContext
 /* virtual */ nsresult
 nsMathMLTokenFrame::Place(nsRenderingContext& aRenderingContext,
                           bool                 aPlaceOrigin,
                           nsHTMLReflowMetrics& aDesiredSize)
 {
   mBoundingMetrics = nsBoundingMetrics();
   for (nsIFrame* childFrame = GetFirstPrincipalChild(); childFrame;
        childFrame = childFrame->GetNextSibling()) {
-    nsHTMLReflowMetrics childSize;
+    nsHTMLReflowMetrics childSize(aDesiredSize.GetWritingMode());
     GetReflowAndBoundingMetricsFor(childFrame, childSize,
                                    childSize.mBoundingMetrics, nullptr);
     // compute and cache the bounding metrics
     mBoundingMetrics += childSize.mBoundingMetrics;
   }
 
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
   nscoord ascent = fm->MaxAscent();
   nscoord descent = fm->MaxDescent();
 
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
-  aDesiredSize.width = mBoundingMetrics.width;
-  aDesiredSize.ascent = std::max(mBoundingMetrics.ascent, ascent);
-  aDesiredSize.height = aDesiredSize.ascent +
+  aDesiredSize.Width() = mBoundingMetrics.width;
+  aDesiredSize.SetTopAscent(std::max(mBoundingMetrics.ascent, ascent));
+  aDesiredSize.Height() = aDesiredSize.TopAscent() +
                         std::max(mBoundingMetrics.descent, descent);
 
   if (aPlaceOrigin) {
     nscoord dy, dx = 0;
     for (nsIFrame* childFrame = GetFirstPrincipalChild(); childFrame;
          childFrame = childFrame->GetNextSibling()) {
-      nsHTMLReflowMetrics childSize;
+      nsHTMLReflowMetrics childSize(aDesiredSize.GetWritingMode());
       GetReflowAndBoundingMetricsFor(childFrame, childSize,
                                      childSize.mBoundingMetrics);
 
       // place and size the child; (dx,0) makes the caret happy - bug 188146
-      dy = childSize.height == 0 ? 0 : aDesiredSize.ascent - childSize.ascent;
+      dy = childSize.Height() == 0 ? 0 : aDesiredSize.TopAscent() - childSize.TopAscent();
       FinishReflowChild(childFrame, PresContext(), nullptr, childSize, dx, dy, 0);
-      dx += childSize.width;
+      dx += childSize.Width();
     }
   }
 
-  SetReference(nsPoint(0, aDesiredSize.ascent));
+  SetReference(nsPoint(0, aDesiredSize.TopAscent()));
 
   return NS_OK;
 }
 
--- a/layout/mathml/nsMathMLmencloseFrame.cpp
+++ b/layout/mathml/nsMathMLmencloseFrame.cpp
@@ -302,17 +302,17 @@ nsMathMLmencloseFrame::Place(nsRendering
 nsMathMLmencloseFrame::PlaceInternal(nsRenderingContext& aRenderingContext,
                                      bool                 aPlaceOrigin,
                                      nsHTMLReflowMetrics& aDesiredSize,
                                      bool                 aWidthOnly)
 {
   ///////////////
   // Measure the size of our content using the base class to format like an
   // inferred mrow.
-  nsHTMLReflowMetrics baseSize;
+  nsHTMLReflowMetrics baseSize(aDesiredSize.GetWritingMode());
   nsresult rv =
     nsMathMLContainerFrame::Place(aRenderingContext, false, baseSize);
 
   if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
       DidReflowChildren(GetFirstPrincipalChild());
       return rv;
     }
 
@@ -544,117 +544,117 @@ nsMathMLmencloseFrame::PlaceInternal(nsR
   ///////////////
   // The maximum size is now computed: set the remaining parameters
   mBoundingMetrics.width = dx_left + bmBase.width + dx_right;
 
   mBoundingMetrics.leftBearing = std::min(0, dx_left + bmBase.leftBearing);
   mBoundingMetrics.rightBearing =
     std::max(mBoundingMetrics.width, dx_left + bmBase.rightBearing);
   
-  aDesiredSize.width = mBoundingMetrics.width;
+  aDesiredSize.Width() = mBoundingMetrics.width;
 
-  aDesiredSize.ascent = std::max(mBoundingMetrics.ascent, baseSize.ascent);
-  aDesiredSize.height = aDesiredSize.ascent +
-    std::max(mBoundingMetrics.descent, baseSize.height - baseSize.ascent);
+  aDesiredSize.SetTopAscent(std::max(mBoundingMetrics.ascent, baseSize.TopAscent()));
+  aDesiredSize.Height() = aDesiredSize.TopAscent() +
+    std::max(mBoundingMetrics.descent, baseSize.Height() - baseSize.TopAscent());
 
   if (IsToDraw(NOTATION_LONGDIV) || IsToDraw(NOTATION_RADICAL)) {
     // get the leading to be left at the top of the resulting frame
     // this seems more reliable than using fm->GetLeading() on suspicious
     // fonts
     nscoord leading = nscoord(0.2f * mEmHeight);
-    nscoord desiredSizeAscent = aDesiredSize.ascent;
-    nscoord desiredSizeDescent = aDesiredSize.height - aDesiredSize.ascent;
+    nscoord desiredSizeAscent = aDesiredSize.TopAscent();
+    nscoord desiredSizeDescent = aDesiredSize.Height() - aDesiredSize.TopAscent();
     
     if (IsToDraw(NOTATION_LONGDIV)) {
       desiredSizeAscent = std::max(desiredSizeAscent,
                                  longdivAscent + leading);
       desiredSizeDescent = std::max(desiredSizeDescent,
                                   longdivDescent + mRuleThickness);
     }
     
     if (IsToDraw(NOTATION_RADICAL)) {
       desiredSizeAscent = std::max(desiredSizeAscent,
                                  radicalAscent + leading);
       desiredSizeDescent = std::max(desiredSizeDescent,
                                   radicalDescent + mRuleThickness);
     }
 
-    aDesiredSize.ascent = desiredSizeAscent;
-    aDesiredSize.height = desiredSizeAscent + desiredSizeDescent;
+    aDesiredSize.SetTopAscent(desiredSizeAscent);
+    aDesiredSize.Height() = desiredSizeAscent + desiredSizeDescent;
   }
     
   if (IsToDraw(NOTATION_CIRCLE) ||
       IsToDraw(NOTATION_ROUNDEDBOX) ||
       (IsToDraw(NOTATION_TOP) && IsToDraw(NOTATION_BOTTOM))) {
     // center the menclose around the content (vertically)
-    nscoord dy = std::max(aDesiredSize.ascent - bmBase.ascent,
-                        aDesiredSize.height - aDesiredSize.ascent -
+    nscoord dy = std::max(aDesiredSize.TopAscent() - bmBase.ascent,
+                        aDesiredSize.Height() - aDesiredSize.TopAscent() -
                         bmBase.descent);
 
-    aDesiredSize.ascent = bmBase.ascent + dy;
-    aDesiredSize.height = aDesiredSize.ascent + bmBase.descent + dy;
+    aDesiredSize.SetTopAscent(bmBase.ascent + dy);
+    aDesiredSize.Height() = aDesiredSize.TopAscent() + bmBase.descent + dy;
   }
 
   // Update mBoundingMetrics ascent/descent
   if (IsToDraw(NOTATION_TOP) ||
       IsToDraw(NOTATION_RIGHT) ||
       IsToDraw(NOTATION_LEFT) ||
       IsToDraw(NOTATION_UPDIAGONALSTRIKE) ||
       IsToDraw(NOTATION_UPDIAGONALARROW) ||
       IsToDraw(NOTATION_DOWNDIAGONALSTRIKE) ||
       IsToDraw(NOTATION_VERTICALSTRIKE) ||
       IsToDraw(NOTATION_CIRCLE) ||
       IsToDraw(NOTATION_ROUNDEDBOX))
-    mBoundingMetrics.ascent = aDesiredSize.ascent;
+    mBoundingMetrics.ascent = aDesiredSize.TopAscent();
   
   if (IsToDraw(NOTATION_BOTTOM) ||
       IsToDraw(NOTATION_RIGHT) ||
       IsToDraw(NOTATION_LEFT) ||
       IsToDraw(NOTATION_UPDIAGONALSTRIKE) ||
       IsToDraw(NOTATION_UPDIAGONALARROW) ||
       IsToDraw(NOTATION_DOWNDIAGONALSTRIKE) ||
       IsToDraw(NOTATION_VERTICALSTRIKE) ||
       IsToDraw(NOTATION_CIRCLE) ||
       IsToDraw(NOTATION_ROUNDEDBOX))
-    mBoundingMetrics.descent = aDesiredSize.height - aDesiredSize.ascent;
+    mBoundingMetrics.descent = aDesiredSize.Height() - aDesiredSize.TopAscent();
 
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
   
   mReference.x = 0;
-  mReference.y = aDesiredSize.ascent;
+  mReference.y = aDesiredSize.TopAscent();
 
   if (aPlaceOrigin) {
     //////////////////
     // Set position and size of MathMLChars
     if (IsToDraw(NOTATION_LONGDIV))
       mMathMLChar[mLongDivCharIndex].SetRect(nsRect(dx_left -
                                                     bmLongdivChar.width,
-                                                    aDesiredSize.ascent -
+                                                    aDesiredSize.TopAscent() -
                                                     longdivAscent,
                                                     bmLongdivChar.width,
                                                     bmLongdivChar.ascent +
                                                     bmLongdivChar.descent));
 
     if (IsToDraw(NOTATION_RADICAL)) {
       nscoord dx = (StyleVisibility()->mDirection ?
                     dx_left + bmBase.width : dx_left - bmRadicalChar.width);
 
       mMathMLChar[mRadicalCharIndex].SetRect(nsRect(dx,
-                                                    aDesiredSize.ascent -
+                                                    aDesiredSize.TopAscent() -
                                                     radicalAscent,
                                                     bmRadicalChar.width,
                                                     bmRadicalChar.ascent +
                                                     bmRadicalChar.descent));
     }
 
     mContentWidth = bmBase.width;
 
     //////////////////
     // Finish reflowing child frames
-    PositionRowChildFrames(dx_left, aDesiredSize.ascent);
+    PositionRowChildFrames(dx_left, aDesiredSize.TopAscent());
   }
 
   return NS_OK;
 }
 
 nscoord
 nsMathMLmencloseFrame::FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize)
 {
--- a/layout/mathml/nsMathMLmfencedFrame.cpp
+++ b/layout/mathml/nsMathMLmfencedFrame.cpp
@@ -194,18 +194,18 @@ nsMathMLmfencedFrame::BuildDisplayList(n
 
 NS_IMETHODIMP
 nsMathMLmfencedFrame::Reflow(nsPresContext*          aPresContext,
                              nsHTMLReflowMetrics&     aDesiredSize,
                              const nsHTMLReflowState& aReflowState,
                              nsReflowStatus&          aStatus)
 {
   nsresult rv;
-  aDesiredSize.width = aDesiredSize.height = 0;
-  aDesiredSize.ascent = 0;
+  aDesiredSize.Width() = aDesiredSize.Height() = 0;
+  aDesiredSize.SetTopAscent(0);
   aDesiredSize.mBoundingMetrics = nsBoundingMetrics();
 
   int32_t i;
   const nsStyleFont* font = StyleFont();
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
   aReflowState.rendContext->SetFont(fm);
   nscoord axisHeight, em;
@@ -234,37 +234,38 @@ nsMathMLmfencedFrame::Reflow(nsPresConte
   if (firstChild || mOpenChar || mCloseChar || mSeparatorsCount > 0) {
     // We use the ASCII metrics to get our minimum height. This way,
     // if we have borders or a background, they will fit better with
     // other elements on the line.
     ascent = fm->MaxAscent();
     descent = fm->MaxDescent();
   }
   while (childFrame) {
-    nsHTMLReflowMetrics childDesiredSize(aDesiredSize.mFlags
+    nsHTMLReflowMetrics childDesiredSize(aReflowState.GetWritingMode(),
+                                         aDesiredSize.mFlags
                                          | NS_REFLOW_CALC_BOUNDING_METRICS);
     nsHTMLReflowState childReflowState(aPresContext, aReflowState,
                                        childFrame, availSize);
     rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
                      childReflowState, childStatus);
     //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
     if (NS_FAILED(rv)) {
       // Call DidReflow() for the child frames we successfully did reflow.
       DidReflowChildren(firstChild, childFrame);
       return rv;
     }
 
     SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
                                     childDesiredSize.mBoundingMetrics);
 
-    nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent;
+    nscoord childDescent = childDesiredSize.Height() - childDesiredSize.TopAscent();
     if (descent < childDescent)
       descent = childDescent;
-    if (ascent < childDesiredSize.ascent)
-      ascent = childDesiredSize.ascent;
+    if (ascent < childDesiredSize.TopAscent())
+      ascent = childDesiredSize.TopAscent();
 
     childFrame = childFrame->GetNextSibling();
   }
 
   /////////////
   // Ask stretchy children to stretch themselves
 
   nsBoundingMetrics containerSize;
@@ -272,32 +273,32 @@ nsMathMLmfencedFrame::Reflow(nsPresConte
 
   GetPreferredStretchSize(*aReflowState.rendContext,
                           0, /* i.e., without embellishments */
                           stretchDir, containerSize);
   childFrame = firstChild;
   while (childFrame) {
     nsIMathMLFrame* mathmlChild = do_QueryFrame(childFrame);
     if (mathmlChild) {
-      nsHTMLReflowMetrics childDesiredSize;
+      nsHTMLReflowMetrics childDesiredSize(aReflowState.GetWritingMode());
       // retrieve the metrics that was stored at the previous pass
       GetReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
                                      childDesiredSize.mBoundingMetrics);
       
       mathmlChild->Stretch(*aReflowState.rendContext, 
                            stretchDir, containerSize, childDesiredSize);
       // store the updated metrics
       SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
                                       childDesiredSize.mBoundingMetrics);
       
-      nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent;
+      nscoord childDescent = childDesiredSize.Height() - childDesiredSize.TopAscent();
       if (descent < childDescent)
         descent = childDescent;
-      if (ascent < childDesiredSize.ascent)
-        ascent = childDesiredSize.ascent;
+      if (ascent < childDesiredSize.TopAscent())
+        ascent = childDesiredSize.TopAscent();
     }
     childFrame = childFrame->GetNextSibling();
   }
 
   // bug 121748: for surrounding fences & separators, use a size that covers everything
   GetPreferredStretchSize(*aReflowState.rendContext,
                           STRETCH_CONSIDER_EMBELLISHMENTS,
                           stretchDir, containerSize);
@@ -356,28 +357,28 @@ nsMathMLmfencedFrame::Reflow(nsPresConte
   }
 
   if (isRTL) {
     childFrame = this->GetLastChild(nsIFrame::kPrincipalList);
   } else {
     childFrame = firstChild;
   }
   while (childFrame) {
-    nsHTMLReflowMetrics childSize;
+    nsHTMLReflowMetrics childSize(aReflowState.GetWritingMode());
     GetReflowAndBoundingMetricsFor(childFrame, childSize, bm);
     if (firstTime) {
       firstTime = false;
       aDesiredSize.mBoundingMetrics  = bm;
     }
     else  
       aDesiredSize.mBoundingMetrics += bm;
 
     FinishReflowChild(childFrame, aPresContext, nullptr, childSize, 
-                      dx, ascent - childSize.ascent, 0);
-    dx += childSize.width;
+                      dx, ascent - childSize.TopAscent(), 0);
+    dx += childSize.Width();
 
     if (i < mSeparatorsCount) {
       PlaceChar(&mSeparatorsChar[isRTL ? mSeparatorsCount - 1 - i : i],
                 ascent, bm, dx);
       aDesiredSize.mBoundingMetrics += bm;
     }
     i++;
 
@@ -391,22 +392,22 @@ nsMathMLmfencedFrame::Reflow(nsPresConte
   if (rightChar) {
     PlaceChar(rightChar, ascent, bm, dx);
     if (firstTime)
       aDesiredSize.mBoundingMetrics  = bm;
     else  
       aDesiredSize.mBoundingMetrics += bm;
   }
 
-  aDesiredSize.width = aDesiredSize.mBoundingMetrics.width;
-  aDesiredSize.height = ascent + descent;
-  aDesiredSize.ascent = ascent;
+  aDesiredSize.Width() = aDesiredSize.mBoundingMetrics.width;
+  aDesiredSize.Height() = ascent + descent;
+  aDesiredSize.SetTopAscent(ascent);
 
   SetBoundingMetrics(aDesiredSize.mBoundingMetrics);
-  SetReference(nsPoint(0, aDesiredSize.ascent));
+  SetReference(nsPoint(0, aDesiredSize.TopAscent()));
 
   // see if we should fix the spacing
   FixInterFrameSpacing(aDesiredSize);
 
   // Finished with these:
   ClearSavedChildMetrics();
 
   // Set our overflow area
@@ -602,17 +603,17 @@ nsMathMLmfencedFrame::GetIntrinsicWidthM
   }
 
   if (mCloseChar) {
     width +=
       GetMaxCharWidth(presContext, aRenderingContext, mCloseChar,
                       NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel, em);
   }
 
-  aDesiredSize.width = width;
+  aDesiredSize.Width() = width;
   aDesiredSize.mBoundingMetrics.width = width;
   aDesiredSize.mBoundingMetrics.leftBearing = 0;
   aDesiredSize.mBoundingMetrics.rightBearing = width;
 }
 
 nscoord
 nsMathMLmfencedFrame::FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize)
 {
--- a/layout/mathml/nsMathMLmfracFrame.cpp
+++ b/layout/mathml/nsMathMLmfracFrame.cpp
@@ -180,18 +180,18 @@ nsresult
 nsMathMLmfracFrame::PlaceInternal(nsRenderingContext& aRenderingContext,
                                   bool                 aPlaceOrigin,
                                   nsHTMLReflowMetrics& aDesiredSize,
                                   bool                 aWidthOnly)
 {
   ////////////////////////////////////
   // Get the children's desired sizes
   nsBoundingMetrics bmNum, bmDen;
-  nsHTMLReflowMetrics sizeNum;
-  nsHTMLReflowMetrics sizeDen;
+  nsHTMLReflowMetrics sizeNum(aDesiredSize.GetWritingMode());
+  nsHTMLReflowMetrics sizeDen(aDesiredSize.GetWritingMode());
   nsIFrame* frameDen = nullptr;
   nsIFrame* frameNum = mFrames.FirstChild();
   if (frameNum) 
     frameDen = frameNum->GetNextSibling();
   if (!frameNum || !frameDen || frameDen->GetNextSibling()) {
     // report an error, encourage people to get their markups in order
     if (aPlaceOrigin) {
       ReportChildCountError();
@@ -314,67 +314,67 @@ nsMathMLmfracFrame::PlaceInternal(nsRend
     }
 
     //////////////////
     // Place Children
 
     // XXX Need revisiting the width. TeX uses the exact width
     // e.g. in $$\huge\frac{\displaystyle\int}{i}$$
     nscoord width = std::max(bmNum.width, bmDen.width);
-    nscoord dxNum = leftSpace + (width - sizeNum.width)/2;
-    nscoord dxDen = leftSpace + (width - sizeDen.width)/2;
+    nscoord dxNum = leftSpace + (width - sizeNum.Width())/2;
+    nscoord dxDen = leftSpace + (width - sizeDen.Width())/2;
     width += leftSpace + rightSpace;
 
     // see if the numalign attribute is there 
     GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::numalign_,
                  value);
     if (value.EqualsLiteral("left"))
       dxNum = leftSpace;
     else if (value.EqualsLiteral("right"))
-      dxNum = width - rightSpace - sizeNum.width;
+      dxNum = width - rightSpace - sizeNum.Width();
 
     // see if the denomalign attribute is there 
     GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::denomalign_,
                  value);
     if (value.EqualsLiteral("left"))
       dxDen = leftSpace;
     else if (value.EqualsLiteral("right"))
-      dxDen = width - rightSpace - sizeDen.width;
+      dxDen = width - rightSpace - sizeDen.Width();
 
     mBoundingMetrics.rightBearing =
       std::max(dxNum + bmNum.rightBearing, dxDen + bmDen.rightBearing);
     if (mBoundingMetrics.rightBearing < width - rightSpace)
       mBoundingMetrics.rightBearing = width - rightSpace;
     mBoundingMetrics.leftBearing =
       std::min(dxNum + bmNum.leftBearing, dxDen + bmDen.leftBearing);
     if (mBoundingMetrics.leftBearing > leftSpace)
       mBoundingMetrics.leftBearing = leftSpace;
     mBoundingMetrics.ascent = bmNum.ascent + numShift;
     mBoundingMetrics.descent = bmDen.descent + denShift;
     mBoundingMetrics.width = width;
 
-    aDesiredSize.ascent = sizeNum.ascent + numShift;
-    aDesiredSize.height = aDesiredSize.ascent +
-      sizeDen.height - sizeDen.ascent + denShift;
-    aDesiredSize.width = mBoundingMetrics.width;
+    aDesiredSize.SetTopAscent(sizeNum.TopAscent() + numShift);
+    aDesiredSize.Height() = aDesiredSize.TopAscent() +
+      sizeDen.Height() - sizeDen.TopAscent() + denShift;
+    aDesiredSize.Width() = mBoundingMetrics.width;
     aDesiredSize.mBoundingMetrics = mBoundingMetrics;
 
     mReference.x = 0;
-    mReference.y = aDesiredSize.ascent;
+    mReference.y = aDesiredSize.TopAscent();
 
     if (aPlaceOrigin) {
       nscoord dy;
       // place numerator
       dy = 0;
       FinishReflowChild(frameNum, presContext, nullptr, sizeNum, dxNum, dy, 0);
       // place denominator
-      dy = aDesiredSize.height - sizeDen.height;
+      dy = aDesiredSize.Height() - sizeDen.Height();
       FinishReflowChild(frameDen, presContext, nullptr, sizeDen, dxDen, dy, 0);
       // place the fraction bar - dy is top of bar
-      dy = aDesiredSize.ascent - (axisHeight + actualRuleThickness/2);
+      dy = aDesiredSize.TopAscent() - (axisHeight + actualRuleThickness/2);
       mLineRect.SetRect(leftSpace, dy, width - (leftSpace + rightSpace),
                         actualRuleThickness);
     }
   } else {
     nscoord numShift = 0.0;
     nscoord denShift = 0.0;
     nscoord padding = 3 * defaultRuleThickness;
     nscoord slashRatio = 3;
@@ -457,45 +457,45 @@ nsMathMLmfracFrame::PlaceInternal(nsRend
       mBoundingMetrics.leftBearing = leadingSpace + bmNum.leftBearing;
       mBoundingMetrics.rightBearing = leadingSpace + bmNum.width + mLineRect.width + bmDen.rightBearing;
     }
     mBoundingMetrics.width =
       leadingSpace + bmNum.width + mLineRect.width + bmDen.width +
       trailingSpace;
 
     // Set aDesiredSize
-    aDesiredSize.ascent = mBoundingMetrics.ascent + padding;
-    aDesiredSize.height =
+    aDesiredSize.SetTopAscent(mBoundingMetrics.ascent + padding);
+    aDesiredSize.Height() =
       mBoundingMetrics.ascent + mBoundingMetrics.descent + 2 * padding;
-    aDesiredSize.width = mBoundingMetrics.width;
+    aDesiredSize.Width() = mBoundingMetrics.width;
     aDesiredSize.mBoundingMetrics = mBoundingMetrics;
 
     mReference.x = 0;
-    mReference.y = aDesiredSize.ascent;
+    mReference.y = aDesiredSize.TopAscent();
     
     if (aPlaceOrigin) {
       nscoord dx, dy;
 
       // place numerator
-      dx = MirrorIfRTL(aDesiredSize.width, sizeNum.width,
+      dx = MirrorIfRTL(aDesiredSize.Width(), sizeNum.Width(),
                        leadingSpace);
-      dy = aDesiredSize.ascent - numShift - sizeNum.ascent;
+      dy = aDesiredSize.TopAscent() - numShift - sizeNum.TopAscent();
       FinishReflowChild(frameNum, presContext, nullptr, sizeNum, dx, dy, 0);
 
       // place the fraction bar
-      dx = MirrorIfRTL(aDesiredSize.width, mLineRect.width,
+      dx = MirrorIfRTL(aDesiredSize.Width(), mLineRect.width,
                        leadingSpace + bmNum.width);
-      dy = aDesiredSize.ascent - mBoundingMetrics.ascent;
+      dy = aDesiredSize.TopAscent() - mBoundingMetrics.ascent;
       mLineRect.SetRect(dx, dy,
-                        mLineRect.width, aDesiredSize.height - 2 * padding);
+                        mLineRect.width, aDesiredSize.Height() - 2 * padding);
 
       // place denominator
-      dx = MirrorIfRTL(aDesiredSize.width, sizeDen.width,
+      dx = MirrorIfRTL(aDesiredSize.Width(), sizeDen.Width(),
                        leadingSpace + bmNum.width + mLineRect.width);
-      dy = aDesiredSize.ascent + denShift - sizeDen.ascent;
+      dy = aDesiredSize.TopAscent() + denShift - sizeDen.TopAscent();
       FinishReflowChild(frameDen, presContext, nullptr, sizeDen, dx, dy, 0);
     }
 
   }
 
   return NS_OK;
 }
 
--- a/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
+++ b/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
@@ -4,16 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "nsMathMLmmultiscriptsFrame.h"
 #include "nsPresContext.h"
 #include "nsRenderingContext.h"
 #include <algorithm>
 
+using mozilla::WritingMode;
+
 //
 // <mmultiscripts> -- attach prescripts and tensor indices to a base - implementation
 // <msub> -- attach a subscript to a base - implementation
 // <msubsup> -- attach a subscript-superscript pair to a base - implementation
 // <msup> -- attach a superscript to a base - implementation
 //
 
 nsIFrame*
@@ -157,17 +159,16 @@ nsMathMLmmultiscriptsFrame::PlaceMultiSc
   if (tag == nsGkAtoms::mover_)
     tag = nsGkAtoms::msup_;
   else if (tag == nsGkAtoms::munder_)
     tag = nsGkAtoms::msub_;
   else if (tag  == nsGkAtoms::munderover_)
     tag = nsGkAtoms::msubsup_;
 
   nsBoundingMetrics bmFrame;
-  nsHTMLReflowMetrics frameSize;
 
   nscoord minShiftFromXHeight, subDrop, supDrop;
 
   ////////////////////////////////////////
   // Initialize super/sub shifts that
   // depend only on the current font
   ////////////////////////////////////////
 
@@ -254,42 +255,44 @@ nsMathMLmmultiscriptsFrame::PlaceMultiSc
     // the user has set the supscriptshift attribute
     supScriptShift = std::max(supScriptShift, aUserSupScriptShift);
   }
 
   ////////////////////////////////////
   // Get the children's sizes
   ////////////////////////////////////
 
+  const WritingMode wm(aDesiredSize.GetWritingMode());
   nscoord width = 0, prescriptsWidth = 0, rightBearing = 0;
   nscoord minSubScriptShift = 0, minSupScriptShift = 0;
   nscoord trySubScriptShift = subScriptShift;
   nscoord trySupScriptShift = supScriptShift;
   nscoord maxSubScriptShift = subScriptShift;
   nscoord maxSupScriptShift = supScriptShift;
-  nsHTMLReflowMetrics baseSize;
-  nsHTMLReflowMetrics subScriptSize;
-  nsHTMLReflowMetrics supScriptSize;
-  nsHTMLReflowMetrics multiSubSize, multiSupSize;
+  nsHTMLReflowMetrics baseSize(wm);
+  nsHTMLReflowMetrics subScriptSize(wm);
+  nsHTMLReflowMetrics supScriptSize(wm);
+  nsHTMLReflowMetrics multiSubSize(wm), multiSupSize(wm);
   baseFrame = nullptr;
   nsIFrame* subScriptFrame = nullptr;
   nsIFrame* supScriptFrame = nullptr;
   nsIFrame* prescriptsFrame = nullptr; // frame of <mprescripts/>, if there.
 
   bool firstPrescriptsPair = false;
   nsBoundingMetrics bmBase, bmSubScript, bmSupScript, bmMultiSub, bmMultiSup;
-  multiSubSize.ascent = multiSupSize.ascent = -0x7FFFFFFF;
+  multiSubSize.SetTopAscent(-0x7FFFFFFF);
+  multiSupSize.SetTopAscent(-0x7FFFFFFF);
   bmMultiSub.ascent = bmMultiSup.ascent = -0x7FFFFFFF;
   bmMultiSub.descent = bmMultiSup.descent = -0x7FFFFFFF;
   nscoord italicCorrection = 0;
 
   nsBoundingMetrics boundingMetrics;
   boundingMetrics.width = 0;
   boundingMetrics.ascent = boundingMetrics.descent = -0x7FFFFFFF;
-  aDesiredSize.width = aDesiredSize.height = 0;
+  aDesiredSize.Width() = aDesiredSize.Height() = 0;
 
   int32_t count = 0;
   bool foundNoneTag = false;
 
   // Boolean to determine whether the current child is a subscript.
   // Note that only msup starts with a superscript.
   bool isSubScript = (tag != nsGkAtoms::msup_);
 
@@ -363,23 +366,23 @@ nsMathMLmmultiscriptsFrame::PlaceMultiSc
         // subscript
         subScriptFrame = childFrame;
         GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript);
         // get the subdrop from the subscript font
         GetSubDropFromChild (subScriptFrame, subDrop);
         // parameter v, Rule 18a, App. G, TeXbook
         minSubScriptShift = bmBase.descent + subDrop;
         trySubScriptShift = std::max(minSubScriptShift,subScriptShift);
-        multiSubSize.ascent = std::max(multiSubSize.ascent,
-                                       subScriptSize.ascent);
+        multiSubSize.SetTopAscent(std::max(multiSubSize.TopAscent(),
+                                       subScriptSize.TopAscent()));
         bmMultiSub.ascent = std::max(bmMultiSub.ascent, bmSubScript.ascent);
         bmMultiSub.descent = std::max(bmMultiSub.descent, bmSubScript.descent);
-        multiSubSize.height = 
-          std::max(multiSubSize.height,
-                   subScriptSize.height - subScriptSize.ascent);
+        multiSubSize.Height() = 
+          std::max(multiSubSize.Height(),
+                   subScriptSize.Height() - subScriptSize.TopAscent());
         if (bmSubScript.width)
           width = bmSubScript.width + aScriptSpace;
         rightBearing = bmSubScript.rightBearing;
 
         if (tag == nsGkAtoms::msub_) {
           boundingMetrics.rightBearing = boundingMetrics.width + rightBearing;
           boundingMetrics.width += width;
 
@@ -402,23 +405,23 @@ nsMathMLmmultiscriptsFrame::PlaceMultiSc
         minSupScriptShift = bmBase.ascent - supDrop;
         // get min supscript shift limit from x-height
         // = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook
         minShiftFromXHeight = NSToCoordRound
           ((bmSupScript.descent + (1.0f/4.0f) * xHeight));
         trySupScriptShift = std::max(minSupScriptShift,
                                      std::max(minShiftFromXHeight,
                                               supScriptShift));
-        multiSupSize.ascent = std::max(multiSupSize.ascent,
-                                       supScriptSize.ascent);
+        multiSupSize.SetTopAscent(std::max(multiSupSize.TopAscent(),
+                                       supScriptSize.TopAscent()));
         bmMultiSup.ascent = std::max(bmMultiSup.ascent, bmSupScript.ascent);
         bmMultiSup.descent = std::max(bmMultiSup.descent, bmSupScript.descent);
-        multiSupSize.height = 
-          std::max(multiSupSize.height,
-                   supScriptSize.height - supScriptSize.ascent);
+        multiSupSize.Height() = 
+          std::max(multiSupSize.Height(),
+                   supScriptSize.Height() - supScriptSize.TopAscent());
 
         if (bmSupScript.width)
           width = std::max(width, bmSupScript.width + aScriptSpace);
         rightBearing = std::max(rightBearing, bmSupScript.rightBearing);
 
         if (!prescriptsFrame) { // we are still looping over base & postscripts
           boundingMetrics.rightBearing = boundingMetrics.width + rightBearing;
           boundingMetrics.width += width;
@@ -514,28 +517,28 @@ nsMathMLmmultiscriptsFrame::PlaceMultiSc
                                        bmMultiSup.descent - maxSupScriptShift);
   } else {
     boundingMetrics.descent =
       std::max(bmBase.descent, (bmMultiSub.descent + maxSubScriptShift));
   }
   aFrame->SetBoundingMetrics(boundingMetrics);
 
   // get the reflow metrics ...
-  aDesiredSize.ascent = 
-    std::max(baseSize.ascent, 
-             std::max(multiSubSize.ascent - maxSubScriptShift,
-                      multiSupSize.ascent + maxSupScriptShift));
-  aDesiredSize.height = aDesiredSize.ascent +
-    std::max(baseSize.height - baseSize.ascent,
-             std::max(multiSubSize.height + maxSubScriptShift,
-                      multiSupSize.height - maxSupScriptShift));
-  aDesiredSize.width = boundingMetrics.width;
+  aDesiredSize.SetTopAscent( 
+    std::max(baseSize.TopAscent(), 
+             std::max(multiSubSize.TopAscent() - maxSubScriptShift,
+                      multiSupSize.TopAscent() + maxSupScriptShift)));
+  aDesiredSize.Height() = aDesiredSize.TopAscent() +
+    std::max(baseSize.Height() - baseSize.TopAscent(),
+             std::max(multiSubSize.Height() + maxSubScriptShift,
+                      multiSupSize.Height() - maxSupScriptShift));
+  aDesiredSize.Width() = boundingMetrics.width;
   aDesiredSize.mBoundingMetrics = boundingMetrics;
 
-  aFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
+  aFrame->SetReference(nsPoint(0, aDesiredSize.TopAscent()));
 
   //////////////////
   // Place Children
 
   // Place prescripts, followed by base, and then postscripts.
   // The list of frames is in the order: {base} {postscripts} {prescripts}
   // We go over the list in a circular manner, starting at <prescripts/>
 
@@ -551,20 +554,20 @@ nsMathMLmmultiscriptsFrame::PlaceMultiSc
       count = 0;
     childFrame = prescriptsFrame;
     bool isPreScript = true;
     do {
       if (!childFrame) { // end of prescripts,
         isPreScript = false;
         // place the base ...
         childFrame = baseFrame;
-        dy = aDesiredSize.ascent - baseSize.ascent;
+        dy = aDesiredSize.TopAscent() - baseSize.TopAscent();
         FinishReflowChild (baseFrame, aPresContext, nullptr, baseSize,
-                           aFrame->MirrorIfRTL(aDesiredSize.width,
-                                               baseSize.width,
+                           aFrame->MirrorIfRTL(aDesiredSize.Width(),
+                                               baseSize.Width(),
                                                dx),
                            dy, 0);
         dx += bmBase.width + italicCorrection;
       } else if (prescriptsFrame != childFrame) {
         // process each sup/sub pair
         if (0 == count) {
           subScriptFrame = childFrame;
           count = 1;
@@ -575,44 +578,44 @@ nsMathMLmmultiscriptsFrame::PlaceMultiSc
 
           // get the ascent/descent of sup/subscripts stored in their rects
           // rect.x = descent, rect.y = ascent
           if (subScriptFrame)
             GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript);
           if (supScriptFrame)
             GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript);
 
-          width = std::max(subScriptSize.width, supScriptSize.width);
+          width = std::max(subScriptSize.Width(), supScriptSize.Width());
 
           if (subScriptFrame) {
             nscoord x = dx;
             // prescripts should be right aligned
             // https://bugzilla.mozilla.org/show_bug.cgi?id=928675
             if (isPreScript)
-              x += width - subScriptSize.width;
-            dy = aDesiredSize.ascent - subScriptSize.ascent +
+              x += width - subScriptSize.Width();
+            dy = aDesiredSize.TopAscent() - subScriptSize.TopAscent() +
               maxSubScriptShift;
             FinishReflowChild (subScriptFrame, aPresContext, nullptr,
                                subScriptSize,
-                               aFrame->MirrorIfRTL(aDesiredSize.width,
-                                                   subScriptSize.width,
+                               aFrame->MirrorIfRTL(aDesiredSize.Width(),
+                                                   subScriptSize.Width(),
                                                    x),
                                dy, 0);
           }
 
           if (supScriptFrame) {
             nscoord x = dx;
             if (isPreScript)
-              x += width - supScriptSize.width;
-            dy = aDesiredSize.ascent - supScriptSize.ascent -
+              x += width - supScriptSize.Width();
+            dy = aDesiredSize.TopAscent() - supScriptSize.TopAscent() -
               maxSupScriptShift;
             FinishReflowChild (supScriptFrame, aPresContext, nullptr,
                                supScriptSize,
-                               aFrame->MirrorIfRTL(aDesiredSize.width,
-                                                   supScriptSize.width,
+                               aFrame->MirrorIfRTL(aDesiredSize.Width(),
+                                                   supScriptSize.Width(),
                                                    x),
                                dy, 0);
           }
           dx += width + aScriptSpace;
         }
       }
       childFrame = childFrame->GetNextSibling();
     } while (prescriptsFrame != childFrame);
--- a/layout/mathml/nsMathMLmoFrame.cpp
+++ b/layout/mathml/nsMathMLmoFrame.cpp
@@ -823,36 +823,36 @@ nsMathMLmoFrame::Stretch(nsRenderingCont
     GetEmbellishDataFrom(mParent, parentData);
     isAccent =
        (NS_MATHML_EMBELLISH_IS_ACCENTOVER(parentData.flags) ||
         NS_MATHML_EMBELLISH_IS_ACCENTUNDER(parentData.flags)) &&
        parentData.coreFrame != this;
   }
   if (isAccent && firstChild) {
     // see bug 188467 for what is going on here
-    nscoord dy = aDesiredStretchSize.ascent - (mBoundingMetrics.ascent + leading);
-    aDesiredStretchSize.ascent = mBoundingMetrics.ascent + leading;
-    aDesiredStretchSize.height = aDesiredStretchSize.ascent + mBoundingMetrics.descent;
+    nscoord dy = aDesiredStretchSize.TopAscent() - (mBoundingMetrics.ascent + leading);
+    aDesiredStretchSize.SetTopAscent(mBoundingMetrics.ascent + leading);
+    aDesiredStretchSize.Height() = aDesiredStretchSize.TopAscent() + mBoundingMetrics.descent;
 
     firstChild->SetPosition(firstChild->GetPosition() - nsPoint(0, dy));
   }
   else if (useMathMLChar) {
     nscoord ascent = fm->MaxAscent();
     nscoord descent = fm->MaxDescent();
-    aDesiredStretchSize.ascent = std::max(mBoundingMetrics.ascent + leading, ascent);
-    aDesiredStretchSize.height = aDesiredStretchSize.ascent +
+    aDesiredStretchSize.SetTopAscent(std::max(mBoundingMetrics.ascent + leading, ascent));
+    aDesiredStretchSize.Height() = aDesiredStretchSize.TopAscent() +
                                  std::max(mBoundingMetrics.descent + leading, descent);
   }
-  aDesiredStretchSize.width = mBoundingMetrics.width;
+  aDesiredStretchSize.Width() = mBoundingMetrics.width;
   aDesiredStretchSize.mBoundingMetrics = mBoundingMetrics;
   mReference.x = 0;
-  mReference.y = aDesiredStretchSize.ascent;
+  mReference.y = aDesiredStretchSize.TopAscent();
   // Place our mMathMLChar, its origin is in our coordinate system
   if (useMathMLChar) {
-    nscoord dy = aDesiredStretchSize.ascent - mBoundingMetrics.ascent;
+    nscoord dy = aDesiredStretchSize.TopAscent() - mBoundingMetrics.ascent;
     mMathMLChar.SetRect(nsRect(0, dy, charSize.width, charSize.ascent + charSize.descent));
   }
 
   // Before we leave... there is a last item in the check-list:
   // If our parent is not embellished, it means we are the outermost embellished
   // container and so we put the spacing, otherwise we don't include the spacing,
   // the outermost embellished container will take care of it.
 
@@ -864,17 +864,17 @@ nsMathMLmoFrame::Stretch(nsRenderingCont
       leadingSpace = 0;
     }
     nscoord trailingSpace = mEmbellishData.trailingSpace;
     if (isAccent && !NS_MATHML_OPERATOR_HAS_RSPACE_ATTR(mFlags)) {
       trailingSpace = 0;
     }
 
     mBoundingMetrics.width += leadingSpace + trailingSpace;
-    aDesiredStretchSize.width = mBoundingMetrics.width;
+    aDesiredStretchSize.Width() = mBoundingMetrics.width;
     aDesiredStretchSize.mBoundingMetrics.width = mBoundingMetrics.width;
 
     nscoord dx = (StyleVisibility()->mDirection ?
                   trailingSpace : leadingSpace);
     if (dx) {
       // adjust the offsets
       mBoundingMetrics.leftBearing += dx;
       mBoundingMetrics.rightBearing += dx;
@@ -956,19 +956,19 @@ nsMathMLmoFrame::Reflow(nsPresContext*  
   ProcessOperatorData();
 
   // play safe by not passing invisible operators to the font subsystem because
   // some platforms risk selecting strange glyphs for them and give bad inter-space
   if (NS_MATHML_OPERATOR_IS_INVISIBLE(mFlags)) {
     // return empty space for now, but this is not yet final since there
     // can be lspace and rspace attributes that reclaim some room.
     // These will be dealt with later in Stretch().
-    aDesiredSize.width = 0;
-    aDesiredSize.height = 0;
-    aDesiredSize.ascent = 0;
+    aDesiredSize.Width() = 0;
+    aDesiredSize.Height() = 0;
+    aDesiredSize.SetTopAscent(0);
     aDesiredSize.mBoundingMetrics = nsBoundingMetrics();
     aStatus = NS_FRAME_COMPLETE;
 
     NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
     return NS_OK;
   }
 
   return nsMathMLTokenFrame::Reflow(aPresContext, aDesiredSize,
@@ -1001,33 +1001,33 @@ nsMathMLmoFrame::MarkIntrinsicWidthsDirt
 }
 
 /* virtual */ void
 nsMathMLmoFrame::GetIntrinsicWidthMetrics(nsRenderingContext *aRenderingContext, nsHTMLReflowMetrics& aDesiredSize)
 {
   ProcessOperatorData();
   if (UseMathMLChar()) {
     uint32_t stretchHint = GetStretchHint(mFlags, mPresentationData, true);
-    aDesiredSize.width = mMathMLChar.
+    aDesiredSize.Width() = mMathMLChar.
       GetMaxWidth(PresContext(), *aRenderingContext,
                   stretchHint, mMaxSize,
                   NS_MATHML_OPERATOR_MAXSIZE_IS_ABSOLUTE(mFlags));
   }
   else {
     nsMathMLTokenFrame::GetIntrinsicWidthMetrics(aRenderingContext,
                                                  aDesiredSize);
   }
 
   // leadingSpace and trailingSpace are actually applied to the outermost
   // embellished container but for determining total intrinsic width it should
   // be safe to include it for the core here instead.
   bool isRTL = StyleVisibility()->mDirection;
-  aDesiredSize.width +=
+  aDesiredSize.Width() +=
     mEmbellishData.leadingSpace + mEmbellishData.trailingSpace;
-  aDesiredSize.mBoundingMetrics.width = aDesiredSize.width;
+  aDesiredSize.mBoundingMetrics.width = aDesiredSize.Width();
   if (isRTL) {
     aDesiredSize.mBoundingMetrics.leftBearing += mEmbellishData.trailingSpace;
     aDesiredSize.mBoundingMetrics.rightBearing += mEmbellishData.trailingSpace;
   } else {
     aDesiredSize.mBoundingMetrics.leftBearing += mEmbellishData.leadingSpace;
     aDesiredSize.mBoundingMetrics.rightBearing += mEmbellishData.leadingSpace;
   }
 }
--- a/layout/mathml/nsMathMLmpaddedFrame.cpp
+++ b/layout/mathml/nsMathMLmpaddedFrame.cpp
@@ -271,25 +271,25 @@ nsMathMLmpaddedFrame::UpdateValue(int32_
 {
   nsCSSUnit unit = aCSSValue.GetUnit();
   if (NS_MATHML_SIGN_INVALID != aSign && eCSSUnit_Null != unit) {
     nscoord scaler = 0, amount = 0;
 
     if (eCSSUnit_Percent == unit || eCSSUnit_Number == unit) {
       switch(aPseudoUnit) {
         case NS_MATHML_PSEUDO_UNIT_WIDTH:
-             scaler = aDesiredSize.width;
+             scaler = aDesiredSize.Width();
              break;
 
         case NS_MATHML_PSEUDO_UNIT_HEIGHT:
-             scaler = aDesiredSize.ascent;
+             scaler = aDesiredSize.TopAscent();
              break;
 
         case NS_MATHML_PSEUDO_UNIT_DEPTH:
-             scaler = aDesiredSize.height - aDesiredSize.ascent;
+             scaler = aDesiredSize.Height() - aDesiredSize.TopAscent();
              break;
 
         default:
           // if we ever reach here, it would mean something is wrong 
           // somewhere with the setup and/or the caller
           NS_ERROR("Unexpected Pseudo Unit");
           return;
       }
@@ -334,18 +334,18 @@ nsMathMLmpaddedFrame::Place(nsRenderingC
 {
   nsresult rv =
     nsMathMLContainerFrame::Place(aRenderingContext, false, aDesiredSize);
   if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
     DidReflowChildren(GetFirstPrincipalChild());
     return rv;
   }
 
-  nscoord height = aDesiredSize.ascent;
-  nscoord depth  = aDesiredSize.height - aDesiredSize.ascent;
+  nscoord height = aDesiredSize.TopAscent();
+  nscoord depth  = aDesiredSize.Height() - aDesiredSize.TopAscent();
   // The REC says:
   //
   // "The lspace attribute ('leading' space) specifies the horizontal location
   // of the positioning point of the child content with respect to the
   // positioning point of the mpadded element. By default they coincide, and
   // therefore absolute values for lspace have the same effect as relative
   // values."
   //
@@ -361,17 +361,17 @@ nsMathMLmpaddedFrame::Place(nsRenderingC
   // a side of an object when which side to use depends on the directionality;
   // ie. leading means left in LTR but right in RTL."
   // (http://www.w3.org/TR/MathML/chapter3.html#presm.bidi.math)
   nscoord lspace = 0;
   // In MathML3, "width" will be the bounding box width and "advancewidth" will
   // refer "to the horizontal distance between the positioning point of the
   // mpadded and the positioning point for the following content".  MathML2
   // doesn't make the distinction.
-  nscoord width  = aDesiredSize.width;
+  nscoord width  = aDesiredSize.Width();
   nscoord voffset = 0;
 
   int32_t pseudoUnit;
   nscoord initialWidth = width;
 
   // update width
   pseudoUnit = (mWidthPseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF)
              ? NS_MATHML_PSEUDO_UNIT_WIDTH : mWidthPseudoUnit;
@@ -425,29 +425,29 @@ nsMathMLmpaddedFrame::Place(nsRenderingC
     // (so that our parent won't correct us)
     mBoundingMetrics.width = width;
     mBoundingMetrics.rightBearing = mBoundingMetrics.width;
   }
 
   nscoord dx = (StyleVisibility()->mDirection ?
                 width - initialWidth - lspace : lspace);
     
-  aDesiredSize.ascent = height;
-  aDesiredSize.width = mBoundingMetrics.width;
-  aDesiredSize.height = depth + aDesiredSize.ascent;
+  aDesiredSize.SetTopAscent(height);
+  aDesiredSize.Width() = mBoundingMetrics.width;
+  aDesiredSize.Height() = depth + aDesiredSize.TopAscent();
   mBoundingMetrics.ascent = height;
   mBoundingMetrics.descent = depth;
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
 
   mReference.x = 0;
-  mReference.y = aDesiredSize.ascent;
+  mReference.y = aDesiredSize.TopAscent();
 
   if (aPlaceOrigin) {
     // Finish reflowing child frames, positioning their origins.
-    PositionRowChildFrames(dx, aDesiredSize.ascent - voffset);
+    PositionRowChildFrames(dx, aDesiredSize.TopAscent() - voffset);
   }
 
   return NS_OK;
 }
 
 /* virtual */ nsresult
 nsMathMLmpaddedFrame::MeasureForWidth(nsRenderingContext& aRenderingContext,
                                       nsHTMLReflowMetrics& aDesiredSize)
--- a/layout/mathml/nsMathMLmrootFrame.cpp
+++ b/layout/mathml/nsMathMLmrootFrame.cpp
@@ -147,34 +147,35 @@ nsMathMLmrootFrame::Reflow(nsPresContext
                            nsHTMLReflowMetrics&     aDesiredSize,
                            const nsHTMLReflowState& aReflowState,
                            nsReflowStatus&          aStatus)
 {
   nsresult rv = NS_OK;
   nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE);
   nsReflowStatus childStatus;
 
-  aDesiredSize.width = aDesiredSize.height = 0;
-  aDesiredSize.ascent = 0;
+  aDesiredSize.Width() = aDesiredSize.Height() = 0;
+  aDesiredSize.SetTopAscent(0);
 
   nsBoundingMetrics bmSqr, bmBase, bmIndex;
   nsRenderingContext& renderingContext = *aReflowState.rendContext;
 
   //////////////////
   // Reflow Children
 
   int32_t count = 0;
   nsIFrame* baseFrame = nullptr;
   nsIFrame* indexFrame = nullptr;
-  nsHTMLReflowMetrics baseSize;
-  nsHTMLReflowMetrics indexSize;
+  nsHTMLReflowMetrics baseSize(aReflowState.GetWritingMode());
+  nsHTMLReflowMetrics indexSize(aReflowState.GetWritingMode());
   nsIFrame* childFrame = mFrames.FirstChild();
   while (childFrame) {
     // ask our children to compute their bounding metrics 
-    nsHTMLReflowMetrics childDesiredSize(aDesiredSize.mFlags
+    nsHTMLReflowMetrics childDesiredSize(aReflowState.GetWritingMode(),
+                                         aDesiredSize.mFlags
                                          | NS_REFLOW_CALC_BOUNDING_METRICS);
     nsHTMLReflowState childReflowState(aPresContext, aReflowState,
                                        childFrame, availSize);
     rv = ReflowChild(childFrame, aPresContext,
                      childDesiredSize, childReflowState, childStatus);
     //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
     if (NS_FAILED(rv)) {
       // Call DidReflow() for the child frames we successfully did reflow.
@@ -276,79 +277,79 @@ nsMathMLmrootFrame::Reflow(nsPresContext
   mBoundingMetrics.descent = 
     std::max(bmBase.descent,
            (bmSqr.ascent + bmSqr.descent - mBoundingMetrics.ascent));
   mBoundingMetrics.width = bmSqr.width + bmBase.width;
   mBoundingMetrics.leftBearing = bmSqr.leftBearing;
   mBoundingMetrics.rightBearing = bmSqr.width + 
     std::max(bmBase.width, bmBase.rightBearing); // take also care of the rule
 
-  aDesiredSize.ascent = mBoundingMetrics.ascent + leading;
-  aDesiredSize.height = aDesiredSize.ascent +
-    std::max(baseSize.height - baseSize.ascent,
+  aDesiredSize.SetTopAscent(mBoundingMetrics.ascent + leading);
+  aDesiredSize.Height() = aDesiredSize.TopAscent() +
+    std::max(baseSize.Height() - baseSize.TopAscent(),
            mBoundingMetrics.descent + ruleThickness);
-  aDesiredSize.width = mBoundingMetrics.width;
+  aDesiredSize.Width() = mBoundingMetrics.width;
 
   /////////////
   // Re-adjust the desired size to include the index.
   
   // the index is raised by some fraction of the height
   // of the radical, see \mroot macro in App. B, TexBook
   nscoord raiseIndexDelta = NSToCoordRound(0.6f * (bmSqr.ascent + bmSqr.descent));
   nscoord indexRaisedAscent = mBoundingMetrics.ascent // top of radical 
     - (bmSqr.ascent + bmSqr.descent) // to bottom of radical
     + raiseIndexDelta + bmIndex.ascent + bmIndex.descent; // to top of raised index
 
   nscoord indexClearance = 0;
   if (mBoundingMetrics.ascent < indexRaisedAscent) {
     indexClearance = 
       indexRaisedAscent - mBoundingMetrics.ascent; // excess gap introduced by a tall index 
     mBoundingMetrics.ascent = indexRaisedAscent;
-    nscoord descent = aDesiredSize.height - aDesiredSize.ascent;
-    aDesiredSize.ascent = mBoundingMetrics.ascent + leading;
-    aDesiredSize.height = aDesiredSize.ascent + descent;
+    nscoord descent = aDesiredSize.Height() - aDesiredSize.TopAscent();
+    aDesiredSize.SetTopAscent(mBoundingMetrics.ascent + leading);
+    aDesiredSize.Height() = aDesiredSize.TopAscent() + descent;
   }
 
   nscoord dxIndex, dxSqr;
   GetRadicalXOffsets(bmIndex.width, bmSqr.width, fm, &dxIndex, &dxSqr);
 
   mBoundingMetrics.width = dxSqr + bmSqr.width + bmBase.width;
   mBoundingMetrics.leftBearing = 
     std::min(dxIndex + bmIndex.leftBearing, dxSqr + bmSqr.leftBearing);
   mBoundingMetrics.rightBearing = dxSqr + bmSqr.width +
     std::max(bmBase.width, bmBase.rightBearing);
 
-  aDesiredSize.width = mBoundingMetrics.width;
+  aDesiredSize.Width() = mBoundingMetrics.width;
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
   GatherAndStoreOverflow(&aDesiredSize);
 
   // place the index
   nscoord dx = dxIndex;
-  nscoord dy = aDesiredSize.ascent - (indexRaisedAscent + indexSize.ascent - bmIndex.ascent);
+  nscoord dy = aDesiredSize.TopAscent() - (indexRaisedAscent + indexSize.TopAscent() - bmIndex.ascent);
   FinishReflowChild(indexFrame, aPresContext, nullptr, indexSize,
-                    MirrorIfRTL(aDesiredSize.width, indexSize.width, dx),
+                    MirrorIfRTL(aDesiredSize.Width(), indexSize.Width(), dx),
                     dy, 0);
 
   // place the radical symbol and the radical bar
   dx = dxSqr;
   dy = indexClearance + leading; // leave a leading at the top
-  mSqrChar.SetRect(nsRect(MirrorIfRTL(aDesiredSize.width, bmSqr.width, dx),
+  mSqrChar.SetRect(nsRect(MirrorIfRTL(aDesiredSize.Width(), bmSqr.width, dx),
                           dy, bmSqr.width, bmSqr.ascent + bmSqr.descent));
   dx += bmSqr.width;
-  mBarRect.SetRect(MirrorIfRTL(aDesiredSize.width, bmBase.width, dx),
+  mBarRect.SetRect(MirrorIfRTL(aDesiredSize.Width(), bmBase.width, dx),
                    dy, bmBase.width, ruleThickness);
 
   // place the base
-  dy = aDesiredSize.ascent - baseSize.ascent;
+  dy = aDesiredSize.TopAscent() - baseSize.TopAscent();
   FinishReflowChild(baseFrame, aPresContext, nullptr, baseSize,
-                    MirrorIfRTL(aDesiredSize.width, baseSize.width, dx),
+                    MirrorIfRTL(aDesiredSize.Width(), baseSize.Width(), dx),
                     dy, 0);
 
   mReference.x = 0;
-  mReference.y = aDesiredSize.ascent;
+  mReference.y = aDesiredSize.TopAscent();
 
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 /* virtual */ void
 nsMathMLmrootFrame::GetIntrinsicWidthMetrics(nsRenderingContext* aRenderingContext, nsHTMLReflowMetrics& aDesiredSize)
@@ -371,17 +372,17 @@ nsMathMLmrootFrame::GetIntrinsicWidthMet
   nscoord sqrWidth = mSqrChar.GetMaxWidth(PresContext(), *aRenderingContext);
 
   nscoord dxSqr;
   GetRadicalXOffsets(indexWidth, sqrWidth, aRenderingContext->FontMetrics(),
                      nullptr, &dxSqr);
 
   nscoord width = dxSqr + sqrWidth + baseWidth;
 
-  aDesiredSize.width = width;
+  aDesiredSize.Width() = width;
   aDesiredSize.mBoundingMetrics.width = width;
   aDesiredSize.mBoundingMetrics.leftBearing = 0;
   aDesiredSize.mBoundingMetrics.rightBearing = width;
 }
 
 // ----------------------
 // the Style System will use these to pass the proper style context to our MathMLChar
 nsStyleContext*
--- a/layout/mathml/nsMathMLmspaceFrame.cpp
+++ b/layout/mathml/nsMathMLmspaceFrame.cpp
@@ -104,30 +104,30 @@ nsMathMLmspaceFrame::Reflow(nsPresContex
 
   mBoundingMetrics = nsBoundingMetrics();
   mBoundingMetrics.width = mWidth;
   mBoundingMetrics.ascent = mHeight;
   mBoundingMetrics.descent = mDepth;
   mBoundingMetrics.leftBearing = 0;
   mBoundingMetrics.rightBearing = mBoundingMetrics.width;
 
-  aDesiredSize.ascent = mHeight;
-  aDesiredSize.width = std::max(0, mBoundingMetrics.width);
-  aDesiredSize.height = aDesiredSize.ascent + mDepth;
+  aDesiredSize.SetTopAscent(mHeight);
+  aDesiredSize.Width() = std::max(0, mBoundingMetrics.width);
+  aDesiredSize.Height() = aDesiredSize.TopAscent() + mDepth;
   // Also return our bounding metrics
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
 
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 /* virtual */ nsresult
 nsMathMLmspaceFrame::MeasureForWidth(nsRenderingContext& aRenderingContext,
                                      nsHTMLReflowMetrics& aDesiredSize)
 {
   ProcessAttributes(PresContext());
   mBoundingMetrics = nsBoundingMetrics();
   mBoundingMetrics.width = mWidth;
-  aDesiredSize.width = std::max(0, mBoundingMetrics.width);
+  aDesiredSize.Width() = std::max(0, mBoundingMetrics.width);
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
   return NS_OK;
 }
--- a/layout/mathml/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/nsMathMLmtableFrame.cpp
@@ -587,68 +587,68 @@ nsMathMLmtableOuterFrame::Reflow(nsPresC
                                  nsReflowStatus&          aStatus)
 {
   nsresult rv;
   nsAutoString value;
   // we want to return a table that is anchored according to the align attribute
 
   rv = nsTableOuterFrame::Reflow(aPresContext, aDesiredSize, aReflowState,
                                  aStatus);
-  NS_ASSERTION(aDesiredSize.height >= 0, "illegal height for mtable");
-  NS_ASSERTION(aDesiredSize.width >= 0, "illegal width for mtable");
+  NS_ASSERTION(aDesiredSize.Height() >= 0, "illegal height for mtable");
+  NS_ASSERTION(aDesiredSize.Width() >= 0, "illegal width for mtable");
 
   // see if the user has set the align attribute on the <mtable>
   // XXX should we also check <mstyle> ?
   int32_t rowIndex = 0;
   eAlign tableAlign = eAlign_axis;
   GetAttribute(mContent, nullptr, nsGkAtoms::align, value);
   if (!value.IsEmpty()) {
     ParseAlignAttribute(value, tableAlign, rowIndex);
   }
 
   // adjustments if there is a specified row from where to anchor the table
   // (conceptually: when there is no row of reference, picture the table as if
   // it is wrapped in a single big fictional row at dy = 0, this way of
   // doing so allows us to have a single code path for all cases).
   nscoord dy = 0;
-  nscoord height = aDesiredSize.height;
+  nscoord height = aDesiredSize.Height();
   nsIFrame* rowFrame = nullptr;
   if (rowIndex) {
     rowFrame = GetRowFrameAt(aPresContext, rowIndex);
     if (rowFrame) {
       // translate the coordinates to be relative to us
       nsIFrame* frame = rowFrame;
       height = frame->GetSize().height;
       do {
         dy += frame->GetPosition().y;
         frame = frame->GetParent();
       } while (frame != this);
     }
   }
   switch (tableAlign) {
     case eAlign_top:
-      aDesiredSize.ascent = dy;
+      aDesiredSize.SetTopAscent(dy);
       break;
     case eAlign_bottom:
-      aDesiredSize.ascent = dy + height;
+      aDesiredSize.SetTopAscent(dy + height);
       break;
     case eAlign_center:
-      aDesiredSize.ascent = dy + height/2;
+      aDesiredSize.SetTopAscent(dy + height / 2);
       break;
     case eAlign_baseline:
       if (rowFrame) {
         // anchor the table on the baseline of the row of reference
         nscoord rowAscent = ((nsTableRowFrame*)rowFrame)->GetMaxCellAscent();
         if (rowAscent) { // the row has at least one cell with 'vertical-align: baseline'
-          aDesiredSize.ascent = dy + rowAscent;
+          aDesiredSize.SetTopAscent(dy + rowAscent);
           break;
         }
       }
       // in other situations, fallback to center
-      aDesiredSize.ascent = dy + height/2;
+      aDesiredSize.SetTopAscent(dy + height / 2);
       break;
     case eAlign_axis:
     default: {
       // XXX should instead use style data from the row of reference here ?
       nsRefPtr<nsFontMetrics> fm;
       nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
       aReflowState.rendContext->SetFont(fm);
       nscoord axisHeight;
@@ -656,35 +656,35 @@ nsMathMLmtableOuterFrame::Reflow(nsPresC
                     aReflowState.rendContext->FontMetrics(),
                     axisHeight);
       if (rowFrame) {
         // anchor the table on the axis of the row of reference
         // XXX fallback to baseline because it is a hard problem
         // XXX need to fetch the axis of the row; would need rowalign=axis to work better
         nscoord rowAscent = ((nsTableRowFrame*)rowFrame)->GetMaxCellAscent();
         if (rowAscent) { // the row has at least one cell with 'vertical-align: baseline'
-          aDesiredSize.ascent = dy + rowAscent;
+          aDesiredSize.SetTopAscent(dy + rowAscent);
           break;
         }
       }
       // in other situations, fallback to using half of the height
-      aDesiredSize.ascent = dy + height/2 + axisHeight;
+      aDesiredSize.SetTopAscent(dy + height / 2 + axisHeight);
     }
   }
 
   mReference.x = 0;
-  mReference.y = aDesiredSize.ascent;
+  mReference.y = aDesiredSize.TopAscent();
 
   // just make-up a bounding metrics
   mBoundingMetrics = nsBoundingMetrics();
-  mBoundingMetrics.ascent = aDesiredSize.ascent;
-  mBoundingMetrics.descent = aDesiredSize.height - aDesiredSize.ascent;
-  mBoundingMetrics.width = aDesiredSize.width;
+  mBoundingMetrics.ascent = aDesiredSize.TopAscent();
+  mBoundingMetrics.descent = aDesiredSize.Height() - aDesiredSize.TopAscent();
+  mBoundingMetrics.width = aDesiredSize.Width();
   mBoundingMetrics.leftBearing = 0;
-  mBoundingMetrics.rightBearing = aDesiredSize.width;
+  mBoundingMetrics.rightBearing = aDesiredSize.Width();
 
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
 
   return rv;
 }
 
 nsIFrame*
--- a/layout/mathml/nsMathMLmunderoverFrame.cpp
+++ b/layout/mathml/nsMathMLmunderoverFrame.cpp
@@ -325,24 +325,24 @@ nsMathMLmunderoverFrame::Place(nsRenderi
     }
     
   }
 
   ////////////////////////////////////
   // Get the children's desired sizes
 
   nsBoundingMetrics bmBase, bmUnder, bmOver;
-  nsHTMLReflowMetrics baseSize;
-  nsHTMLReflowMetrics underSize;
-  nsHTMLReflowMetrics overSize;
+  nsHTMLReflowMetrics baseSize(aDesiredSize.GetWritingMode());
+  nsHTMLReflowMetrics underSize(aDesiredSize.GetWritingMode());
+  nsHTMLReflowMetrics overSize(aDesiredSize.GetWritingMode());
   nsIFrame* overFrame = nullptr;
   nsIFrame* underFrame = nullptr;
   nsIFrame* baseFrame = mFrames.FirstChild();
-  underSize.ascent = 0; 
-  overSize.ascent = 0;
+  underSize.SetTopAscent(0);
+  overSize.SetTopAscent(0);
   bool haveError = false;
   if (baseFrame) {
     if (tag == nsGkAtoms::munder_ ||
         tag == nsGkAtoms::munderover_) {
       underFrame = baseFrame->GetNextSibling();
     } else if (tag == nsGkAtoms::mover_) {
       overFrame = baseFrame->GetNextSibling();
     }
@@ -555,18 +555,18 @@ nsMathMLmunderoverFrame::Place(nsRenderi
   // result. We conceptually view the previous result as an "anynomous base" 
   // from where to attach the underscript. Hence if the underscript is empty,
   // we should end up like <mover>. If the overscript is empty, we should
   // end up like <munder>.
 
   nsBoundingMetrics bmAnonymousBase = mBoundingMetrics;
   nscoord ascentAnonymousBase =
     std::max(mBoundingMetrics.ascent + overDelta2,
-           overSize.ascent + bmOver.descent + overDelta1 + bmBase.ascent);
-  ascentAnonymousBase = std::max(ascentAnonymousBase, baseSize.ascent);
+           overSize.TopAscent() + bmOver.descent + overDelta1 + bmBase.ascent);
+  ascentAnonymousBase = std::max(ascentAnonymousBase, baseSize.TopAscent());
 
   // Width of non-spacing marks is zero so use left and right bearing.
   nscoord underWidth = bmUnder.width;
   if (!underWidth) {
     underWidth = bmUnder.rightBearing - bmUnder.leftBearing;
     dxUnder = -bmUnder.leftBearing;
   }
 
@@ -595,43 +595,43 @@ nsMathMLmunderoverFrame::Place(nsRenderi
   // At this point, mBoundingMetrics.ascent = bmAnonymousBase.ascent 
   mBoundingMetrics.descent = 
     bmAnonymousBase.descent + underDelta1 + bmUnder.ascent + bmUnder.descent;
   mBoundingMetrics.leftBearing =
     std::min(dxAnonymousBase + bmAnonymousBase.leftBearing, dxUnder + bmUnder.leftBearing);
   mBoundingMetrics.rightBearing = 
     std::max(dxAnonymousBase + bmAnonymousBase.rightBearing, dxUnder + bmUnder.rightBearing);
 
-  aDesiredSize.ascent = ascentAnonymousBase;
-  aDesiredSize.height = aDesiredSize.ascent +
+  aDesiredSize.SetTopAscent(ascentAnonymousBase);
+  aDesiredSize.Height() = aDesiredSize.TopAscent() +
     std::max(mBoundingMetrics.descent + underDelta2,
            bmAnonymousBase.descent + underDelta1 + bmUnder.ascent +
-             underSize.height - underSize.ascent);
-  aDesiredSize.height = std::max(aDesiredSize.height,
-                               aDesiredSize.ascent +
-                               baseSize.height - baseSize.ascent);
-  aDesiredSize.width = mBoundingMetrics.width;
+             underSize.Height() - underSize.TopAscent());
+  aDesiredSize.Height() = std::max(aDesiredSize.Height(),
+                               aDesiredSize.TopAscent() +
+                               baseSize.Height() - baseSize.TopAscent());
+  aDesiredSize.Width() = mBoundingMetrics.width;
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
 
   mReference.x = 0;
-  mReference.y = aDesiredSize.ascent;
+  mReference.y = aDesiredSize.TopAscent();
 
   if (aPlaceOrigin) {
     nscoord dy;
     // place overscript
     if (overFrame) {
-      dy = aDesiredSize.ascent - mBoundingMetrics.ascent + bmOver.ascent 
-        - overSize.ascent;
+      dy = aDesiredSize.TopAscent() - mBoundingMetrics.ascent + bmOver.ascent 
+        - overSize.TopAscent();
       FinishReflowChild (overFrame, PresContext(), nullptr, overSize, dxOver, dy, 0);
     }
     // place base
-    dy = aDesiredSize.ascent - baseSize.ascent;
+    dy = aDesiredSize.TopAscent() - baseSize.TopAscent();
     FinishReflowChild (baseFrame, PresContext(), nullptr, baseSize, dxBase, dy, 0);
     // place underscript
     if (underFrame) {
-      dy = aDesiredSize.ascent + mBoundingMetrics.descent - bmUnder.descent 
-        - underSize.ascent;
+      dy = aDesiredSize.TopAscent() + mBoundingMetrics.descent - bmUnder.descent 
+        - underSize.TopAscent();
       FinishReflowChild (underFrame, PresContext(), nullptr, underSize,
                          dxUnder, dy, 0);
     }
   }
   return NS_OK;
 }
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -5161,28 +5161,28 @@ SVGTextFrame::DoReflow()
   }
 
   mState |= NS_STATE_SVG_TEXT_IN_REFLOW;
 
   nscoord width = kid->GetPrefWidth(renderingContext);
   nsHTMLReflowState reflowState(presContext, kid,
                                 renderingContext,
                                 nsSize(width, NS_UNCONSTRAINEDSIZE));
-  nsHTMLReflowMetrics desiredSize;
+  nsHTMLReflowMetrics desiredSize(reflowState.GetWritingMode());
   nsReflowStatus status;
 
   NS_ASSERTION(reflowState.ComputedPhysicalBorderPadding() == nsMargin(0, 0, 0, 0) &&
                reflowState.ComputedPhysicalMargin() == nsMargin(0, 0, 0, 0),
                "style system should ensure that :-moz-svg-text "
                "does not get styled");
 
   kid->WillReflow(presContext);
   kid->Reflow(presContext, desiredSize, reflowState, status);
   kid->DidReflow(presContext, &reflowState, nsDidReflowStatus::FINISHED);
-  kid->SetSize(nsSize(desiredSize.width, desiredSize.height));
+  kid->SetSize(nsSize(desiredSize.Width(), desiredSize.Height()));
 
   mState &= ~NS_STATE_SVG_TEXT_IN_REFLOW;
 
   TextNodeCorrespondenceRecorder::RecordCorrespondence(this);
 }
 
 // Usable font size range in devpixels / user-units
 #define CLAMP_MIN_SIZE 8.0
--- a/layout/svg/nsSVGForeignObjectFrame.cpp
+++ b/layout/svg/nsSVGForeignObjectFrame.cpp
@@ -140,18 +140,18 @@ nsSVGForeignObjectFrame::Reflow(nsPresCo
                "should only get reflow from being reflow root");
   NS_ASSERTION(aReflowState.ComputedWidth() == GetSize().width &&
                aReflowState.ComputedHeight() == GetSize().height,
                "reflow roots should be reflowed at existing size and "
                "svg.css should ensure we have no padding/border/margin");
 
   DoReflow();
 
-  aDesiredSize.width = aReflowState.ComputedWidth();
-  aDesiredSize.height = aReflowState.ComputedHeight();
+  aDesiredSize.Width() = aReflowState.ComputedWidth();
+  aDesiredSize.Height() = aReflowState.ComputedHeight();
   aDesiredSize.SetOverflowAreasToDesiredBounds();
   aStatus = NS_FRAME_COMPLETE;
 
   return NS_OK;
 }
 
 void
 nsSVGForeignObjectFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
@@ -548,33 +548,33 @@ nsSVGForeignObjectFrame::DoReflow()
   if (!renderingContext)
     return;
 
   mInReflow = true;
 
   nsHTMLReflowState reflowState(presContext, kid,
                                 renderingContext,
                                 nsSize(mRect.width, NS_UNCONSTRAINEDSIZE));
-  nsHTMLReflowMetrics desiredSize;
+  nsHTMLReflowMetrics desiredSize(reflowState.GetWritingMode());
   nsReflowStatus status;
 
   // We don't use mRect.height above because that tells the child to do
   // page/column breaking at that height.
   NS_ASSERTION(reflowState.ComputedPhysicalBorderPadding() == nsMargin(0, 0, 0, 0) &&
                reflowState.ComputedPhysicalMargin() == nsMargin(0, 0, 0, 0),
                "style system should ensure that :-moz-svg-foreign-content "
                "does not get styled");
   NS_ASSERTION(reflowState.ComputedWidth() == mRect.width,
                "reflow state made child wrong size");
   reflowState.SetComputedHeight(mRect.height);
 
   ReflowChild(kid, presContext, desiredSize, reflowState, 0, 0,
               NS_FRAME_NO_MOVE_FRAME, status);
-  NS_ASSERTION(mRect.width == desiredSize.width &&
-               mRect.height == desiredSize.height, "unexpected size");
+  NS_ASSERTION(mRect.width == desiredSize.Width() &&
+               mRect.height == desiredSize.Height(), "unexpected size");
   FinishReflowChild(kid, presContext, &reflowState, desiredSize, 0, 0,
                     NS_FRAME_NO_MOVE_FRAME);
   
   mInReflow = false;
 }
 
 nsRect
 nsSVGForeignObjectFrame::GetInvalidRegion()
--- a/layout/svg/nsSVGOuterSVGFrame.cpp
+++ b/layout/svg/nsSVGOuterSVGFrame.cpp
@@ -317,19 +317,19 @@ nsSVGOuterSVGFrame::Reflow(nsPresContext
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                   ("enter nsSVGOuterSVGFrame::Reflow: availSize=%d,%d",
                   aReflowState.AvailableWidth(), aReflowState.AvailableHeight()));
 
   NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow");
 
   aStatus = NS_FRAME_COMPLETE;
 
-  aDesiredSize.width  = aReflowState.ComputedWidth() +
+  aDesiredSize.Width()  = aReflowState.ComputedWidth() +
                           aReflowState.ComputedPhysicalBorderPadding().LeftRight();
-  aDesiredSize.height = aReflowState.ComputedHeight() +
+  aDesiredSize.Height() = aReflowState.ComputedHeight() +
                           aReflowState.ComputedPhysicalBorderPadding().TopBottom();
 
   NS_ASSERTION(!GetPrevInFlow(), "SVG can't currently be broken across pages.");
 
   SVGSVGElement *svgElem = static_cast<SVGSVGElement*>(mContent);
 
   nsSVGOuterSVGAnonChildFrame *anonKid =
     static_cast<nsSVGOuterSVGAnonChildFrame*>(GetFirstPrincipalChild());
@@ -443,17 +443,17 @@ nsSVGOuterSVGFrame::Reflow(nsPresContext
     aDesiredSize.mOverflowAreas.VisualOverflow().UnionRect(
       aDesiredSize.mOverflowAreas.VisualOverflow(),
       anonKid->GetVisualOverflowRect() + anonKid->GetPosition());
   }
   FinishAndStoreOverflow(&aDesiredSize);
 
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                   ("exit nsSVGOuterSVGFrame::Reflow: size=%d,%d",
-                  aDesiredSize.width, aDesiredSize.height));
+                  aDesiredSize.Width(), aDesiredSize.Height()));
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSVGOuterSVGFrame::DidReflow(nsPresContext*   aPresContext,
                               const nsHTMLReflowState*  aReflowState,
                               nsDidReflowStatus aStatus)
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -601,19 +601,19 @@ void nsTableCellFrame::VerticallyAlignCh
   kidYTop = std::max(0, kidYTop);
 
   if (kidYTop != kidRect.y) {
     // Invalidate at the old position first
     firstKid->InvalidateFrameSubtree();
   }
 
   firstKid->SetPosition(nsPoint(kidRect.x, kidYTop));
-  nsHTMLReflowMetrics desiredSize;
-  desiredSize.width = mRect.width;
-  desiredSize.height = mRect.height;
+  nsHTMLReflowMetrics desiredSize(GetWritingMode()); // ???
+  desiredSize.Width() = mRect.width;
+  desiredSize.Height() = mRect.height;
 
   nsRect overflow(nsPoint(0,0), GetSize());
   overflow.Inflate(GetBorderOverflow());
   desiredSize.mOverflowAreas.SetAllTo(overflow);
   ConsiderChildOverflow(desiredSize.mOverflowAreas, firstKid);
   FinishAndStoreOverflow(&desiredSize);
   if (kidYTop != kidRect.y) {
     // Make sure any child views are correctly positioned. We know the inner table
@@ -780,19 +780,19 @@ nsTableCellFrame::IntrinsicWidthOffsets(
 
 #ifdef DEBUG
 #define PROBABLY_TOO_LARGE 1000000
 static
 void DebugCheckChildSize(nsIFrame*            aChild,
                          nsHTMLReflowMetrics& aMet,
                          nsSize&              aAvailSize)
 {
-  if ((aMet.width < 0) || (aMet.width > PROBABLY_TOO_LARGE)) {
+  if ((aMet.Width() < 0) || (aMet.Width() > PROBABLY_TOO_LARGE)) {
     printf("WARNING: cell content %p has large width %d \n",
-           static_cast<void*>(aChild), int32_t(aMet.width));
+           static_cast<void*>(aChild), int32_t(aMet.Width()));
   }
 }
 #endif
 
 // the computed height for the cell, which descendants use for percent height calculations
 // it is the height (minus border, padding) of the cell's first in flow during its final
 // reflow without an unconstrained height.
 static nscoord
@@ -861,18 +861,18 @@ NS_METHOD nsTableCellFrame::Reflow(nsPre
   if (NS_UNCONSTRAINEDSIZE != availSize.height)
     availSize.height -= topInset + bottomInset;
 
   // Try to reflow the child into the available space. It might not
   // fit or might need continuing.
   if (availSize.height < 0)
     availSize.height = 1;
 
-  nsHTMLReflowMetrics kidSize(aDesiredSize.mFlags);
-  kidSize.width = kidSize.height = 0;
+  nsHTMLReflowMetrics kidSize(aReflowState.GetWritingMode(), aDesiredSize.mFlags);
+  kidSize.Width() = kidSize.Height() = 0;
   SetPriorAvailWidth(aReflowState.AvailableWidth());
   nsIFrame* firstKid = mFrames.FirstChild();
   NS_ASSERTION(firstKid, "Frame construction error, a table cell always has an inner cell frame");
   nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
 
   if (aReflowState.mFlags.mSpecialHeightReflow) {
     const_cast<nsHTMLReflowState&>(aReflowState).SetComputedHeight(mRect.height - topInset - bottomInset);
     DISPLAY_REFLOW_CHANGE();
@@ -938,63 +938,63 @@ NS_METHOD nsTableCellFrame::Reflow(nsPre
 
   // 0 dimensioned cells need to be treated specially in Standard/NavQuirks mode
   // see testcase "emptyCells.html"
   nsIFrame* prevInFlow = GetPrevInFlow();
   bool isEmpty;
   if (prevInFlow) {
     isEmpty = static_cast<nsTableCellFrame*>(prevInFlow)->GetContentEmpty();
   } else {
-    isEmpty = !CellHasVisibleContent(kidSize.height, tableFrame, firstKid);
+    isEmpty = !CellHasVisibleContent(kidSize.Height(), tableFrame, firstKid);
   }
   SetContentEmpty(isEmpty);
 
   // Place the child
   FinishReflowChild(firstKid, aPresContext, &kidReflowState, kidSize,
                     kidOrigin.x, kidOrigin.y, 0);
 
   nsTableFrame::InvalidateTableFrame(firstKid, origRect, origVisualOverflow,
                                      firstReflow);
 
   // first, compute the height which can be set w/o being restricted by aMaxSize.height
-  nscoord cellHeight = kidSize.height;
+  nscoord cellHeight = kidSize.Height();
 
   if (NS_UNCONSTRAINEDSIZE != cellHeight) {
     cellHeight += topInset + bottomInset;
   }
 
   // next determine the cell's width
-  nscoord cellWidth = kidSize.width;      // at this point, we've factored in the cell's style attributes
+  nscoord cellWidth = kidSize.Width();      // at this point, we've factored in the cell's style attributes
 
   // factor in border and padding
   if (NS_UNCONSTRAINEDSIZE != cellWidth) {
     cellWidth += leftInset + rightInset;
   }
 
   // set the cell's desired size and max element size
-  aDesiredSize.width   = cellWidth;
-  aDesiredSize.height  = cellHeight;
+  aDesiredSize.Width() = cellWidth;
+  aDesiredSize.Height() = cellHeight;
 
   // the overflow area will be computed when the child will be vertically aligned
 
   if (aReflowState.mFlags.mSpecialHeightReflow) {
-    if (aDesiredSize.height > mRect.height) {
+    if (aDesiredSize.Height() > mRect.height) {
       // set a bit indicating that the pct height contents exceeded
       // the height that they could honor in the pass 2 reflow
       SetHasPctOverHeight(true);
     }
     if (NS_UNCONSTRAINEDSIZE == aReflowState.AvailableHeight()) {
-      aDesiredSize.height = mRect.height;
+      aDesiredSize.Height() = mRect.height;
     }
   }
 
   // If our parent is in initial reflow, it'll handle invalidating our
   // entire overflow rect.
   if (!(GetParent()->GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
-      nsSize(aDesiredSize.width, aDesiredSize.height) != mRect.Size()) {
+      nsSize(aDesiredSize.Width(), aDesiredSize.Height()) != mRect.Size()) {
     InvalidateFrame();
   }
 
   // remember the desired size for this reflow
   SetDesiredSize(aDesiredSize);
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
--- a/layout/tables/nsTableCellFrame.h
+++ b/layout/tables/nsTableCellFrame.h
@@ -251,18 +251,18 @@ inline nscoord nsTableCellFrame::GetPrio
 inline void nsTableCellFrame::SetPriorAvailWidth(nscoord aPriorAvailWidth)
 { mPriorAvailWidth = aPriorAvailWidth;}
 
 inline nsSize nsTableCellFrame::GetDesiredSize()
 { return mDesiredSize; }
 
 inline void nsTableCellFrame::SetDesiredSize(const nsHTMLReflowMetrics & aDesiredSize)
 {
-  mDesiredSize.width = aDesiredSize.width;
-  mDesiredSize.height = aDesiredSize.height;
+  mDesiredSize.width = aDesiredSize.Width();
+  mDesiredSize.height = aDesiredSize.Height();
 }
 
 inline bool nsTableCellFrame::GetContentEmpty()
 {
   return (mState & NS_TABLE_CELL_CONTENT_EMPTY) ==
          NS_TABLE_CELL_CONTENT_EMPTY;
 }
 
--- a/layout/tables/nsTableColFrame.cpp
+++ b/layout/tables/nsTableColFrame.cpp
@@ -86,18 +86,18 @@ void nsTableColFrame::SetContinuousBCBor
 
 NS_METHOD nsTableColFrame::Reflow(nsPresContext*          aPresContext,
                                   nsHTMLReflowMetrics&     aDesiredSize,
                                   const nsHTMLReflowState& aReflowState,
                                   nsReflowStatus&          aStatus)
 {
   DO_GLOBAL_REFLOW_COUNT("nsTableColFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
-  aDesiredSize.width=0;
-  aDesiredSize.height=0;
+  aDesiredSize.Width() = 0;
+  aDesiredSize.Height() = 0;
   const nsStyleVisibility* colVis = StyleVisibility();
   bool collapseCol = (NS_STYLE_VISIBILITY_COLLAPSE == colVis->mVisible);
   if (collapseCol) {
     nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
     tableFrame->SetNeedToCollapse(true);
   }
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
--- a/layout/tables/nsTableColGroupFrame.cpp
+++ b/layout/tables/nsTableColGroupFrame.cpp
@@ -366,27 +366,27 @@ NS_METHOD nsTableColGroupFrame::Reflow(n
     tableFrame->SetNeedToCollapse(true);
   }
   // for every content child that (is a column thingy and does not already have a frame)
   // create a frame and adjust it's style
   
   for (nsIFrame *kidFrame = mFrames.FirstChild(); kidFrame;
        kidFrame = kidFrame->GetNextSibling()) {
     // Give the child frame a chance to reflow, even though we know it'll have 0 size
-    nsHTMLReflowMetrics kidSize;
+    nsHTMLReflowMetrics kidSize(aReflowState.GetWritingMode());
     nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
                                      nsSize(0,0));
 
     nsReflowStatus status;
     ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, 0, 0, 0, status);
     FinishReflowChild(kidFrame, aPresContext, nullptr, kidSize, 0, 0, 0);
   }
 
-  aDesiredSize.width=0;
-  aDesiredSize.height=0;
+  aDesiredSize.Width() = 0;
+  aDesiredSize.Height() = 0;
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return rv;
 }
 
 nsTableColFrame * nsTableColGroupFrame::GetFirstColumn()
 {
   return GetNextColumn(nullptr);
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1697,17 +1697,17 @@ NS_METHOD nsTableFrame::Reflow(nsPresCon
   }
   nsresult rv = NS_OK;
 
   // see if collapsing borders need to be calculated
   if (!GetPrevInFlow() && IsBorderCollapse() && NeedToCalcBCBorders()) {
     CalcBCBorders();
   }
 
-  aDesiredSize.width = aReflowState.AvailableWidth();
+  aDesiredSize.Width() = aReflowState.AvailableWidth();
 
   // Check for an overflow list, and append any row group frames being pushed
   MoveOverflowToChildList(aPresContext);
 
   bool haveDesiredHeight = false;
   SetHaveReflowedColGroups(false);
 
   // Reflow the entire table (pass 2 and possibly pass 3). This phase is necessary during a
@@ -1778,59 +1778,59 @@ NS_METHOD nsTableFrame::Reflow(nsPresCon
       mutable_rs.mFlags.mSpecialHeightReflow = true;
 
       ReflowTable(aDesiredSize, aReflowState, aReflowState.AvailableHeight(),
                   lastChildReflowed, aStatus);
 
       if (lastChildReflowed && NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
         // if there is an incomplete child, then set the desired height to include it but not the next one
         nsMargin borderPadding = GetChildAreaOffset(&aReflowState);
-        aDesiredSize.height = borderPadding.bottom + GetCellSpacingY() +
+        aDesiredSize.Height() = borderPadding.bottom + GetCellSpacingY() +
                               lastChildReflowed->GetRect().YMost();
       }
       haveDesiredHeight = true;
 
       mutable_rs.mFlags.mSpecialHeightReflow = false;
     }
   }
   else {
     // Calculate the overflow area contribution from our children.
     for (nsIFrame* kid = GetFirstPrincipalChild(); kid; kid = kid->GetNextSibling()) {
       ConsiderChildOverflow(aDesiredSize.mOverflowAreas, kid);
     }
   }
 
-  aDesiredSize.width = aReflowState.ComputedWidth() +
+  aDesiredSize.Width() = aReflowState.ComputedWidth() +
                        aReflowState.ComputedPhysicalBorderPadding().LeftRight();
   if (!haveDesiredHeight) {
     CalcDesiredHeight(aReflowState, aDesiredSize);
   }
   if (IsRowInserted()) {
-    ProcessRowInserted(aDesiredSize.height);
+    ProcessRowInserted(aDesiredSize.Height());
   }
 
   nsMargin borderPadding = GetChildAreaOffset(&aReflowState);
-  SetColumnDimensions(aDesiredSize.height, borderPadding);
+  SetColumnDimensions(aDesiredSize.Height(), borderPadding);
   if (NeedToCollapse() &&
       (NS_UNCONSTRAINEDSIZE != aReflowState.AvailableWidth())) {
     AdjustForCollapsingRowsCols(aDesiredSize, borderPadding);
   }
 
   // make sure the table overflow area does include the table rect.
-  nsRect tableRect(0, 0, aDesiredSize.width, aDesiredSize.height) ;
+  nsRect tableRect(0, 0, aDesiredSize.Width(), aDesiredSize.Height()) ;
 
   if (!ShouldApplyOverflowClipping(this, aReflowState.mStyleDisplay)) {
     // collapsed border may leak out
     nsMargin bcMargin = GetExcludedOuterBCBorder();
     tableRect.Inflate(bcMargin);
   }
   aDesiredSize.mOverflowAreas.UnionAllWith(tableRect);
 
   if ((GetStateBits() & NS_FRAME_FIRST_REFLOW) ||
-      nsSize(aDesiredSize.width, aDesiredSize.height) != mRect.Size()) {
+      nsSize(aDesiredSize.Width(), aDesiredSize.Height()) != mRect.Size()) {
       nsIFrame::InvalidateFrame();
   }
 
   FinishAndStoreOverflow(&aDesiredSize);
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return rv;
 }
 
@@ -1862,20 +1862,20 @@ nsTableFrame::ReflowTable(nsHTMLReflowMe
   nsresult rv = NS_OK;
   aLastChildReflowed = nullptr;
 
   if (!GetPrevInFlow()) {
     mTableLayoutStrategy->ComputeColumnWidths(aReflowState);
   }
   // Constrain our reflow width to the computed table width (of the 1st in flow).
   // and our reflow height to our avail height minus border, padding, cellspacing
-  aDesiredSize.width = aReflowState.ComputedWidth() +
+  aDesiredSize.Width() = aReflowState.ComputedWidth() +
                        aReflowState.ComputedPhysicalBorderPadding().LeftRight();
   nsTableReflowState reflowState(*PresContext(), aReflowState, *this,
-                                 aDesiredSize.width, aAvailHeight);
+                                 aDesiredSize.Width(), aAvailHeight);
   ReflowChildren(reflowState, aStatus, aLastChildReflowed,
                  aDesiredSize.mOverflowAreas);
 
   ReflowColGroups(aReflowState.rendContext);
   return rv;
 }
 
 nsIFrame*
@@ -1983,21 +1983,21 @@ nsTableFrame::AdjustForCollapsingRowsCol
   // Walk the list of children
   for (uint32_t childX = 0; childX < rowGroups.Length(); childX++) {
     nsTableRowGroupFrame* rgFrame = rowGroups[childX];
     NS_ASSERTION(rgFrame, "Must have row group frame here");
     yTotalOffset += rgFrame->CollapseRowGroupIfNecessary(yTotalOffset, rgWidth);
     ConsiderChildOverflow(overflow, rgFrame);
   }
 
-  aDesiredSize.height -= yTotalOffset;
-  aDesiredSize.width   = width;
-  overflow.UnionAllWith(nsRect(0, 0, aDesiredSize.width, aDesiredSize.height));
+  aDesiredSize.Height() -= yTotalOffset;
+  aDesiredSize.Width() = width;
+  overflow.UnionAllWith(nsRect(0, 0, aDesiredSize.Width(), aDesiredSize.Height()));
   FinishAndStoreOverflow(overflow,
-                         nsSize(aDesiredSize.width, aDesiredSize.height));
+                         nsSize(aDesiredSize.Width(), aDesiredSize.Height()));
 }
 
 
 nscoord
 nsTableFrame::GetCollapsedWidth(nsMargin aBorderPadding)
 {
   NS_ASSERTION(!GetPrevInFlow(), "GetCollapsedWidth called on next in flow");
   nscoord cellSpacingX = GetCellSpacingX();
@@ -2540,21 +2540,21 @@ void nsTableFrame::PlaceChild(nsTableRef
   // Place and size the child
   FinishReflowChild(aKidFrame, PresContext(), nullptr, aKidDesiredSize,
                     aReflowState.x, aReflowState.y, 0);
 
   InvalidateTableFrame(aKidFrame, aOriginalKidRect, aOriginalKidVisualOverflow,
                        isFirstReflow);
 
   // Adjust the running y-offset
-  aReflowState.y += aKidDesiredSize.height;
+  aReflowState.y += aKidDesiredSize.Height();
 
   // If our height is constrained, then update the available height
   if (NS_UNCONSTRAINEDSIZE != aReflowState.availSize.height) {
-    aReflowState.availSize.height -= aKidDesiredSize.height;
+    aReflowState.availSize.height -= aKidDesiredSize.Height();
   }
 }
 
 void
 nsTableFrame::OrderRowGroups(RowGroupArray& aChildren,
                              nsTableRowGroupFrame** aHead,
                              nsTableRowGroupFrame** aFoot) const
 {
@@ -2679,26 +2679,26 @@ nsTableFrame::SetupHeaderFooterChild(con
 
   // Reflow the child with unconstrainted height
   nsHTMLReflowState kidReflowState(presContext, aReflowState.reflowState,
                                    aFrame,
                                    nsSize(aReflowState.availSize.width, NS_UNCONSTRAINEDSIZE),
                                    -1, -1, nsHTMLReflowState::CALLER_WILL_INIT);
   InitChildReflowState(kidReflowState);
   kidReflowState.mFlags.mIsTopOfPage = true;
-  nsHTMLReflowMetrics desiredSize;
-  desiredSize.width = desiredSize.height = 0;
+  nsHTMLReflowMetrics desiredSize(aReflowState.reflowState.GetWritingMode());
+  desiredSize.Width() = desiredSize.Height() = 0;
   nsReflowStatus status;
   nsresult rv = ReflowChild(aFrame, presContext, desiredSize, kidReflowState,
                             aReflowState.x, aReflowState.y, 0, status);
   NS_ENSURE_SUCCESS(rv, rv);
   // The child will be reflowed again "for real" so no need to place it now
 
-  aFrame->SetRepeatable(IsRepeatable(desiredSize.height, pageHeight));
-  *aDesiredHeight = desiredSize.height;
+  aFrame->SetRepeatable(IsRepeatable(desiredSize.Height(), pageHeight));
+  *aDesiredHeight = desiredSize.Height();
   return NS_OK;
 }
 
 void 
 nsTableFrame::PlaceRepeatedFooter(nsTableReflowState& aReflowState,
                                   nsTableRowGroupFrame *aTfoot,
                                   nscoord aFooterHeight)
 {
@@ -2712,18 +2712,18 @@ nsTableFrame::PlaceRepeatedFooter(nsTabl
                                       nsHTMLReflowState::CALLER_WILL_INIT);
   InitChildReflowState(footerReflowState);
   aReflowState.y += GetCellSpacingY();
 
   nsRect origTfootRect = aTfoot->GetRect();
   nsRect origTfootVisualOverflow = aTfoot->GetVisualOverflowRect();
           
   nsReflowStatus footerStatus;
-  nsHTMLReflowMetrics desiredSize;
-  desiredSize.width = desiredSize.height = 0;
+  nsHTMLReflowMetrics desiredSize(aReflowState.reflowState.GetWritingMode());
+  desiredSize.Width() = desiredSize.Height() = 0;
   ReflowChild(aTfoot, presContext, desiredSize, footerReflowState,
               aReflowState.x, aReflowState.y, 0, footerStatus);
   PlaceChild(aReflowState, aTfoot, desiredSize, origTfootRect,
              origTfootVisualOverflow);
 }
                     
 // Reflow the children based on the avail size and reason in aReflowState
 // update aReflowMetrics a aStatus
@@ -2818,18 +2818,18 @@ nsTableFrame::ReflowChildren(nsTableRefl
             kidAvailSize.height -= footerHeight + cellSpacingY;
           }
         }
       }
 
       nsRect oldKidRect = kidFrame->GetRect();
       nsRect oldKidVisualOverflow = kidFrame->GetVisualOverflowRect();
 
-      nsHTMLReflowMetrics desiredSize;
-      desiredSize.width = desiredSize.height = 0;
+      nsHTMLReflowMetrics desiredSize(aReflowState.reflowState.GetWritingMode());
+      desiredSize.Width() = desiredSize.Height() = 0;
 
       // Reflow the child into the available space
       nsHTMLReflowState kidReflowState(presContext, aReflowState.reflowState,
                                        kidFrame, kidAvailSize,
                                        -1, -1,
                                        nsHTMLReflowState::CALLER_WILL_INIT);
       InitChildReflowState(kidReflowState);
 
@@ -2869,17 +2869,17 @@ nsTableFrame::ReflowChildren(nsTableRefl
         break;
       }
       // see if the rowgroup did not fit on this page might be pushed on
       // the next page
       if (isPaginated &&
           (NS_INLINE_IS_BREAK_BEFORE(aStatus) ||
            (NS_FRAME_IS_COMPLETE(aStatus) &&
             (NS_UNCONSTRAINEDSIZE != kidReflowState.AvailableHeight()) &&
-            kidReflowState.AvailableHeight() < desiredSize.height))) {
+            kidReflowState.AvailableHeight() < desiredSize.Height()))) {
         if (ShouldAvoidBreakInside(aReflowState.reflowState)) {
           aStatus = NS_INLINE_LINE_BREAK_BEFORE();
           break;
         }
         // if we are on top of the page place with dataloss
         if (kidReflowState.mFlags.mIsTopOfPage) {
           if (childX+1 < rowGroups.Length()) {
             nsIFrame* nextRowGroupFrame = rowGroups[childX + 1];
@@ -3004,17 +3004,17 @@ nsTableFrame::ReflowChildren(nsTableRefl
 
   return rv;
 }
 
 void
 nsTableFrame::ReflowColGroups(nsRenderingContext *aRenderingContext)
 {
   if (!GetPrevInFlow() && !HaveReflowedColGroups()) {
-    nsHTMLReflowMetrics kidMet;
+    nsHTMLReflowMetrics kidMet(GetWritingMode());
     nsPresContext *presContext = PresContext();
     for (nsIFrame* kidFrame = mColGroups.FirstChild(); kidFrame;
          kidFrame = kidFrame->GetNextSibling()) {
       if (NS_SUBTREE_DIRTY(kidFrame)) {
         // The column groups don't care about dimensions or reflow states.
         nsHTMLReflowState kidReflowState(presContext, kidFrame,
                                        aRenderingContext, nsSize(0,0));
         nsReflowStatus cgStatus;
@@ -3028,36 +3028,36 @@ nsTableFrame::ReflowColGroups(nsRenderin
 }
 
 void
 nsTableFrame::CalcDesiredHeight(const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredSize)
 {
   nsTableCellMap* cellMap = GetCellMap();
   if (!cellMap) {
     NS_ASSERTION(false, "never ever call me until the cell map is built!");
-    aDesiredSize.height = 0;
+    aDesiredSize.Height() = 0;
     return;
   }
   nscoord  cellSpacingY = GetCellSpacingY();
   nsMargin borderPadding = GetChildAreaOffset(&aReflowState);
 
   // get the natural height based on the last child's (row group) rect
   RowGroupArray rowGroups;
   OrderRowGroups(rowGroups);
   if (rowGroups.IsEmpty()) {
     // tables can be used as rectangular items without content
     nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
     if ((NS_UNCONSTRAINEDSIZE != tableSpecifiedHeight) &&
         (tableSpecifiedHeight > 0) &&
         eCompatibility_NavQuirks != PresContext()->CompatibilityMode()) {
           // empty tables should not have a size in quirks mode
-      aDesiredSize.height = tableSpecifiedHeight;
+      aDesiredSize.Height() = tableSpecifiedHeight;
     }
     else
-      aDesiredSize.height = 0;
+      aDesiredSize.Height() = 0;
     return;
   }
   int32_t rowCount = cellMap->GetRowCount();
   int32_t colCount = cellMap->GetColCount();
   nscoord desiredHeight = borderPadding.top + borderPadding.bottom;
   if (rowCount > 0 && colCount > 0) {
     desiredHeight += cellSpacingY;
     for (uint32_t rgX = 0; rgX < rowGroups.Length(); rgX++) {
@@ -3076,37 +3076,37 @@ nsTableFrame::CalcDesiredHeight(const ns
       DistributeHeightToRows(aReflowState, tableSpecifiedHeight - desiredHeight);
       // this might have changed the overflow area incorporate the childframe overflow area.
       for (nsIFrame* kidFrame = mFrames.FirstChild(); kidFrame; kidFrame = kidFrame->GetNextSibling()) {
         ConsiderChildOverflow(aDesiredSize.mOverflowAreas, kidFrame);
       }
       desiredHeight = tableSpecifiedHeight;
     }
   }
-  aDesiredSize.height = desiredHeight;
+  aDesiredSize.Height() = desiredHeight;
 }
 
 static
 void ResizeCells(nsTableFrame& aTableFrame)
 {
   nsTableFrame::RowGroupArray rowGroups;
   aTableFrame.OrderRowGroups(rowGroups);
-  nsHTMLReflowMetrics tableDesiredSize;
+  nsHTMLReflowMetrics tableDesiredSize(aTableFrame.GetWritingMode()); // ???
   nsRect tableRect = aTableFrame.GetRect();
-  tableDesiredSize.width = tableRect.width;
-  tableDesiredSize.height = tableRect.height;
+  tableDesiredSize.Width() = tableRect.width;
+  tableDesiredSize.Height() = tableRect.height;
   tableDesiredSize.SetOverflowAreasToDesiredBounds();
 
   for (uint32_t rgX = 0; rgX < rowGroups.Length(); rgX++) {
     nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
 
     nsRect rowGroupRect = rgFrame->GetRect();
-    nsHTMLReflowMetrics groupDesiredSize;
-    groupDesiredSize.width = rowGroupRect.width;
-    groupDesiredSize.height = rowGroupRect.height;
+    nsHTMLReflowMetrics groupDesiredSize(tableDesiredSize.GetWritingMode());
+    groupDesiredSize.Width() = rowGroupRect.width;
+    groupDesiredSize.Height() = rowGroupRect.height;
     groupDesiredSize.SetOverflowAreasToDesiredBounds();
 
     nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
     while (rowFrame) {
       rowFrame->DidResize();
       rgFrame->ConsiderChildOverflow(groupDesiredSize.mOverflowAreas, rowFrame);
       rowFrame = rowFrame->GetNextRow();
     }
--- a/layout/tables/nsTableOuterFrame.cpp
+++ b/layout/tables/nsTableOuterFrame.cpp
@@ -865,17 +865,17 @@ nsTableOuterFrame::OuterDoReflowChild(ns
 
 void 
 nsTableOuterFrame::UpdateReflowMetrics(uint8_t              aCaptionSide,
                                        nsHTMLReflowMetrics& aMet,
                                        const nsMargin&      aInnerMargin,
                                        const nsMargin&      aCaptionMargin)
 {
   SetDesiredSize(aCaptionSide, aInnerMargin, aCaptionMargin,
-                 aMet.width, aMet.height);
+                 aMet.Width(), aMet.Height());
 
   aMet.SetOverflowAreasToDesiredBounds();
   ConsiderChildOverflow(aMet.mOverflowAreas, InnerTableFrame());
   if (mCaptionFrames.NotEmpty()) {
     ConsiderChildOverflow(aMet.mOverflowAreas, mCaptionFrames.FirstChild());
   }
 }
 
@@ -886,17 +886,17 @@ NS_METHOD nsTableOuterFrame::Reflow(nsPr
 {
   DO_GLOBAL_REFLOW_COUNT("nsTableOuterFrame");
   DISPLAY_REFLOW(aPresContext, this, aOuterRS, aDesiredSize, aStatus);
 
   nsresult rv = NS_OK;
   uint8_t captionSide = GetCaptionSide();
 
   // Initialize out parameters
-  aDesiredSize.width = aDesiredSize.height = 0;
+  aDesiredSize.Width() = aDesiredSize.Height() = 0;
   aStatus = NS_FRAME_COMPLETE;
 
   if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
     // Set up our kids.  They're already present, on an overflow list, 
     // or there are none so we'll create them now
     MoveOverflowToChildList(aPresContext);
   }
 
@@ -971,26 +971,26 @@ NS_METHOD nsTableOuterFrame::Reflow(nsPr
     // Size the table and the caption independently.
     OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRS,
                           captionRSSpace, aOuterRS.ComputedWidth());
     OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS,
                           innerRSSpace, aOuterRS.ComputedWidth());
   }
 
   // First reflow the caption.
-  nsHTMLReflowMetrics captionMet;
+  nsHTMLReflowMetrics captionMet(captionRS->GetWritingMode());
   nsSize captionSize;
   nsMargin captionMargin;
   if (mCaptionFrames.NotEmpty()) {
     nsReflowStatus capStatus; // don't let the caption cause incomplete
     rv = OuterDoReflowChild(aPresContext, mCaptionFrames.FirstChild(),
                             *captionRS, captionMet, capStatus);
     if (NS_FAILED(rv)) return rv;
-    captionSize.width = captionMet.width;
-    captionSize.height = captionMet.height;
+    captionSize.width = captionMet.Width();
+    captionSize.height = captionMet.Height();
     captionMargin = captionRS->ComputedPhysicalMargin();
     // Now that we know the height of the caption, reduce the available height
     // for the table frame if we are height constrained and the caption is above
     // or below the inner table.
     if (NS_UNCONSTRAINEDSIZE != aOuterRS.AvailableHeight()) {
       nscoord captionHeight = 0;
       switch (captionSide) {
         case NS_STYLE_CAPTION_SIDE_TOP:
@@ -1006,23 +1006,23 @@ NS_METHOD nsTableOuterFrame::Reflow(nsPr
     }
   } else {
     captionSize.SizeTo(0,0);
     captionMargin.SizeTo(0,0,0,0);
   }
 
   // Then, now that we know how much to reduce the width of the inner
   // table to account for side captions, reflow the inner table.
-  nsHTMLReflowMetrics innerMet;
+  nsHTMLReflowMetrics innerMet(innerRS->GetWritingMode());
   rv = OuterDoReflowChild(aPresContext, InnerTableFrame(), *innerRS,
                           innerMet, aStatus);
   if (NS_FAILED(rv)) return rv;
   nsSize innerSize;
-  innerSize.width = innerMet.width;
-  innerSize.height = innerMet.height;
+  innerSize.width = innerMet.Width();
+  innerSize.height = innerMet.Height();
   nsMargin innerMargin = innerRS->ComputedPhysicalMargin();
 
   nsSize   containSize = GetContainingBlockSize(aOuterRS);
 
   // Now that we've reflowed both we can place them.
   // XXXldb Most of the input variables here are now uninitialized!
 
   // XXX Need to recompute inner table's auto margins for the case of side
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -313,19 +313,19 @@ nsTableRowFrame::GetFirstCell()
 void
 nsTableRowFrame::DidResize()
 {
   // Resize and re-align the cell frames based on our row height
   nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
   nsTableIterator iter(*this);
   nsIFrame* childFrame = iter.First();
   
-  nsHTMLReflowMetrics desiredSize;
-  desiredSize.width = mRect.width;
-  desiredSize.height = mRect.height;
+  nsHTMLReflowMetrics desiredSize(GetWritingMode()); // ???
+  desiredSize.Width() = mRect.width;
+  desiredSize.Height() = mRect.height;
   desiredSize.SetOverflowAreasToDesiredBounds();
 
   while (childFrame) {
     nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
     if (cellFrame) {
       nscoord cellHeight = mRect.height + GetHeightOfRowsSpannedBelowFirst(*cellFrame, *tableFrame);
 
       // resize the cell's height
@@ -809,17 +809,17 @@ nsTableRowFrame::ReflowChildren(nsPresCo
       // XXXldb nsCSSFrameConstructor needs to enforce this!
       NS_NOTREACHED("yikes, a non-row child");
 
       // it's an unknown frame type, give it a generic reflow and ignore the results
       nsTableCellReflowState kidReflowState(aPresContext, aReflowState,
                                             kidFrame, nsSize(0,0),
                                             nsHTMLReflowState::CALLER_WILL_INIT);
       InitChildReflowState(*aPresContext, nsSize(0,0), false, kidReflowState);
-      nsHTMLReflowMetrics desiredSize;
+      nsHTMLReflowMetrics desiredSize(aReflowState.GetWritingMode());
       nsReflowStatus  status;
       ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, 0, 0, 0, status);
       kidFrame->DidReflow(aPresContext, nullptr, nsDidReflowStatus::FINISHED);
 
       continue;
     }
 
     // See if we should only reflow the dirty child frames
@@ -864,17 +864,17 @@ nsTableRowFrame::ReflowChildren(nsPresCo
     bool firstReflow =
       (kidFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
 
     if (doReflowChild) {
       // Calculate the available width for the table cell using the known column widths
       nscoord availCellWidth =
         CalcAvailWidth(aTableFrame, *cellFrame, cellSpacingX);
 
-      nsHTMLReflowMetrics desiredSize;
+      nsHTMLReflowMetrics desiredSize(aReflowState.GetWritingMode());
 
       // If the avail width is not the same as last time we reflowed the cell or
       // the cell wants to be bigger than what was available last time or
       // it is a style change reflow or we are printing, then we must reflow the
       // cell. Otherwise we can skip the reflow.
       // XXXldb Why is this condition distinct from doReflowChild above?
       nsSize cellDesiredSize = cellFrame->GetDesiredSize();
       if ((availCellWidth != cellFrame->GetPriorAvailWidth())       ||
@@ -906,62 +906,62 @@ nsTableRowFrame::ReflowChildren(nsPresCo
           aStatus = NS_FRAME_NOT_COMPLETE;
         }
       }
       else {
         if (x != kidRect.x) {
           kidFrame->InvalidateFrameSubtree();
         }
         
-        desiredSize.width = cellDesiredSize.width;
-        desiredSize.height = cellDesiredSize.height;
+        desiredSize.Width() = cellDesiredSize.width;
+        desiredSize.Height() = cellDesiredSize.height;
         desiredSize.mOverflowAreas = cellFrame->GetOverflowAreas();
 
         // if we are in a floated table, our position is not yet established, so we cannot reposition our views
         // the containing block will do this for us after positioning the table
         if (!aTableFrame.IsFloating()) {
           // Because we may have moved the frame we need to make sure any views are
           // positioned properly. We have to do this, because any one of our parent
           // frames could have moved and we have no way of knowing...
           nsTableFrame::RePositionViews(kidFrame);
         }
       }
       
       if (NS_UNCONSTRAINEDSIZE == aReflowState.AvailableHeight()) {
         if (!GetPrevInFlow()) {
           // Calculate the cell's actual height given its pass2 height. This
           // function takes into account the specified height (in the style)
-          CalculateCellActualHeight(cellFrame, desiredSize.height);
+          CalculateCellActualHeight(cellFrame, desiredSize.Height());
         }
         // height may have changed, adjust descent to absorb any excess difference
         nscoord ascent;
         if (!kidFrame->GetFirstPrincipalChild()->GetFirstPrincipalChild())
-          ascent = desiredSize.height;
+          ascent = desiredSize.Height();
         else
           ascent = ((nsTableCellFrame *)kidFrame)->GetCellBaseline();
-        nscoord descent = desiredSize.height - ascent;
-        UpdateHeight(desiredSize.height, ascent, descent, &aTableFrame, cellFrame);
+        nscoord descent = desiredSize.Height() - ascent;
+        UpdateHeight(desiredSize.Height(), ascent, descent, &aTableFrame, cellFrame);
       }
       else {
-        cellMaxHeight = std::max(cellMaxHeight, desiredSize.height);
+        cellMaxHeight = std::max(cellMaxHeight, desiredSize.Height());
         int32_t rowSpan = aTableFrame.GetEffectiveRowSpan((nsTableCellFrame&)*kidFrame);
         if (1 == rowSpan) {
           SetContentHeight(cellMaxHeight);
         }
       }
 
       // Place the child
-      desiredSize.width = availCellWidth;
+      desiredSize.Width() = availCellWidth;
 
       FinishReflowChild(kidFrame, aPresContext, nullptr, desiredSize, x, 0, 0);
 
       nsTableFrame::InvalidateTableFrame(kidFrame, kidRect, kidVisualOverflow,
                                          firstReflow);
       
-      x += desiredSize.width;  
+      x += desiredSize.Width();  
     }
     else {
       if (kidRect.x != x) {
         // Invalidate the old position
         kidFrame->InvalidateFrameSubtree();
         // move to the new position
         kidFrame->SetPosition(nsPoint(x, kidRect.y));
         nsTableFrame::RePositionViews(kidFrame);
@@ -975,47 +975,47 @@ nsTableRowFrame::ReflowChildren(nsPresCo
         aStatus = NS_FRAME_NOT_COMPLETE;
       }
     }
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, kidFrame);
     x += cellSpacingX;
   }
 
   // just set our width to what was available. The table will calculate the width and not use our value.
-  aDesiredSize.width = aReflowState.AvailableWidth();
+  aDesiredSize.Width() = aReflowState.AvailableWidth();
 
   if (aReflowState.mFlags.mSpecialHeightReflow) {
-    aDesiredSize.height = mRect.height;
+    aDesiredSize.Height() = mRect.height;
   }
   else if (NS_UNCONSTRAINEDSIZE == aReflowState.AvailableHeight()) {
-    aDesiredSize.height = CalcHeight(aReflowState);
+    aDesiredSize.Height() = CalcHeight(aReflowState);
     if (GetPrevInFlow()) {
       nscoord height = CalcHeightFromUnpaginatedHeight(aPresContext, *this);
-      aDesiredSize.height = std::max(aDesiredSize.height, height);
+      aDesiredSize.Height() = std::max(aDesiredSize.Height(), height);
     }
     else {
       if (isPaginated && HasStyleHeight()) {
         // set the unpaginated height so next in flows can try to honor it
         SetHasUnpaginatedHeight(true);
-        SetUnpaginatedHeight(aPresContext, aDesiredSize.height);
+        SetUnpaginatedHeight(aPresContext, aDesiredSize.Height());
       }
       if (isPaginated && HasUnpaginatedHeight()) {
-        aDesiredSize.height = std::max(aDesiredSize.height, GetUnpaginatedHeight(aPresContext));
+        aDesiredSize.Height() = std::max(aDesiredSize.Height(), GetUnpaginatedHeight(aPresContext));
       }
     }
   }
   else { // constrained height, paginated
     // Compute the height we should have from style (subtracting the
     // height from our prev-in-flows from the style height)
     nscoord styleHeight = CalcHeightFromUnpaginatedHeight(aPresContext, *this);
     if (styleHeight > aReflowState.AvailableHeight()) {
       styleHeight = aReflowState.AvailableHeight();
       NS_FRAME_SET_INCOMPLETE(aStatus);
     }
-    aDesiredSize.height = std::max(cellMaxHeight, styleHeight);
+    aDesiredSize.Height() = std::max(cellMaxHeight, styleHeight);
   }
   aDesiredSize.UnionOverflowAreasWithDesiredBounds();
   FinishAndStoreOverflow(&aDesiredSize);
   return rv;
 }
 
 /** Layout the entire row.
   * This method stacks cells horizontally according to HTML 4.0 rules.
@@ -1047,22 +1047,22 @@ nsTableRowFrame::Reflow(nsPresContext*  
                       aStatus);
 
   if (aPresContext->IsPaginated() && !NS_FRAME_IS_FULLY_COMPLETE(aStatus) &&
       ShouldAvoidBreakInside(aReflowState)) {
     aStatus = NS_INLINE_LINE_BREAK_BEFORE();
   }
 
   // just set our width to what was available. The table will calculate the width and not use our value.
-  aDesiredSize.width = aReflowState.AvailableWidth();
+  aDesiredSize.Width() = aReflowState.AvailableWidth();
 
   // If our parent is in initial reflow, it'll handle invalidating our
   // entire overflow rect.
   if (!(GetParent()->GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
-      nsSize(aDesiredSize.width, aDesiredSize.height) != mRect.Size()) {
+      nsSize(aDesiredSize.Width(), aDesiredSize.Height()) != mRect.Size()) {
     InvalidateFrame();
   }
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return rv;
 }
 
 /**
@@ -1086,41 +1086,41 @@ nsTableRowFrame::ReflowCellFrame(nsPresC
   nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
   bool borderCollapse = tableFrame->IsBorderCollapse();
   nsTableCellReflowState cellReflowState(aPresContext, aReflowState,
                                          aCellFrame, availSize,
                                          nsHTMLReflowState::CALLER_WILL_INIT);
   InitChildReflowState(*aPresContext, availSize, borderCollapse, cellReflowState);
   cellReflowState.mFlags.mIsTopOfPage = aIsTopOfPage;
 
-  nsHTMLReflowMetrics desiredSize;
+  nsHTMLReflowMetrics desiredSize(aReflowState.GetWritingMode());
 
   ReflowChild(aCellFrame, aPresContext, desiredSize, cellReflowState,
               0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
   bool fullyComplete = NS_FRAME_IS_COMPLETE(aStatus) && !NS_FRAME_IS_TRUNCATED(aStatus);
   if (fullyComplete) {
-    desiredSize.height = aAvailableHeight;
+    desiredSize.Height() = aAvailableHeight;
   }
-  aCellFrame->SetSize(nsSize(cellRect.width, desiredSize.height));
+  aCellFrame->SetSize(nsSize(cellRect.width, desiredSize.Height()));
 
   // Note: VerticallyAlignChild can affect the overflow rect.
   // XXX What happens if this cell has 'vertical-align: baseline' ?
   // XXX Why is it assumed that the cell's ascent hasn't changed ?
   if (fullyComplete) {
     aCellFrame->VerticallyAlignChild(mMaxCellAscent);
   }
   
   nsTableFrame::InvalidateTableFrame(aCellFrame, cellRect,
                                      cellVisualOverflow,
                                      (aCellFrame->GetStateBits() &
                                       NS_FRAME_FIRST_REFLOW) != 0);
   
   aCellFrame->DidReflow(aPresContext, nullptr, nsDidReflowStatus::FINISHED);
 
-  return desiredSize.height;
+  return desiredSize.Height();
 }
 
 nscoord
 nsTableRowFrame::CollapseRowIfNecessary(nscoord aRowOffset,
                                         nscoord aWidth,
                                         bool    aCollapseGroup,
                                         bool& aDidCollapse)
 {
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -272,21 +272,21 @@ nsTableRowGroupFrame::PlaceChild(nsPresC
   // Place and size the child
   FinishReflowChild(aKidFrame, aPresContext, nullptr, aDesiredSize, 0,
                     aReflowState.y, 0);
 
   nsTableFrame::InvalidateTableFrame(aKidFrame, aOriginalKidRect,
                                      aOriginalKidVisualOverflow, isFirstReflow);
 
   // Adjust the running y-offset
-  aReflowState.y += aDesiredSize.height;
+  aReflowState.y += aDesiredSize.Height();
 
   // If our height is constrained then update the available height
   if (NS_UNCONSTRAINEDSIZE != aReflowState.availSize.height) {
-    aReflowState.availSize.height -= aDesiredSize.height;
+    aReflowState.availSize.height -= aDesiredSize.Height();
   }
 }
 
 void
 nsTableRowGroupFrame::InitChildReflowState(nsPresContext&     aPresContext, 
                                            bool               aBorderCollapse,
                                            nsHTMLReflowState& aReflowState)                                    
 {
@@ -357,18 +357,19 @@ nsTableRowGroupFrame::ReflowChildren(nsP
         (aReflowState.reflowState.mFlags.mSpecialHeightReflow &&
          (isPaginated || (kidFrame->GetStateBits() &
                           NS_FRAME_CONTAINS_RELATIVE_HEIGHT)))) {
       nsRect oldKidRect = kidFrame->GetRect();
       nsRect oldKidVisualOverflow = kidFrame->GetVisualOverflowRect();
 
       // XXXldb We used to only pass aDesiredSize.mFlags through for the
       // incremental reflow codepath.
-      nsHTMLReflowMetrics desiredSize(aDesiredSize.mFlags);
-      desiredSize.width = desiredSize.height = 0;
+      nsHTMLReflowMetrics desiredSize(aReflowState.reflowState.GetWritingMode(),
+                                      aDesiredSize.mFlags);
+      desiredSize.Width() = desiredSize.Height() = 0;
   
       // Reflow the child into the available space, giving it as much height as
       // it wants. We'll deal with splitting later after we've computed the row
       // heights, taking into account cells with row spans...
       nsSize kidAvailSize(aReflowState.availSize.width, NS_UNCONSTRAINEDSIZE);
       nsHTMLReflowState kidReflowState(aPresContext, aReflowState.reflowState,
                                        kidFrame, kidAvailSize,
                                        -1, -1,
@@ -402,20 +403,20 @@ nsTableRowGroupFrame::ReflowChildren(nsP
           // the overflow area may have changed inflate the overflow area
           const nsStylePosition *stylePos = StylePosition();
           nsStyleUnit unit = stylePos->mHeight.GetUnit();
           if (aReflowState.tableFrame->IsAutoHeight() &&
               unit != eStyleUnit_Coord) {
             // Because other cells in the row may need to be aligned
             // differently, repaint the entire row
             nsRect kidRect(0, aReflowState.y,
-                           desiredSize.width, desiredSize.height);
+                           desiredSize.Width(), desiredSize.Height());
             InvalidateFrame();
           }
-          else if (oldKidRect.height != desiredSize.height)
+          else if (oldKidRect.height != desiredSize.Height())
             needToCalcRowHeights = true;
         } else {
           needToCalcRowHeights = true;
         }
       }
 
       if (isPaginated && aPageBreakBeforeEnd && !*aPageBreakBeforeEnd) {
         nsTableRowFrame* nextRow = rowFrame->GetNextRow();
@@ -436,18 +437,18 @@ nsTableRowGroupFrame::ReflowChildren(nsP
     }
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, kidFrame);
   }
 
   if (haveRow)
     aReflowState.y -= cellSpacingY;
 
   // Return our desired rect
-  aDesiredSize.width = aReflowState.reflowState.AvailableWidth();
-  aDesiredSize.height = aReflowState.y;
+  aDesiredSize.Width() = aReflowState.reflowState.AvailableWidth();
+  aDesiredSize.Height() = aReflowState.y;
 
   if (aReflowState.reflowState.mFlags.mSpecialHeightReflow) {
     DidResizeRows(aDesiredSize);
     if (isPaginated) {
       CacheRowHeightsForPrinting(aPresContext, GetFirstRow());
     }
   }
   else if (needToCalcRowHeights) {
@@ -787,17 +788,17 @@ nsTableRowGroupFrame::CalculateRowHeight
 
   if (isPaginated && styleHeightAllocation) {
     // since the row group has a style height, cache the row heights, so next in flows can honor them 
     CacheRowHeightsForPrinting(aPresContext, GetFirstRow());
   }
 
   DidResizeRows(aDesiredSize);
 
-  aDesiredSize.height = rowGroupHeight; // Adjust our desired size
+  aDesiredSize.Height() = rowGroupHeight; // Adjust our desired size
 }
 
 nscoord
 nsTableRowGroupFrame::CollapseRowGroupIfNecessary(nscoord aYTotalOffset,
                                                   nscoord aWidth)
 {
   nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
   const nsStyleVisibility* groupVis = StyleVisibility();
@@ -1027,17 +1028,17 @@ nsTableRowGroupFrame::SplitRowGroup(nsPr
                                     nsTableFrame*            aTableFrame,
                                     nsReflowStatus&          aStatus,
                                     bool                     aRowForcedPageBreak)
 {
   NS_PRECONDITION(aPresContext->IsPaginated(), "SplitRowGroup currently supports only paged media"); 
 
   nsresult rv = NS_OK;
   nsTableRowFrame* prevRowFrame = nullptr;
-  aDesiredSize.height = 0;
+  aDesiredSize.Height() = 0;
 
   nscoord availWidth  = aReflowState.AvailableWidth();
   nscoord availHeight = aReflowState.AvailableHeight();
   
   const bool borderCollapse = aTableFrame->IsBorderCollapse();
   nscoord cellSpacingY = aTableFrame->GetCellSpacingY();
   
   // get the page height
@@ -1058,101 +1059,101 @@ nsTableRowGroupFrame::SplitRowGroup(nsPr
     bool rowIsOnPage = true;
     nsRect rowRect = rowFrame->GetRect();
     // See if the row fits on this page
     if (rowRect.YMost() > availHeight) {
       nsTableRowFrame* contRow = nullptr;
       // Reflow the row in the availabe space and have it split if it is the 1st
       // row (on the page) or there is at least 5% of the current page available 
       // XXX this 5% should be made a preference 
-      if (!prevRowFrame || (availHeight - aDesiredSize.height > pageHeight / 20)) { 
+      if (!prevRowFrame || (availHeight - aDesiredSize.Height() > pageHeight / 20)) { 
         nsSize availSize(availWidth, std::max(availHeight - rowRect.y, 0));
         // don't let the available height exceed what CalculateRowHeights set for it
         availSize.height = std::min(availSize.height, rowRect.height);
 
         nsHTMLReflowState rowReflowState(aPresContext, aReflowState,
                                          rowFrame, availSize,
                                          -1, -1,
                                          nsHTMLReflowState::CALLER_WILL_INIT);
                                          
         InitChildReflowState(*aPresContext, borderCollapse, rowReflowState);
         rowReflowState.mFlags.mIsTopOfPage = isTopOfPage; // set top of page
-        nsHTMLReflowMetrics rowMetrics;
+        nsHTMLReflowMetrics rowMetrics(aReflowState.GetWritingMode());
 
         // Get the old size before we reflow.
         nsRect oldRowRect = rowFrame->GetRect();
         nsRect oldRowVisualOverflow = rowFrame->GetVisualOverflowRect();
 
         // Reflow the cell with the constrained height. A cell with rowspan >1 will get this
         // reflow later during SplitSpanningCells.
         rv = ReflowChild(rowFrame, aPresContext, rowMetrics, rowReflowState,
                          0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
         if (NS_FAILED(rv)) return rv;
-        rowFrame->SetSize(nsSize(rowMetrics.width, rowMetrics.height));
+        rowFrame->SetSize(nsSize(rowMetrics.Width(), rowMetrics.Height()));
         rowFrame->DidReflow(aPresContext, nullptr, nsDidReflowStatus::FINISHED);
         rowFrame->DidResize();
 
         if (!aRowForcedPageBreak && !NS_FRAME_IS_FULLY_COMPLETE(aStatus) &&
             ShouldAvoidBreakInside(aReflowState)) {
           aStatus = NS_INLINE_LINE_BREAK_BEFORE();
           break;
         }
 
         nsTableFrame::InvalidateTableFrame(rowFrame, oldRowRect,
                                            oldRowVisualOverflow,
                                            false);
 
         if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
           // The row frame is incomplete and all of the rowspan 1 cells' block frames split
-          if ((rowMetrics.height <= rowReflowState.AvailableHeight()) || isTopOfPage) {
+          if ((rowMetrics.Height() <= rowReflowState.AvailableHeight()) || isTopOfPage) {
             // The row stays on this page because either it split ok or we're on the top of page.
             // If top of page and the height exceeded the avail height, then there will be data loss
-            NS_ASSERTION(rowMetrics.height <= rowReflowState.AvailableHeight(), 
+            NS_ASSERTION(rowMetrics.Height() <= rowReflowState.AvailableHeight(), 
                          "data loss - incomplete row needed more height than available, on top of page");
             CreateContinuingRowFrame(*aPresContext, *rowFrame, (nsIFrame**)&contRow);
             if (contRow) {
-              aDesiredSize.height += rowMetrics.height;
+              aDesiredSize.Height() += rowMetrics.Height();
               if (prevRowFrame) 
-                aDesiredSize.height += cellSpacingY;
+                aDesiredSize.Height() += cellSpacingY;
             }
             else return NS_ERROR_NULL_POINTER;
           }
           else {
             // Put the row on the next page to give it more height 
             rowIsOnPage = false;
           }
         } 
         else {
           // The row frame is complete because either (1) its minimum height is greater than the 
           // available height we gave it, or (2) it may have been given a larger height through 
           // style than its content, or (3) it contains a rowspan >1 cell which hasn't been
           // reflowed with a constrained height yet (we will find out when SplitSpanningCells is
           // called below)
-          if (rowMetrics.height > availSize.height ||
+          if (rowMetrics.Height() > availSize.height ||
               (NS_INLINE_IS_BREAK_BEFORE(aStatus) && !aRowForcedPageBreak)) {
             // cases (1) and (2)
             if (isTopOfPage) { 
               // We're on top of the page, so keep the row on this page. There will be data loss.
               // Push the row frame that follows
               nsTableRowFrame* nextRowFrame = rowFrame->GetNextRow();
               if (nextRowFrame) {
                 aStatus = NS_FRAME_NOT_COMPLETE;
               }
-              aDesiredSize.height += rowMetrics.height;
+              aDesiredSize.Height() += rowMetrics.Height();
               if (prevRowFrame) 
-                aDesiredSize.height += cellSpacingY;
+                aDesiredSize.Height() += cellSpacingY;
               NS_WARNING("data loss - complete row needed more height than available, on top of page");
             }
             else {
               // We're not on top of the page, so put the row on the next page to give it more height 
               rowIsOnPage = false;
             }
           }
         }
-      } //if (!prevRowFrame || (availHeight - aDesiredSize.height > pageHeight / 20))
+      } //if (!prevRowFrame || (availHeight - aDesiredSize.Height() > pageHeight / 20))
       else { 
         // put the row on the next page to give it more height
         rowIsOnPage = false;
       }
 
       nsTableRowFrame* lastRowThisPage = rowFrame;
       nscoord spanningRowBottom = availHeight;
       if (!rowIsOnPage) {
@@ -1164,17 +1165,17 @@ nsTableRowGroupFrame::SplitRowGroup(nsPr
         if (prevRowFrame) {
           spanningRowBottom = prevRowFrame->GetRect().YMost();
           lastRowThisPage = prevRowFrame;
           isTopOfPage = (lastRowThisPage == firstRowThisPage) && aReflowState.mFlags.mIsTopOfPage;
           aStatus = NS_FRAME_NOT_COMPLETE;
         }
         else {
           // We can't push children, so let our parent reflow us again with more space
-          aDesiredSize.height = rowRect.YMost();
+          aDesiredSize.Height() = rowRect.YMost();
           aStatus = NS_FRAME_COMPLETE;
           break;
         }
       }
       // reflow the cells with rowspan >1 that occur on the page
 
       nsTableRowFrame* firstTruncatedRow;
       nscoord yMost;
@@ -1184,17 +1185,17 @@ nsTableRowGroupFrame::SplitRowGroup(nsPr
       if (firstTruncatedRow) {
         // A rowspan >1 cell did not fit (and could not split) in the space we gave it
         if (firstTruncatedRow == firstRowThisPage) {
           if (aReflowState.mFlags.mIsTopOfPage) {
             NS_WARNING("data loss in a row spanned cell");
           }
           else {
             // We can't push children, so let our parent reflow us again with more space
-            aDesiredSize.height = rowRect.YMost();
+            aDesiredSize.Height() = rowRect.YMost();
             aStatus = NS_FRAME_COMPLETE;
             UndoContinuedRow(aPresContext, contRow);
             contRow = nullptr;
           }
         }
         else { // (firstTruncatedRow != firstRowThisPage)
           // Try to put firstTruncateRow on the next page 
           nsTableRowFrame* rowBefore = ::GetRowBefore(*firstRowThisPage, *firstTruncatedRow);
@@ -1205,55 +1206,55 @@ nsTableRowGroupFrame::SplitRowGroup(nsPr
           contRow = nullptr;
           nsTableRowFrame* oldLastRowThisPage = lastRowThisPage;
           lastRowThisPage = rowBefore;
           aStatus = NS_FRAME_NOT_COMPLETE;
 
           // Call SplitSpanningCells again with rowBefore as the last row on the page
           SplitSpanningCells(*aPresContext, aReflowState, *aTableFrame, 
                              *firstRowThisPage, *rowBefore, aReflowState.mFlags.mIsTopOfPage, 
-                             spanningRowBottom, contRow, firstTruncatedRow, aDesiredSize.height);
+                             spanningRowBottom, contRow, firstTruncatedRow, aDesiredSize.Height());
           if (firstTruncatedRow) {
             if (aReflowState.mFlags.mIsTopOfPage) {
               // We were better off with the 1st call to SplitSpanningCells, do it again
               UndoContinuedRow(aPresContext, contRow);
               contRow = nullptr;
               lastRowThisPage = oldLastRowThisPage;
               spanningRowBottom = oldSpanningRowBottom;
               SplitSpanningCells(*aPresContext, aReflowState, *aTableFrame, *firstRowThisPage,
                                  *lastRowThisPage, aReflowState.mFlags.mIsTopOfPage, spanningRowBottom, contRow, 
-                                 firstTruncatedRow, aDesiredSize.height);
+                                 firstTruncatedRow, aDesiredSize.Height());
               NS_WARNING("data loss in a row spanned cell");
             }
             else {
               // Let our parent reflow us again with more space
-              aDesiredSize.height = rowRect.YMost();
+              aDesiredSize.Height() = rowRect.YMost();
               aStatus = NS_FRAME_COMPLETE;
               UndoContinuedRow(aPresContext, contRow);
               contRow = nullptr;
             }
           }
         } // if (firstTruncatedRow == firstRowThisPage)
       } // if (firstTruncatedRow)
       else {
-        aDesiredSize.height = std::max(aDesiredSize.height, yMost);
+        aDesiredSize.Height() = std::max(aDesiredSize.Height(), yMost);
         if (contRow) {
           aStatus = NS_FRAME_NOT_COMPLETE;
         }
       }
       if (NS_FRAME_IS_NOT_COMPLETE(aStatus) && !contRow) {
         nsTableRowFrame* nextRow = lastRowThisPage->GetNextRow();
         if (nextRow) {
           PushChildren(aPresContext, nextRow, lastRowThisPage);
         }
       }
       break;
     } // if (rowRect.YMost() > availHeight)
     else { 
-      aDesiredSize.height = rowRect.YMost();
+      aDesiredSize.Height() = rowRect.YMost();
       prevRowFrame = rowFrame;
       // see if there is a page break after the row
       nsTableRowFrame* nextRow = rowFrame->GetNextRow();
       if (nextRow && nsTableFrame::PageBreakAfter(rowFrame, nextRow)) {
         PushChildren(aPresContext, nextRow, rowFrame);
         aStatus = NS_FRAME_NOT_COMPLETE;
         break;
       }
@@ -1303,17 +1304,17 @@ nsTableRowGroupFrame::Reflow(nsPresConte
   rv = ReflowChildren(aPresContext, aDesiredSize, state, aStatus,
                       &splitDueToPageBreak);
 
   // See if all the frames fit. Do not try to split anything if we're
   // not paginated ... we can't split across columns yet.
   if (aReflowState.mFlags.mTableIsSplittable &&
       NS_UNCONSTRAINEDSIZE != aReflowState.AvailableHeight() &&
       (NS_FRAME_NOT_COMPLETE == aStatus || splitDueToPageBreak || 
-       aDesiredSize.height > aReflowState.AvailableHeight())) {
+       aDesiredSize.Height() > aReflowState.AvailableHeight())) {
     // Nope, find a place to split the row group 
     bool specialReflow = (bool)aReflowState.mFlags.mSpecialHeightReflow;
     ((nsHTMLReflowState::ReflowStateFlags&)aReflowState.mFlags).mSpecialHeightReflow = false;
 
     SplitRowGroup(aPresContext, aDesiredSize, aReflowState, tableFrame, aStatus,
                   splitDueToPageBreak);
 
     ((nsHTMLReflowState::ReflowStateFlags&)aReflowState.mFlags).mSpecialHeightReflow = specialReflow;
@@ -1325,24 +1326,24 @@ nsTableRowGroupFrame::Reflow(nsPresConte
   if (GetNextInFlow() && GetNextInFlow()->GetFirstPrincipalChild()) {
     NS_FRAME_SET_INCOMPLETE(aStatus);
   }
 
   SetHasStyleHeight((NS_UNCONSTRAINEDSIZE != aReflowState.ComputedHeight()) &&
                     (aReflowState.ComputedHeight() > 0)); 
   
   // just set our width to what was available. The table will calculate the width and not use our value.
-  aDesiredSize.width = aReflowState.AvailableWidth();
+  aDesiredSize.Width() = aReflowState.AvailableWidth();
 
   aDesiredSize.UnionOverflowAreasWithDesiredBounds();
 
   // If our parent is in initial reflow, it'll handle invalidating our
   // entire overflow rect.
   if (!(GetParent()->GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
-      nsSize(aDesiredSize.width, aDesiredSize.height) != mRect.Size()) {
+      nsSize(aDesiredSize.Width(), aDesiredSize.Height()) != mRect.Size()) {
     InvalidateFrame();
   }
   
   FinishAndStoreOverflow(&aDesiredSize);
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return rv;
 }
 
--- a/layout/xul/nsBoxFrame.cpp
+++ b/layout/xul/nsBoxFrame.cpp
@@ -704,25 +704,25 @@ nsBoxFrame::Reflow(nsPresContext*       
   nscoord ascent = mRect.height;
 
   // getting the ascent could be a lot of work. Don't get it if
   // we are the root. The viewport doesn't care about it.
   if (!(mState & NS_STATE_IS_ROOT)) {
     ascent = GetBoxAscent(state);
   }
 
-  aDesiredSize.width  = mRect.width;
-  aDesiredSize.height = mRect.height;
-  aDesiredSize.ascent = ascent;
+  aDesiredSize.Width() = mRect.width;
+  aDesiredSize.Height() = mRect.height;
+  aDesiredSize.SetTopAscent(ascent);
 
   aDesiredSize.mOverflowAreas = GetOverflowAreas();
 
 #ifdef DO_NOISY_REFLOW
   {
-    printf("%p ** nsBF(done) W:%d H:%d  ", this, aDesiredSize.width, aDesiredSize.height);
+    printf("%p ** nsBF(done) W:%d H:%d  ", this, aDesiredSize.Width(), aDesiredSize.Height());
 
     if (maxElementSize) {
       printf("MW:%d\n", *maxElementWidth); 
     } else {
       printf("MW:?\n"); 
     }
 
   }
@@ -908,29 +908,29 @@ nsBoxFrame::DoLayout(nsBoxLayoutState& a
 
   if (HasAbsolutelyPositionedChildren()) {
     // Set up a |reflowState| to pass into ReflowAbsoluteFrames
     nsHTMLReflowState reflowState(aState.PresContext(), this,
                                   aState.GetRenderingContext(),
                                   nsSize(mRect.width, NS_UNCONSTRAINEDSIZE));
 
     // Set up a |desiredSize| to pass into ReflowAbsoluteFrames
-    nsHTMLReflowMetrics desiredSize;
-    desiredSize.width  = mRect.width;
-    desiredSize.height = mRect.height;
+    nsHTMLReflowMetrics desiredSize(reflowState.GetWritingMode());
+    desiredSize.Width() = mRect.width;
+    desiredSize.Height() = mRect.height;
 
     // get the ascent (cribbed from ::Reflow)
     nscoord ascent = mRect.height;
 
     // getting the ascent could be a lot of work. Don't get it if
     // we are the root. The viewport doesn't care about it.
     if (!(mState & NS_STATE_IS_ROOT)) {
       ascent = GetBoxAscent(aState);
     }
-    desiredSize.ascent = ascent;
+    desiredSize.SetTopAscent(ascent);
     desiredSize.mOverflowAreas = GetOverflowAreas();
 
     // Set up a |reflowStatus| to pass into ReflowAbsoluteFrames
     // (just a dummy value; hopefully that's OK)
     nsReflowStatus reflowStatus = NS_FRAME_COMPLETE;
     ReflowAbsoluteFrames(aState.PresContext(), desiredSize,
                          reflowState, reflowStatus);
   }
--- a/layout/xul/nsLeafBoxFrame.cpp
+++ b/layout/xul/nsLeafBoxFrame.cpp
@@ -288,26 +288,26 @@ nsLeafBoxFrame::Reflow(nsPresContext*   
   nsRect r(mRect.x, mRect.y, computedSize.width, computedSize.height);
 
   SetBounds(state, r);
  
   // layout our children
   Layout(state);
   
   // ok our child could have gotten bigger. So lets get its bounds
-  aDesiredSize.width  = mRect.width;
-  aDesiredSize.height = mRect.height;
-  aDesiredSize.ascent = GetBoxAscent(state);
+  aDesiredSize.Width() = mRect.width;
+  aDesiredSize.Height() = mRect.height;
+  aDesiredSize.SetTopAscent(GetBoxAscent(state));
 
   // the overflow rect is set in SetBounds() above
   aDesiredSize.mOverflowAreas = GetOverflowAreas();
 
 #ifdef DO_NOISY_REFLOW
   {
-    printf("%p ** nsLBF(done) W:%d H:%d  ", this, aDesiredSize.width, aDesiredSize.height);
+    printf("%p ** nsLBF(done) W:%d H:%d  ", this, aDesiredSize.Width(), aDesiredSize.Height());
 
     if (maxElementWidth) {
       printf("MW:%d\n", *maxElementWidth); 
     } else {
       printf("MW:?\n"); 
     }
 
   }
--- a/layout/xul/nsScrollbarFrame.cpp
+++ b/layout/xul/nsScrollbarFrame.cpp
@@ -60,20 +60,20 @@ nsScrollbarFrame::Reflow(nsPresContext* 
                          nsReflowStatus&          aStatus)
 {
   nsresult rv = nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // nsGfxScrollFrame may have told us to shrink to nothing. If so, make sure our
   // desired size agrees.
   if (aReflowState.AvailableWidth() == 0) {
-    aDesiredSize.width = 0;
+    aDesiredSize.Width() = 0;
   }
   if (aReflowState.AvailableHeight() == 0) {
-    aDesiredSize.height = 0;
+    aDesiredSize.Height() = 0;
   }
 
   return NS_OK;
 }
 
 nsIAtom*
 nsScrollbarFrame::GetType() const
 {