Switch nsLayoutUtils inflation methods to the new setup with state on the pres context. (Bug 706609, patch 5) r=roc
authorL. David Baron <dbaron@dbaron.org>
Tue, 24 Jan 2012 17:21:29 -0800
changeset 86530 561d7fded0cced29bf18f2bbd05eeb72b33a61da
parent 86529 8213675b8a78cc6e8d9c43e5ebdfe66786ae02e5
child 86531 7a0cbba01ab568f6f3ff700e7a39a05f1ee950d2
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs706609
milestone12.0a1
Switch nsLayoutUtils inflation methods to the new setup with state on the pres context. (Bug 706609, patch 5) r=roc This is the third of three patches to rework the way we handle getting the font inflation container and width data during reflow, which are needed so that we can sometimes honor inflation during intrinsic width calculation (which we need to do to make some form controls inflate correctly).
content/events/src/nsEventStateManager.cpp
layout/base/nsCaret.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/forms/nsListControlFrame.cpp
layout/forms/nsListControlFrame.h
layout/forms/nsProgressFrame.cpp
layout/forms/nsSelectsAreaFrame.cpp
layout/forms/nsTextControlFrame.cpp
layout/generic/TextOverflow.cpp
layout/generic/nsBRFrame.cpp
layout/generic/nsBlockFrame.cpp
layout/generic/nsBulletFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsHTMLReflowState.cpp
layout/generic/nsImageFrame.cpp
layout/generic/nsInlineFrame.cpp
layout/generic/nsLineLayout.cpp
layout/generic/nsTextFrameThebes.cpp
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -2544,17 +2544,18 @@ GetScrollableLineHeight(nsIFrame* aTarge
     nsIScrollableFrame* sf = f->GetScrollTargetFrame();
     if (sf)
       return sf->GetLineScrollAmount().height;
   }
 
   // Fall back to the font height of the target frame.
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(aTargetFrame, getter_AddRefs(fm),
-    nsLayoutUtils::FontSizeInflationFor(aTargetFrame));
+    nsLayoutUtils::FontSizeInflationFor(aTargetFrame,
+                                        nsLayoutUtils::eNotInReflow));
   NS_ASSERTION(fm, "FontMetrics is null!");
   if (fm)
     return fm->MaxHeight();
   return 0;
 }
 
 void
 nsEventStateManager::SendLineScrollEvent(nsIFrame* aTargetFrame,
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -346,17 +346,17 @@ nsCaret::GetGeometryForFrame(nsIFrame* a
     return rv;
 
   nsIFrame *frame = aFrame->GetContentInsertionFrame();
   NS_ASSERTION(frame, "We should not be in the middle of reflow");
   nscoord baseline = frame->GetCaretBaseline();
   nscoord ascent = 0, descent = 0;
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm),
-    nsLayoutUtils::FontSizeInflationFor(aFrame));
+    nsLayoutUtils::FontSizeInflationFor(aFrame, nsLayoutUtils::eNotInReflow));
   NS_ASSERTION(fm, "We should be able to get the font metrics");
   if (fm) {
     ascent = fm->MaxAscent();
     descent = fm->MaxDescent();
   }
   nscoord height = ascent + descent;
   framePos.y = baseline - ascent;
   Metrics caretMetrics = ComputeMetrics(aFrame, aFrameOffset, height);
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -4712,207 +4712,96 @@ ShouldInflateFontsForContainer(const nsI
   // height (propagating down the tree), but the propagation stops when
   // we hit overflow-y: scroll or auto.
   return aFrame->GetStyleText()->mTextSizeAdjust !=
            NS_STYLE_TEXT_SIZE_ADJUST_NONE &&
          !(aFrame->GetStateBits() & NS_FRAME_IN_CONSTRAINED_HEIGHT);
 }
 
 nscoord
-nsLayoutUtils::InflationMinFontSizeFor(const nsHTMLReflowState &aReflowState)
+nsLayoutUtils::InflationMinFontSizeFor(const nsIFrame *aFrame,
+                                       WidthDetermination aWidthDetermination)
 {
 #ifdef DEBUG
-  {
-    const nsHTMLReflowState *rs = &aReflowState;
-    nsIFrame *f = aReflowState.frame;
-    for (; rs; rs = rs->parentReflowState, f = f->GetParent()) {
-      NS_ABORT_IF_FALSE(rs->frame == f,
-                        "reflow state parentage must match frame parentage");
-      nsIScrollableFrame *sf;
-      NS_ABORT_IF_FALSE(rs->parentReflowState ||
-                        IsContainerForFontSizeInflation(f) ||
-                        // OK if NS_FRAME_IN_REFLOW is not set on
-                        // (non-null) parent, since its ancestors have a
-                        // real size.  (Do we set NS_FRAME_IN_REFLOW
-                        // correctly for xul?)
-                        !(f->GetParent()->GetStateBits() &
-                          NS_FRAME_IN_REFLOW) ||
-                        // ugly exception, but ok because the
-                        // child is a container
-                        (f->GetType() == nsGkAtoms::scrollFrame &&
-                         (sf = do_QueryFrame(f)) &&
-                         (IsContainerForFontSizeInflation(
-                            sf->GetScrolledFrame()))),
-                        "must hit container at top of reflow state chain");
-    }
-  }
-#endif
-
-  if (!FontSizeInflationEnabled(aReflowState.frame->PresContext())) {
-    return 0;
-  }
-
-  nsIFrame *reflowRoot = nsnull;
-  for (const nsHTMLReflowState *rs = &aReflowState; rs;
-       reflowRoot = rs->frame, rs = rs->parentReflowState) {
-    if (IsContainerForFontSizeInflation(rs->frame)) {
-      if (!ShouldInflateFontsForContainer(rs->frame)) {
-        return 0;
+  if (aWidthDetermination == eNotInReflow) {
+    // Check that neither this frame nor any of its ancestors are
+    // currently being reflowed.
+    // It's ok for box frames (but not arbitrary ancestors of box frames)
+    // since they set their size before reflow.
+    if (!(aFrame->IsBoxFrame() && IsContainerForFontSizeInflation(aFrame))) {
+      for (const nsIFrame *f = aFrame; f; f = f->GetParent()) {
+        NS_ABORT_IF_FALSE(!(f->GetStateBits() & NS_FRAME_IN_REFLOW),
+                          "must call nsHTMLReflowState& version during reflow");
       }
-
-      NS_ABORT_IF_FALSE(rs->ComputedWidth() != NS_INTRINSICSIZE,
-                        "must have a computed width");
-      return MinimumFontSizeFor(aReflowState.frame->PresContext(),
-                                rs->ComputedWidth());
     }
-  }
-
-  // We've hit the end of the reflow state chain.  There are two
-  // possibilities now:  we're either at a reflow root or we're crossing
-  // into flexbox layout.  (Note that sometimes we cross into and out of
-  // flexbox layout on the same frame, e.g., for nsTextControlFrame,
-  // which breaks the reflow state parentage chain.)
-  // This code depends on:
-  //  * When we cross from HTML to XUL and then on the child jump back
-  //    to HTML again, we link the reflow states correctly (see hack in
-  //    nsFrame::BoxReflow setting reflowState.parentReflowState).
-  //  * For any other cases, the XUL frame is a font size inflation
-  //    container, so we won't cross back into HTML (see the conditions
-  //    under which we test the assertion in
-  //    InflationMinFontSizeFor(const nsIFrame *).
-
-  return InflationMinFontSizeFor(reflowRoot->GetParent());
-}
-
-nscoord
-nsLayoutUtils::InflationMinFontSizeFor(const nsIFrame *aFrame)
-{
-#ifdef DEBUG
-  // Check that neither this frame nor any of its ancestors are
-  // currently being reflowed.
-  // It's ok for box frames (but not arbitrary ancestors of box frames)
-  // since they set their size before reflow.
-  if (!(aFrame->IsBoxFrame() && IsContainerForFontSizeInflation(aFrame))) {
-    for (const nsIFrame *f = aFrame; f; f = f->GetParent()) {
-      NS_ABORT_IF_FALSE(!(f->GetStateBits() & NS_FRAME_IN_REFLOW),
-                        "must call nsHTMLReflowState& version during reflow");
-    }
-  }
-  // It's ok if frames are dirty, or even if they've never been
-  // reflowed, since they will be eventually and then we'll get the
-  // right size.
+    // It's ok if frames are dirty, or even if they've never been
+    // reflowed, since they will be eventually and then we'll get the
+    // right size.
+  }
 #endif
 
   if (!FontSizeInflationEnabled(aFrame->PresContext())) {
     return 0;
   }
 
+  if (aWidthDetermination == eInReflow) {
+    nsPresContext *presContext = aFrame->PresContext();
+    nsIFrame *container = presContext->mCurrentInflationContainer;
+    if (!container || !ShouldInflateFontsForContainer(container)) {
+      return 0;
+    }
+    return MinimumFontSizeFor(presContext,
+                              presContext->mCurrentInflationContainerWidth);
+  }
+
   for (const nsIFrame *f = aFrame; f; f = f->GetParent()) {
     if (IsContainerForFontSizeInflation(f)) {
       if (!ShouldInflateFontsForContainer(f)) {
         return 0;
       }
 
       return MinimumFontSizeFor(aFrame->PresContext(),
                                 f->GetContentRect().width);
     }
   }
 
   NS_ABORT_IF_FALSE(false, "root should always be container");
 
   return 0;
 }
 
-/* static */ nscoord
-nsLayoutUtils::InflationMinFontSizeFor(const nsIFrame *aFrame,
-                                       nscoord aInflationContainerWidth)
-{
-  if (!FontSizeInflationEnabled(aFrame->PresContext())) {
-    return 0;
-  }
-
-  for (const nsIFrame *f = aFrame; f; f = f->GetParent()) {
-    if (IsContainerForFontSizeInflation(f)) {
-      if (!ShouldInflateFontsForContainer(f)) {
-        return 0;
-      }
-
-      // The caller is (sketchily) asserting that it picked the right
-      // container when passing aInflationContainerWidth.  We only do
-      // this for text inputs and a few other limited situations.
-      return MinimumFontSizeFor(aFrame->PresContext(),
-                                aInflationContainerWidth);
-    }
-  }
-
-  NS_ABORT_IF_FALSE(false, "root should always be container");
-
-  return 0;
-}
-
 float
-nsLayoutUtils::FontSizeInflationFor(const nsHTMLReflowState &aReflowState)
+nsLayoutUtils::FontSizeInflationFor(const nsIFrame *aFrame,
+                                    WidthDetermination aWidthDetermination)
 {
 #ifdef DEBUG
-  {
-    const nsHTMLReflowState *rs = &aReflowState;
-    const nsIFrame *f = aReflowState.frame;
-    for (; rs; rs = rs->parentReflowState, f = f->GetParent()) {
-      NS_ABORT_IF_FALSE(rs->frame == f,
-                        "reflow state parentage must match frame parentage");
+  if (aWidthDetermination == eNotInReflow) {
+    // Check that neither this frame nor any of its ancestors are
+    // currently being reflowed.
+    // It's ok for box frames (but not arbitrary ancestors of box frames)
+    // since they set their size before reflow.
+    if (!(aFrame->IsBoxFrame() && IsContainerForFontSizeInflation(aFrame))) {
+      for (const nsIFrame *f = aFrame; f; f = f->GetParent()) {
+        NS_ABORT_IF_FALSE(!(f->GetStateBits() & NS_FRAME_IN_REFLOW),
+                          "must call nsHTMLReflowState& version during reflow");
+      }
     }
-  }
-#endif
-
-  if (!FontSizeInflationEnabled(aReflowState.frame->PresContext())) {
-    return 1.0;
-  }
-
-  return FontSizeInflationInner(aReflowState.frame,
-             InflationMinFontSizeFor(aReflowState));
-}
-
-float
-nsLayoutUtils::FontSizeInflationFor(const nsIFrame *aFrame)
-{
-#ifdef DEBUG
-  // Check that neither this frame nor any of its ancestors are
-  // currently being reflowed.
-  // It's ok for box frames (but not arbitrary ancestors of box frames)
-  // since they set their size before reflow.
-  if (!(aFrame->IsBoxFrame() && IsContainerForFontSizeInflation(aFrame))) {
-    for (const nsIFrame *f = aFrame; f; f = f->GetParent()) {
-      NS_ABORT_IF_FALSE(!(f->GetStateBits() & NS_FRAME_IN_REFLOW),
-                        "must call nsHTMLReflowState& version during reflow");
-    }
-  }
-  // It's ok if frames are dirty, or even if they've never been
-  // reflowed, since they will be eventually and then we'll get the
-  // right size.
+    // It's ok if frames are dirty, or even if they've never been
+    // reflowed, since they will be eventually and then we'll get the
+    // right size.
+  }
 #endif
 
   if (!FontSizeInflationEnabled(aFrame->PresContext())) {
     return 1.0;
   }
 
   return FontSizeInflationInner(aFrame,
-                                InflationMinFontSizeFor(aFrame));
-}
-
-/* static */ float
-nsLayoutUtils::FontSizeInflationFor(const nsIFrame *aFrame,
-                                    nscoord aInflationContainerWidth)
-{
-  if (!FontSizeInflationEnabled(aFrame->PresContext())) {
-    return 1.0;
-  }
-
-  return FontSizeInflationInner(aFrame,
                                 InflationMinFontSizeFor(aFrame,
-                                  aInflationContainerWidth));
+                                                        aWidthDetermination));
 }
 
 /* static */ bool
 nsLayoutUtils::FontSizeInflationEnabled(nsPresContext *aPresContext)
 {
   return (sFontSizeInflationEmPerLine != 0 ||
           sFontSizeInflationMinTwips != 0) &&
          !aPresContext->IsChrome();
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1512,44 +1512,41 @@ public:
     return aFrame->GetStateBits() & NS_FRAME_FONT_INFLATION_CONTAINER;
   }
 
   /**
    * Return the font size inflation *ratio* for a given frame.  This is
    * the factor by which font sizes should be inflated; it is never
    * smaller than 1.
    *
-   * There are three variants: pass a reflow state if the frame or any
-   * of its ancestors are currently being reflowed and a frame
-   * otherwise, or, if you know the width of the inflation container (a
-   * somewhat sketchy assumption), its width.
+   * The WidthDetermination parameter says how we determine the width of
+   * the nearest inflation container:  when not in reflow we look at the
+   * frame tree; when in reflow we look at state stored on the pres
+   * context.
    */
-  static float FontSizeInflationFor(const nsHTMLReflowState &aReflowState);
-  static float FontSizeInflationFor(const nsIFrame *aFrame);
+  enum WidthDetermination { eNotInReflow, eInReflow };
   static float FontSizeInflationFor(const nsIFrame *aFrame,
-                                    nscoord aInflationContainerWidth);
+                                    WidthDetermination aWidthDetermination);
 
   /**
    * Perform the first half of the computation of FontSizeInflationFor
    * (see above).
    * This includes determining whether inflation should be performed
    * within this container and returning 0 if it should not be.
    *
    * The result is guaranteed not to vary between line participants
    * (inlines, text frames) within a line.
    *
    * The result should not be used directly since font sizes slightly
    * above the minimum should always be adjusted as done by
    * FontSizeInflationInner.
    */
-  static nscoord InflationMinFontSizeFor(const nsHTMLReflowState
-                                                 &aReflowState);
-  static nscoord InflationMinFontSizeFor(const nsIFrame *aFrame);
   static nscoord InflationMinFontSizeFor(const nsIFrame *aFrame,
-                                         nscoord aInflationContainerWidth);
+                                         WidthDetermination
+                                           aWidthDetermination);
 
   /**
    * Perform the second half of the computation done by
    * FontSizeInflationFor (see above).
    *
    * aMinFontSize must be the result of one of the
    *   InflationMinFontSizeFor methods above.
    */
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -252,17 +252,18 @@ void nsListControlFrame::PaintFocus(nsRe
 
   nsRect fRect;
   if (childframe) {
     // get the child rect
     fRect = childframe->GetRect();
     // get it into our coordinates
     fRect.MoveBy(childframe->GetParent()->GetOffsetTo(this));
   } else {
-    float inflation = nsLayoutUtils::FontSizeInflationFor(this);
+    float inflation = nsLayoutUtils::FontSizeInflationFor(this,
+                        nsLayoutUtils::eNotInReflow);
     fRect.x = fRect.y = 0;
     fRect.width = GetScrollPortRect().width;
     fRect.height = CalcFallbackRowHeight(inflation);
     fRect.MoveBy(containerFrame->GetOffsetTo(this));
   }
   fRect += aPt;
   
   bool lastItemIsSelected = false;
@@ -289,23 +290,19 @@ nsListControlFrame::InvalidateFocus(cons
   if (mFocused != this)
     return;
 
   nsIFrame* containerFrame = GetOptionsContainer();
   if (containerFrame) {
     // Invalidating from the containerFrame because that's where our focus
     // is drawn.
     // The origin of the scrollport is the origin of containerFrame.
-    float inflation;
-    if (aReflowState) {
-      NS_ABORT_IF_FALSE(aReflowState->frame == this, "wrong reflow state");
-      inflation = nsLayoutUtils::FontSizeInflationFor(*aReflowState);
-    } else {
-      inflation = nsLayoutUtils::FontSizeInflationFor(this);
-    }
+    float inflation = nsLayoutUtils::FontSizeInflationFor(this,
+                        aReflowState ? nsLayoutUtils::eInReflow
+                                     : nsLayoutUtils::eNotInReflow);
     nsRect invalidateArea = containerFrame->GetVisualOverflowRect();
     nsRect emptyFallbackArea(0, 0, GetScrollPortRect().width,
                              CalcFallbackRowHeight(inflation));
     invalidateArea.UnionRect(invalidateArea, emptyFallbackArea);
     containerFrame->Invalidate(invalidateArea);
   }
 }
 
@@ -369,33 +366,30 @@ GetNumberOfOptionsRecursive(nsIContent* 
   }
   return optionCount;
 }
 
 //-----------------------------------------------------------------
 // Main Reflow for ListBox/Dropdown
 //-----------------------------------------------------------------
 
-// Note that it doesn't much matter *which* reflow state aReflowState
-// is (as long as it's in the right block); we intentionally pass
-// whatever reflow state is most convenient.
 nscoord
-nsListControlFrame::CalcHeightOfARow(const nsHTMLReflowState& aReflowState)
+nsListControlFrame::CalcHeightOfARow()
 {
   // Calculate the height of a single row in the listbox or dropdown list by
   // using the tallest thing in the subtree, since there may be option groups
   // in addition to option elements, either of which may be visible or
   // invisible, may use different fonts, etc.
   PRInt32 heightOfARow = GetMaxOptionHeight(GetOptionsContainer());
 
   // Check to see if we have zero items (and optimize by checking
   // heightOfARow first)
   if (heightOfARow == 0 && GetNumberOfOptions() == 0) {
-    nscoord minFontSize = nsLayoutUtils::InflationMinFontSizeFor(aReflowState);
-    float inflation = nsLayoutUtils::FontSizeInflationInner(this, minFontSize);
+    float inflation =
+      nsLayoutUtils::FontSizeInflationInner(this, nsLayoutUtils::eInReflow);
     heightOfARow = CalcFallbackRowHeight(inflation);
   }
 
   return heightOfARow;
 }
 
 nscoord
 nsListControlFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
@@ -509,17 +503,17 @@ nsListControlFrame::Reflow(nsPresContext
     NS_ASSERTION(!IsScrollbarUpdateSuppressed(),
                  "Shouldn't be suppressing if we don't need a second pass!");
     if (!autoHeight) {
       // Update our mNumDisplayRows based on our new row height now that we
       // know it.  Note that if autoHeight and we landed in this code then we
       // already set mNumDisplayRows in CalcIntrinsicHeight.  Also note that we
       // can't use HeightOfARow() here because that just uses a cached value
       // that we didn't compute.
-      nscoord rowHeight = CalcHeightOfARow(aReflowState);
+      nscoord rowHeight = CalcHeightOfARow();
       if (rowHeight == 0) {
         // Just pick something
         mNumDisplayRows = 1;
       } else {
         mNumDisplayRows = NS_MAX(1, state.ComputedHeight() / rowHeight);
       }
     }
 
--- a/layout/forms/nsListControlFrame.h
+++ b/layout/forms/nsListControlFrame.h
@@ -243,17 +243,17 @@ public:
    * Pass non-null aReflowState if during reflow.
    */
   void InvalidateFocus(const nsHTMLReflowState* aReflowState = nsnull);
 
   /**
    * Function to calculate the height a row, for use with the "size" attribute.
    * Can't be const because GetNumberOfOptions() isn't const.
    */
-  nscoord CalcHeightOfARow(const nsHTMLReflowState& aReflowState);
+  nscoord CalcHeightOfARow();
 
   /**
    * Function to ask whether we're currently in what might be the
    * first pass of a two-pass reflow.
    */
   bool MightNeedSecondPass() const {
     return mMightNeedSecondPass;
   }
--- a/layout/forms/nsProgressFrame.cpp
+++ b/layout/forms/nsProgressFrame.cpp
@@ -265,17 +265,17 @@ nsProgressFrame::AttributeChanged(PRInt3
 
 nsSize
 nsProgressFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
                                  nsSize aCBSize, nscoord aAvailableWidth,
                                  nsSize aMargin, nsSize aBorder,
                                  nsSize aPadding, bool aShrinkWrap)
 {
   float inflation =
-    nsLayoutUtils::FontSizeInflationFor(this, aCBSize.width);
+    nsLayoutUtils::FontSizeInflationFor(this, nsLayoutUtils::eInReflow);
   nsRefPtr<nsFontMetrics> fontMet;
   NS_ENSURE_SUCCESS(nsLayoutUtils::GetFontMetricsForFrame(this,
                                                           getter_AddRefs(fontMet),
                                                           inflation),
                     nsSize(0, 0));
 
   nsSize autoSize;
   autoSize.height = autoSize.width = fontMet->Font().size; // 1em
--- a/layout/forms/nsSelectsAreaFrame.cpp
+++ b/layout/forms/nsSelectsAreaFrame.cpp
@@ -229,17 +229,17 @@ nsSelectsAreaFrame::Reflow(nsPresContext
   
   nsresult rv = nsBlockFrame::Reflow(aPresContext, aDesiredSize,
                                     aReflowState, aStatus);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Check whether we need to suppress scrolbar 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(aReflowState);
+    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 ||
                               oldHeight != GetSize().height))) {
       mHeightOfARow = newHeightOfARow;
       list->SetSuppressScrollbarUpdate(true);
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -493,24 +493,18 @@ nsTextControlFrame::GetMinWidth(nsRender
 }
 
 nsSize
 nsTextControlFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
                                     nsSize aCBSize, nscoord aAvailableWidth,
                                     nsSize aMargin, nsSize aBorder,
                                     nsSize aPadding, bool aShrinkWrap)
 {
-  float inflation;
-  if (nsLayoutUtils::IsContainerForFontSizeInflation(this)) {
-    // FIXME: This won't turn out so well for the height; maybe disable
-    // inflation entirely in this case?
-    inflation = 1.0f;
-  } else {
-    inflation = nsLayoutUtils::FontSizeInflationFor(this, aCBSize.width);
-  }
+  float inflation =
+    nsLayoutUtils::FontSizeInflationFor(this, nsLayoutUtils::eInReflow);
   nsSize autoSize;
   nsresult rv = CalcIntrinsicSize(aRenderingContext, autoSize, inflation);
   if (NS_FAILED(rv)) {
     // What now?
     autoSize.SizeTo(0, 0);
   }
 #ifdef DEBUG
   // Note: Ancestor ComputeAutoSize only computes a width if we're auto-width
@@ -607,34 +601,18 @@ nsTextControlFrame::GetMaxSize(nsBoxLayo
 }
 
 nscoord
 nsTextControlFrame::GetBoxAscent(nsBoxLayoutState& aState)
 {
   // Return the baseline of the first (nominal) row, with centering for
   // single-line controls.
 
-  float inflation;
-  if (nsLayoutUtils::IsContainerForFontSizeInflation(this)) {
-    inflation =
-      nsLayoutUtils::FontSizeInflationFor(this, GetContentRect().width);
-  } else {
-    const nsHTMLReflowState *outerReflowState = aState.OuterReflowState();
-    NS_ASSERTION(outerReflowState || !mParent || mParent->IsBoxFrame() ||
-                 !(mParent->GetStateBits() & NS_FRAME_IN_REFLOW),
-                 "when a text control is reflowed by one of its ancestors "
-                 "and its parent is non-XUL, we should have the outer "
-                 "reflow state in the box layout state");
-    if (outerReflowState && outerReflowState->frame == this) {
-      inflation = nsLayoutUtils::FontSizeInflationFor(*outerReflowState);
-    } else {
-      inflation = nsLayoutUtils::FontSizeInflationInner(this,
-                    nsLayoutUtils::InflationMinFontSizeFor(mParent));
-    }
-  }
+  float inflation =
+    nsLayoutUtils::FontSizeInflationFor(this, nsLayoutUtils::eInReflow);
 
   // First calculate the ascent wrt the client rect
   nsRect clientRect;
   GetClientRect(clientRect);
   nscoord lineHeight =
     IsSingleLineTextControl() ? clientRect.height :
     nsHTMLReflowState::CalcLineHeight(GetStyleContext(), NS_AUTOHEIGHT,
                                       inflation);
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -232,17 +232,17 @@ nsDisplayTextOverflowMarker::Paint(nsDis
 }
 
 void
 nsDisplayTextOverflowMarker::PaintTextToContext(nsRenderingContext* aCtx,
                                                 nsPoint aOffsetFromRect)
 {
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(mFrame, getter_AddRefs(fm),
-    nsLayoutUtils::FontSizeInflationFor(mFrame));
+    nsLayoutUtils::FontSizeInflationFor(mFrame, nsLayoutUtils::eNotInReflow));
   aCtx->SetFont(fm);
   gfxFloat y = nsLayoutUtils::GetSnappedBaselineY(mFrame, aCtx->ThebesContext(),
                                                   mRect.y, mAscent);
   nsPoint baselinePt(mRect.x, NSToCoordFloor(y));
   nsLayoutUtils::DrawString(mFrame, aCtx, mString.get(),
                             mString.Length(), baselinePt + aOffsetFromRect);
 }
 
@@ -731,17 +731,17 @@ TextOverflow::Marker::SetupString(nsIFra
 {
   if (mInitialized) {
     return;
   }
   nsRefPtr<nsRenderingContext> rc =
     aFrame->PresContext()->PresShell()->GetReferenceRenderingContext();
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm),
-    nsLayoutUtils::FontSizeInflationFor(aFrame));
+    nsLayoutUtils::FontSizeInflationFor(aFrame, nsLayoutUtils::eNotInReflow));
   rc->SetFont(fm);
 
   mMarkerString = mStyle->mType == NS_STYLE_TEXT_OVERFLOW_ELLIPSIS ?
                     GetEllipsis(fm) : mStyle->mString;
   mWidth = nsLayoutUtils::GetStringWidth(aFrame, rc, mMarkerString.get(),
                                          mMarkerString.Length());
   mIntrinsicWidth = mWidth;
   mInitialized = true;
--- a/layout/generic/nsBRFrame.cpp
+++ b/layout/generic/nsBRFrame.cpp
@@ -146,17 +146,17 @@ BRFrame::Reflow(nsPresContext* aPresCont
       // line-height makes this necessary to make BR cause a line
       // of the full line-height
 
       // We also do this in strict mode because BR should act like a
       // 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(aReflowState));
+        nsLayoutUtils::FontSizeInflationFor(this, nsLayoutUtils::eInReflow));
       aReflowState.rendContext->SetFont(fm); // FIXME: maybe not needed?
       if (fm) {
         nscoord logicalHeight = aReflowState.CalcLineHeight();
         aMetrics.height = logicalHeight;
         aMetrics.ascent =
           nsLayoutUtils::GetCenteredFontBaseline(fm, logicalHeight);
       }
       else {
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -558,21 +558,21 @@ nsBlockFrame::GetCaretBaseline() const
   if (!mLines.empty()) {
     const_line_iterator line = begin_lines();
     const nsLineBox* firstLine = line;
     if (firstLine->GetChildCount()) {
       return bp.top + firstLine->mFirstChild->GetCaretBaseline();
     }
   }
   nsRefPtr<nsFontMetrics> fm;
-  nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
-    nsLayoutUtils::FontSizeInflationFor(this));
+  float inflation =
+    nsLayoutUtils::FontSizeInflationFor(this, nsLayoutUtils::eNotInReflow);
+  nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm), inflation);
   return nsLayoutUtils::GetCenteredFontBaseline(fm, nsHTMLReflowState::
-      CalcLineHeight(GetStyleContext(), contentRect.height,
-      nsLayoutUtils::FontSizeInflationFor(this))) +
+      CalcLineHeight(GetStyleContext(), contentRect.height, inflation)) +
     bp.top;
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // Child frame enumeration
 
 nsFrameList
 nsBlockFrame::GetChildList(ChildListID aListID) const
@@ -2341,17 +2341,17 @@ nsBlockFrame::ReflowDirtyLines(nsBlockRe
 
       if (metrics.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE &&
           !nsLayoutUtils::GetFirstLineBaseline(mBullet, &metrics.ascent)) {
         metrics.ascent = metrics.height;
       }
 
       nsRefPtr<nsFontMetrics> fm;
       nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
-        nsLayoutUtils::FontSizeInflationFor(aState.mReflowState));
+        nsLayoutUtils::FontSizeInflationFor(this, nsLayoutUtils::eInReflow));
       aState.mReflowState.rendContext->SetFont(fm); // FIXME: needed?
 
       nscoord minAscent =
         nsLayoutUtils::GetCenteredFontBaseline(fm, aState.mMinLineHeight);
       nscoord minDescent = aState.mMinLineHeight - minAscent;
 
       aState.mY += NS_MAX(minAscent, metrics.ascent) +
                    NS_MAX(minDescent, metrics.height - metrics.ascent);
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -1413,17 +1413,18 @@ NS_IMETHODIMP
 nsBulletFrame::Reflow(nsPresContext* aPresContext,
                       nsHTMLReflowMetrics& aMetrics,
                       const nsHTMLReflowState& aReflowState,
                       nsReflowStatus& aStatus)
 {
   DO_GLOBAL_REFLOW_COUNT("nsBulletFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
 
-  float inflation = nsLayoutUtils::FontSizeInflationFor(aReflowState);
+  float inflation =
+    nsLayoutUtils::FontSizeInflationFor(this, nsLayoutUtils::eInReflow);
   SetFontSizeInflation(inflation);
 
   // Get the base size
   GetDesiredSize(aPresContext, aReflowState.rendContext, aMetrics, inflation);
 
   // Add in the border and padding; split the top/bottom between the
   // ascent and descent to make things look nice
   const nsMargin& borderPadding = aReflowState.mComputedBorderPadding;
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -7622,18 +7622,18 @@ nsFrame::BoxReflow(nsBoxLayoutState&    
     // messes up dimensions.
     const nsHTMLReflowState *outerReflowState = aState.OuterReflowState();
     NS_ASSERTION(!outerReflowState || outerReflowState->frame != this,
                  "in and out of XUL on a single frame?");
     if (outerReflowState && outerReflowState->frame == parentFrame) {
       // We're a frame (such as a text control frame) that jumps into
       // box reflow and then straight out of it on the child frame.
       // This means we actually have a real parent reflow state.
-      // nsLayoutUtils::InflationMinFontSizeFor needs this to be linked
-      // up correctly for text control frames, so do so here).
+      // nsLayoutUtils::InflationMinFontSizeFor used to need this to be
+      // linked up correctly for text control frames, so do so here).
       reflowState.parentReflowState = outerReflowState;
       reflowState.mCBReflowState = outerReflowState;
     } else {
       reflowState.parentReflowState = &parentReflowState;
       reflowState.mCBReflowState = &parentReflowState;
     }
     reflowState.mReflowDepth = aState.GetReflowDepth();
 
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -2236,17 +2236,17 @@ nsGfxScrollFrameInner::ScrollBy(nsIntPoi
   }
 }
 
 nsSize
 nsGfxScrollFrameInner::GetLineScrollAmount() const
 {
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(mOuter, getter_AddRefs(fm),
-    nsLayoutUtils::FontSizeInflationFor(mOuter));
+    nsLayoutUtils::FontSizeInflationFor(mOuter, nsLayoutUtils::eNotInReflow));
   NS_ASSERTION(fm, "FontMetrics is null, assuming fontHeight == 1 appunit");
   nscoord fontHeight = 1;
   if (fm) {
     fontHeight = fm->MaxHeight();
   }
 
   return nsSize(fontHeight, fontHeight);
 }
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -2208,17 +2208,18 @@ ComputeLineHeight(nsStyleContext* aStyle
 nscoord
 nsHTMLReflowState::CalcLineHeight() const
 {
   nscoord blockHeight =
     nsLayoutUtils::IsNonWrapperBlock(frame) ? mComputedHeight :
     (mCBReflowState ? mCBReflowState->mComputedHeight : NS_AUTOHEIGHT);
 
   return CalcLineHeight(frame->GetStyleContext(), blockHeight,
-                        nsLayoutUtils::FontSizeInflationFor(*this));
+                        nsLayoutUtils::FontSizeInflationFor(frame,
+                          nsLayoutUtils::eInReflow));
 }
 
 /* static */ nscoord
 nsHTMLReflowState::CalcLineHeight(nsStyleContext* aStyleContext,
                                   nscoord aBlockHeight,
                                   float aFontSizeInflation)
 {
   NS_PRECONDITION(aStyleContext, "Must have a style context");
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -983,17 +983,17 @@ nsImageFrame::DisplayAltText(nsPresConte
                              nsRenderingContext& aRenderingContext,
                              const nsString&      aAltText,
                              const nsRect&        aRect)
 {
   // Set font and color
   aRenderingContext.SetColor(GetStyleColor()->mColor);
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
-    nsLayoutUtils::FontSizeInflationFor(this));
+    nsLayoutUtils::FontSizeInflationFor(this, nsLayoutUtils::eNotInReflow));
   aRenderingContext.SetFont(fm);
 
   // Format the text to display within the formatting rect
 
   nscoord maxAscent = fm->MaxAscent();
   nscoord maxDescent = fm->MaxDescent();
   nscoord height = fm->MaxHeight();
 
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -641,17 +641,18 @@ nsInlineFrame::ReflowFrames(nsPresContex
   if (NS_FRAME_IS_COMPLETE(aStatus) &&
       !GetLastInFlow()->GetNextContinuation() &&
       !nsLayoutUtils::FrameIsNonLastInIBSplit(this)) {
     aMetrics.width += ltr ? aReflowState.mComputedBorderPadding.right
                           : aReflowState.mComputedBorderPadding.left;
   }
 
   nsRefPtr<nsFontMetrics> fm;
-  float inflation = nsLayoutUtils::FontSizeInflationFor(aReflowState);
+  float inflation =
+    nsLayoutUtils::FontSizeInflationFor(this, nsLayoutUtils::eInReflow);
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm), inflation);
   aReflowState.rendContext->SetFont(fm);
 
   if (fm) {
     // Compute final height of the frame.
     //
     // 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
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -115,17 +115,18 @@ nsLineLayout::nsLineLayout(nsPresContext
   mStyleText = aOuterReflowState->frame->GetStyleText();
   mLineNumber = 0;
   mFlags = 0; // default all flags to false except those that follow here...
   mTotalPlacedFrames = 0;
   mTopEdge = 0;
   mTrimmableWidth = 0;
 
   mInflationMinFontSize =
-    nsLayoutUtils::InflationMinFontSizeFor(*aOuterReflowState);
+    nsLayoutUtils::InflationMinFontSizeFor(aOuterReflowState->frame,
+                                           nsLayoutUtils::eInReflow);
 
   // Instead of always pre-initializing the free-lists for frames and
   // spans, we do it on demand so that situations that only use a few
   // frames and spans won't waste a lot of time in unneeded
   // initialization.
   PL_INIT_ARENA_POOL(&mArena, "nsLineLayout", 1024);
   mFrameFreeList = nsnull;
   mSpanFreeList = nsnull;
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -4616,17 +4616,18 @@ nsTextFrame::UnionAdditionalOverflow(nsP
     // Since CSS 2.1 requires that text-decoration defined on ancestors maintain
     // style and position, they can be drawn at virtually any y-offset, so
     // maxima and minima are required to reliably generate the rectangle for
     // them
     TextDecorations textDecs;
     GetTextDecorations(aPresContext, textDecs);
     if (textDecs.HasDecorationLines()) {
       nscoord inflationMinFontSize =
-        nsLayoutUtils::InflationMinFontSizeFor(aBlockReflowState);
+        nsLayoutUtils::InflationMinFontSizeFor(aBlockReflowState.frame,
+                                               nsLayoutUtils::eInReflow);
 
       const nscoord width = GetSize().width;
       const gfxFloat appUnitsPerDevUnit = aPresContext->AppUnitsPerDevPixel(),
                      gfxWidth = width / appUnitsPerDevUnit,
                      ascent = gfxFloat(mAscent) / appUnitsPerDevUnit;
       nscoord top(nscoord_MAX), bottom(nscoord_MIN);
       // Below we loop through all text decorations and compute the rectangle
       // containing all of them, in this frame's coordinate space
@@ -5603,17 +5604,17 @@ nsTextFrame::DrawTextRunAndDecorations(
     gfxSize decSize(width / app, 0);
     const gfxFloat ascent = gfxFloat(mAscent) / app;
     const gfxFloat frameTop = aFramePt.y;
 
     gfxRect dirtyRect(aDirtyRect.x / app, aDirtyRect.y / app,
                       aDirtyRect.Width() / app, aDirtyRect.Height() / app);
 
     nscoord inflationMinFontSize =
-      nsLayoutUtils::InflationMinFontSizeFor(this);
+      nsLayoutUtils::InflationMinFontSizeFor(this, nsLayoutUtils::eNotInReflow);
 
     // Underlines
     for (PRUint32 i = aDecorations.mUnderlines.Length(); i-- > 0; ) {
       const LineDecoration& dec = aDecorations.mUnderlines[i];
 
       float inflation = nsLayoutUtils::FontSizeInflationInner(dec.mFrame,
                           inflationMinFontSize);
       const gfxFont::Metrics metrics =
@@ -7342,19 +7343,18 @@ nsTextFrame::ReflowText(nsLineLayout& aL
         SetLength(offset + length - GetContentOffset(), &aLineLayout,
                   ALLOW_FRAME_CREATION_AND_DESTRUCTION);
         // Ensure that the textrun will be rebuilt
         ClearTextRuns();
       }
     } 
   }
 
-  float fontSizeInflation = nsLayoutUtils::FontSizeInflationInner(this,
-                              nsLayoutUtils::InflationMinFontSizeFor(
-                                *aLineLayout.GetLineContainerRS()));
+  float fontSizeInflation = nsLayoutUtils::FontSizeInflationFor(this,
+                              nsLayoutUtils::eInReflow);
 
   if (fontSizeInflation != GetFontSizeInflation()) {
     // FIXME: Ideally, if we already have a text run, we'd move it to be
     // the uninflated text run.
     ClearTextRun(nsnull, nsTextFrame::eInflated);
   }
 
   gfxSkipCharsIterator iter =