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 177826 72591e9d49a8432c45b304c7ccb86a8e09947bb1
parent 177825 10592ba2f6950f6473d6d443c6f340fbc4d6621e
child 177827 07f8896db19cbc95ac470406e0b810f8e68eed8b
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmontagu
bugs735577
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 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
 {