Bug 1138495 - pt 3 - Compute font inflation based on inline-axis dimensions rather than always using physical width. r=smontagu
authorJonathan Kew <jkew@mozilla.com>
Tue, 10 Mar 2015 14:28:23 +0000
changeset 232746 203acd3b8d71fc11e23f00808f270e7a45d686d3
parent 232745 9804af358570510831d3a46489194e2d6d942f56
child 232747 ee33df27bf15a1b28c77ce6d4f464a495b4c3d02
push id56647
push userjkew@mozilla.com
push dateTue, 10 Mar 2015 14:28:49 +0000
treeherdermozilla-inbound@ee33df27bf15 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmontagu
bugs1138495
milestone39.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 1138495 - pt 3 - Compute font inflation based on inline-axis dimensions rather than always using physical width. r=smontagu
dom/base/nsDOMWindowUtils.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/generic/nsFontInflationData.cpp
layout/generic/nsFontInflationData.h
layout/generic/nsHTMLReflowState.cpp
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -3182,26 +3182,26 @@ nsDOMWindowUtils::GetPlugins(JSContext* 
   nsresult rv = nsTArrayToJSArray(cx, plugins, &jsPlugins);
   NS_ENSURE_SUCCESS(rv, rv);
 
   aPlugins.setObject(*jsPlugins);
   return NS_OK;
 }
 
 static void
-MaybeReflowForInflationScreenWidthChange(nsPresContext *aPresContext)
+MaybeReflowForInflationScreenSizeChange(nsPresContext *aPresContext)
 {
   if (aPresContext) {
     nsIPresShell* presShell = aPresContext->GetPresShell();
     bool fontInflationWasEnabled = presShell->FontSizeInflationEnabled();
     presShell->NotifyFontSizeInflationEnabledIsDirty();
     bool changed = false;
     if (presShell && presShell->FontSizeInflationEnabled() &&
         presShell->FontSizeInflationMinTwips() != 0) {
-      aPresContext->ScreenWidthInchesForFontInflation(&changed);
+      aPresContext->ScreenSizeInchesForFontInflation(&changed);
     }
 
     changed = changed ||
       (fontInflationWasEnabled != presShell->FontSizeInflationEnabled());
     if (changed) {
       nsCOMPtr<nsIDocShell> docShell = aPresContext->GetDocShell();
       if (docShell) {
         nsCOMPtr<nsIContentViewer> cv;
@@ -3249,17 +3249,17 @@ nsDOMWindowUtils::SetScrollPositionClamp
     nsPresContext::CSSPixelsToAppUnits(aHeight));
 
   // When the "font.size.inflation.minTwips" preference is set, the
   // layout depends on the size of the screen.  Since when the size
   // of the screen changes, the scroll position clamping scroll port
   // size also changes, we hook in the needed updates here rather
   // than adding a separate notification just for this change.
   nsPresContext* presContext = GetPresContext();
-  MaybeReflowForInflationScreenWidthChange(presContext);
+  MaybeReflowForInflationScreenSizeChange(presContext);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SetContentDocumentFixedPositionMargins(float aTop, float aRight,
                                                          float aBottom, float aLeft)
 {
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -7166,41 +7166,45 @@ nsUnsetAttrRunnable::Run()
 }
 
 /**
  * Compute the minimum font size inside of a container with the given
  * width, such that **when the user zooms the container to fill the full
  * width of the device**, the fonts satisfy our minima.
  */
 static nscoord
-MinimumFontSizeFor(nsPresContext* aPresContext, nscoord aContainerWidth)
+MinimumFontSizeFor(nsPresContext* aPresContext, WritingMode aWritingMode,
+                   nscoord aContainerISize)
 {
   nsIPresShell* presShell = aPresContext->PresShell();
 
   uint32_t emPerLine = presShell->FontSizeInflationEmPerLine();
   uint32_t minTwips = presShell->FontSizeInflationMinTwips();
   if (emPerLine == 0 && minTwips == 0) {
     return 0;
   }
 
   // Clamp the container width to the device dimensions
-  nscoord iFrameWidth = aPresContext->GetVisibleArea().width;
-  nscoord effectiveContainerWidth = std::min(iFrameWidth, aContainerWidth);
+  nscoord iFrameISize = aWritingMode.IsVertical()
+    ? aPresContext->GetVisibleArea().height
+    : aPresContext->GetVisibleArea().width;
+  nscoord effectiveContainerISize = std::min(iFrameISize, aContainerISize);
 
   nscoord byLine = 0, byInch = 0;
   if (emPerLine != 0) {
-    byLine = effectiveContainerWidth / emPerLine;
+    byLine = effectiveContainerISize / emPerLine;
   }
   if (minTwips != 0) {
     // REVIEW: Is this giving us app units and sizes *not* counting
     // viewport scaling?
-    float deviceWidthInches =
-      aPresContext->ScreenWidthInchesForFontInflation();
-    byInch = NSToCoordRound(effectiveContainerWidth /
-                            (deviceWidthInches * 1440 /
+    gfxSize screenSize = aPresContext->ScreenSizeInchesForFontInflation();
+    float deviceISizeInches = aWritingMode.IsVertical()
+      ? screenSize.height : screenSize.width;
+    byInch = NSToCoordRound(effectiveContainerISize /
+                            (deviceISizeInches * 1440 /
                              minTwips ));
   }
   return std::max(byLine, byInch);
 }
 
 /* static */ float
 nsLayoutUtils::FontSizeInflationInner(const nsIFrame *aFrame,
                                       nscoord aMinFontSize)
@@ -7338,17 +7342,18 @@ nsLayoutUtils::InflationMinFontSizeFor(c
         nsFontInflationData::FindFontInflationDataFor(aFrame);
       // FIXME: The need to null-check here is sort of a bug, and might
       // lead to incorrect results.
       if (!data || !data->InflationEnabled()) {
         return 0;
       }
 
       return MinimumFontSizeFor(aFrame->PresContext(),
-                                data->EffectiveWidth());
+                                aFrame->GetWritingMode(),
+                                data->EffectiveISize());
     }
   }
 
   MOZ_ASSERT(false, "root should always be container");
 
   return 0;
 }
 
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -186,17 +186,18 @@ IsVisualCharset(const nsCString& aCharse
   }
 }
 
   // NOTE! nsPresContext::operator new() zeroes out all members, so don't
   // bother initializing members to 0.
 
 nsPresContext::nsPresContext(nsIDocument* aDocument, nsPresContextType aType)
   : mType(aType), mDocument(aDocument), mBaseMinFontSize(0),
-    mTextZoom(1.0), mFullZoom(1.0), mLastFontInflationScreenWidth(-1.0),
+    mTextZoom(1.0), mFullZoom(1.0),
+    mLastFontInflationScreenSize(gfxSize(-1.0, -1.0)),
     mPageSize(-1, -1), mPPScale(1.0f),
     mViewportStyleScrollbar(NS_STYLE_OVERFLOW_AUTO, NS_STYLE_OVERFLOW_AUTO),
     mImageAnimationModePref(imgIContainer::kNormalAnimMode),
     mAllInvalidated(false),
     mPaintFlashing(false), mPaintFlashingInitialized(false)
 {
   // NOTE! nsPresContext::operator new() zeroes out all members, so don't
   // bother initializing members to 0.
@@ -1500,39 +1501,40 @@ nsPresContext::SetFullZoom(float aZoom)
     SetWindowDimensions(NSToCoordRound(oldWidthDevPixels * AppUnitsPerDevPixel()),
                         NSToCoordRound(oldHeightDevPixels * AppUnitsPerDevPixel()));
 
   AppUnitsPerDevPixelChanged();
 
   mSupressResizeReflow = false;
 }
 
-float
-nsPresContext::ScreenWidthInchesForFontInflation(bool* aChanged)
+gfxSize
+nsPresContext::ScreenSizeInchesForFontInflation(bool* aChanged)
 {
   if (aChanged) {
     *aChanged = false;
   }
 
   nsDeviceContext *dx = DeviceContext();
   nsRect clientRect;
   dx->GetClientRect(clientRect); // FIXME: GetClientRect looks expensive
-  float deviceWidthInches =
-    float(clientRect.width) / float(dx->AppUnitsPerPhysicalInch());
-
-  if (mLastFontInflationScreenWidth == -1.0) {
-    mLastFontInflationScreenWidth = deviceWidthInches;
+  float unitsPerInch = dx->AppUnitsPerPhysicalInch();
+  gfxSize deviceSizeInches(float(clientRect.width) / unitsPerInch,
+                           float(clientRect.height) / unitsPerInch);
+
+  if (mLastFontInflationScreenSize == gfxSize(-1.0, -1.0)) {
+    mLastFontInflationScreenSize = deviceSizeInches;
   }
 
-  if (deviceWidthInches != mLastFontInflationScreenWidth && aChanged) {
+  if (deviceSizeInches != mLastFontInflationScreenSize && aChanged) {
     *aChanged = true;
-    mLastFontInflationScreenWidth = deviceWidthInches;
+    mLastFontInflationScreenSize = deviceSizeInches;
   }
 
-  return deviceWidthInches;
+  return deviceSizeInches;
 }
 
 void
 nsPresContext::SetContainer(nsIDocShell* aDocShell)
 {
   if (aDocShell) {
     mContainer = static_cast<nsDocShell*>(aDocShell);
   } else {
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -587,25 +587,25 @@ public:
   float GetFullZoom() { return mFullZoom; }
   void SetFullZoom(float aZoom);
 
   nscoord GetAutoQualityMinFontSize() {
     return DevPixelsToAppUnits(mAutoQualityMinFontSizePixelsPref);
   }
 
   /**
-   * Return the device's screen width in inches, for font size
+   * Return the device's screen size in inches, for font size
    * inflation.
    *
    * If |aChanged| is non-null, then aChanged is filled in with whether
-   * the return value has changed since either:
+   * the screen size value has changed since either:
    *  a. the last time the function was called with non-null aChanged, or
    *  b. the first time the function was called.
    */
-  float ScreenWidthInchesForFontInflation(bool* aChanged = nullptr);
+  gfxSize ScreenSizeInchesForFontInflation(bool* aChanged = nullptr);
 
   static int32_t AppUnitsPerCSSPixel() { return mozilla::AppUnitsPerCSSPixel(); }
   int32_t AppUnitsPerDevPixel() const;
   static int32_t AppUnitsPerCSSInch() { return mozilla::AppUnitsPerCSSInch(); }
 
   static nscoord CSSPixelsToAppUnits(int32_t aPixels)
   { return NSToCoordRoundWithClamp(float(aPixels) *
              float(AppUnitsPerCSSPixel())); }
@@ -1254,17 +1254,17 @@ protected:
 
   mozilla::WeakPtr<nsDocShell>             mContainer;
 
   // Base minimum font size, independent of the language-specific global preference. Defaults to 0
   int32_t               mBaseMinFontSize;
   float                 mTextZoom;      // Text zoom, defaults to 1.0
   float                 mFullZoom;      // Page zoom, defaults to 1.0
 
-  float                 mLastFontInflationScreenWidth;
+  gfxSize               mLastFontInflationScreenSize;
 
   int32_t               mCurAppUnitsPerDevPixel;
   int32_t               mAutoQualityMinFontSizePixelsPref;
 
   nsCOMPtr<nsITheme> mTheme;
   nsCOMPtr<nsILanguageAtomService> mLangService;
   nsCOMPtr<nsIPrintSettings> mPrintSettings;
   nsCOMPtr<nsITimer>    mPrefChangedTimer;
--- a/layout/generic/nsFontInflationData.cpp
+++ b/layout/generic/nsFontInflationData.cpp
@@ -27,43 +27,43 @@ nsFontInflationData::FindFontInflationDa
   NS_ASSERTION(bfc->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT,
                "should have found a flow root");
 
   return static_cast<nsFontInflationData*>(
              bfc->Properties().Get(FontInflationDataProperty()));
 }
 
 /* static */ bool
-nsFontInflationData::UpdateFontInflationDataWidthFor(const nsHTMLReflowState& aReflowState)
+nsFontInflationData::UpdateFontInflationDataISizeFor(const nsHTMLReflowState& aReflowState)
 {
   nsIFrame *bfc = aReflowState.frame;
   NS_ASSERTION(bfc->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT,
                "should have been given a flow root");
   FrameProperties bfcProps(bfc->Properties());
   nsFontInflationData *data = static_cast<nsFontInflationData*>(
                                 bfcProps.Get(FontInflationDataProperty()));
   bool oldInflationEnabled;
-  nscoord oldNCAWidth;
+  nscoord oldNCAISize;
   if (data) {
-    oldNCAWidth = data->mNCAWidth;
+    oldNCAISize = data->mNCAISize;
     oldInflationEnabled = data->mInflationEnabled;
   } else {
     data = new nsFontInflationData(bfc);
     bfcProps.Set(FontInflationDataProperty(), data);
-    oldNCAWidth = -1;
+    oldNCAISize = -1;
     oldInflationEnabled = true; /* not relevant */
   }
 
-  data->UpdateWidth(aReflowState);
+  data->UpdateISize(aReflowState);
 
   if (oldInflationEnabled != data->mInflationEnabled)
     return true;
 
   return oldInflationEnabled &&
-         oldNCAWidth != data->mNCAWidth;
+         oldNCAISize != data->mNCAISize;
 }
 
 /* static */ void
 nsFontInflationData::MarkFontInflationDataTextDirty(nsIFrame *aBFCFrame)
 {
   NS_ASSERTION(aBFCFrame->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT,
                "should have been given a flow root");
 
@@ -72,17 +72,17 @@ nsFontInflationData::MarkFontInflationDa
                                 bfcProps.Get(FontInflationDataProperty()));
   if (data) {
     data->MarkTextDirty();
   }
 }
 
 nsFontInflationData::nsFontInflationData(nsIFrame *aBFCFrame)
   : mBFCFrame(aBFCFrame)
-  , mNCAWidth(0)
+  , mNCAISize(0)
   , mTextAmount(0)
   , mTextThreshold(0)
   , mInflationEnabled(false)
   , mTextDirty(true)
 {
 }
 
 /**
@@ -119,31 +119,31 @@ NearestCommonAncestorFirstInFlow(nsIFram
     }
     result = ancestors1[i1];
   }
 
   return result;
 }
 
 static nscoord
-ComputeDescendantWidth(const nsHTMLReflowState& aAncestorReflowState,
+ComputeDescendantISize(const nsHTMLReflowState& aAncestorReflowState,
                        nsIFrame *aDescendantFrame)
 {
   nsIFrame *ancestorFrame = aAncestorReflowState.frame->FirstInFlow();
   if (aDescendantFrame == ancestorFrame) {
-    return aAncestorReflowState.ComputedWidth();
+    return aAncestorReflowState.ComputedISize();
   }
 
   AutoInfallibleTArray<nsIFrame*, 16> frames;
   for (nsIFrame *f = aDescendantFrame; f != ancestorFrame;
        f = f->GetParent()->FirstInFlow()) {
     frames.AppendElement(f);
   }
 
-  // This ignores the width contributions made by scrollbars, though in
+  // This ignores the inline-size contributions made by scrollbars, though in
   // reality we don't have any scrollbars on the sorts of devices on
   // which we use font inflation, so it's not a problem.  But it may
   // occasionally cause problems when writing tests on desktop.
 
   uint32_t len = frames.Length();
   nsHTMLReflowState *reflowStates = static_cast<nsHTMLReflowState*>
                                 (moz_xmalloc(sizeof(nsHTMLReflowState) * len));
   nsPresContext *presContext = aDescendantFrame->PresContext();
@@ -158,28 +158,28 @@ ComputeDescendantWidth(const nsHTMLReflo
                  parentReflowState.frame->FirstInFlow(),
                "bad logic in this function");
     new (reflowStates + i) nsHTMLReflowState(presContext, parentReflowState,
                                              frame, availSize);
   }
 
   MOZ_ASSERT(reflowStates[len - 1].frame == aDescendantFrame,
              "bad logic in this function");
-  nscoord result = reflowStates[len - 1].ComputedWidth();
+  nscoord result = reflowStates[len - 1].ComputedISize();
 
   for (uint32_t i = len; i-- != 0; ) {
     reflowStates[i].~nsHTMLReflowState();
   }
   moz_free(reflowStates);
 
   return result;
 }
 
 void
-nsFontInflationData::UpdateWidth(const nsHTMLReflowState &aReflowState)
+nsFontInflationData::UpdateISize(const nsHTMLReflowState &aReflowState)
 {
   nsIFrame *bfc = aReflowState.frame;
   NS_ASSERTION(bfc->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT,
                "must be block formatting context");
 
   nsIFrame *firstInflatableDescendant =
              FindEdgeInflatableFrameIn(bfc, eFromStart);
   if (!firstInflatableDescendant) {
@@ -190,40 +190,40 @@ nsFontInflationData::UpdateWidth(const n
     return;
   }
   nsIFrame *lastInflatableDescendant =
              FindEdgeInflatableFrameIn(bfc, eFromEnd);
   MOZ_ASSERT(!firstInflatableDescendant == !lastInflatableDescendant,
              "null-ness should match; NearestCommonAncestorFirstInFlow"
              " will crash when passed null");
 
-  // Particularly when we're computing for the root BFC, the width of
-  // nca might differ significantly for the width of bfc.
+  // Particularly when we're computing for the root BFC, the inline-size of
+  // nca might differ significantly for the inline-size of bfc.
   nsIFrame *nca = NearestCommonAncestorFirstInFlow(firstInflatableDescendant,
                                                    lastInflatableDescendant,
                                                    bfc);
   while (!nca->IsContainerForFontSizeInflation()) {
     nca = nca->GetParent()->FirstInFlow();
   }
 
-  nscoord newNCAWidth = ComputeDescendantWidth(aReflowState, nca);
+  nscoord newNCAISize = ComputeDescendantISize(aReflowState, nca);
 
   // See comment above "font.size.inflation.lineThreshold" in
   // modules/libpref/src/init/all.js .
   nsIPresShell* presShell = bfc->PresContext()->PresShell();
   uint32_t lineThreshold = presShell->FontSizeInflationLineThreshold();
-  nscoord newTextThreshold = (newNCAWidth * lineThreshold) / 100;
+  nscoord newTextThreshold = (newNCAISize * lineThreshold) / 100;
 
   if (mTextThreshold <= mTextAmount && mTextAmount < newTextThreshold) {
     // Because we truncate our scan when we hit sufficient text, we now
     // need to rescan.
     mTextDirty = true;
   }
 
-  mNCAWidth = newNCAWidth;
+  mNCAISize = newNCAISize;
   mTextThreshold = newTextThreshold;
   mInflationEnabled = mTextAmount >= mTextThreshold;
 }
 
 /* static */ nsIFrame*
 nsFontInflationData::FindEdgeInflatableFrameIn(nsIFrame* aFrame,
                                                SearchDirection aDirection)
 {
--- a/layout/generic/nsFontInflationData.h
+++ b/layout/generic/nsFontInflationData.h
@@ -16,60 +16,60 @@ class nsFontInflationData
 {
 public:
 
   static nsFontInflationData* FindFontInflationDataFor(const nsIFrame *aFrame);
 
   // Returns whether the effective width changed (which requires the
   // caller to mark its descendants dirty
   static bool
-    UpdateFontInflationDataWidthFor(const nsHTMLReflowState& aReflowState);
+    UpdateFontInflationDataISizeFor(const nsHTMLReflowState& aReflowState);
 
   static void MarkFontInflationDataTextDirty(nsIFrame *aFrame);
 
   bool InflationEnabled() {
     if (mTextDirty) {
       ScanText();
     }
     return mInflationEnabled;
   }
 
-  nscoord EffectiveWidth() const {
-    return mNCAWidth;
+  nscoord EffectiveISize() const {
+    return mNCAISize;
   }
 
 private:
 
   explicit nsFontInflationData(nsIFrame* aBFCFrame);
 
   nsFontInflationData(const nsFontInflationData&) = delete;
   void operator=(const nsFontInflationData&) = delete;
 
-  void UpdateWidth(const nsHTMLReflowState &aReflowState);
+  void UpdateISize(const nsHTMLReflowState &aReflowState);
   enum SearchDirection { eFromStart, eFromEnd };
   static nsIFrame* FindEdgeInflatableFrameIn(nsIFrame *aFrame,
                                              SearchDirection aDirection);
 
   void MarkTextDirty() { mTextDirty = true; }
   void ScanText();
   // Scan text in the subtree rooted at aFrame.  Increment mTextAmount
   // by multiplying the number of characters found by the font size
-  // (yielding the width that would be occupied by the characters if
+  // (yielding the inline-size that would be occupied by the characters if
   // they were all em squares).  But stop scanning if mTextAmount
   // crosses mTextThreshold.
   void ScanTextIn(nsIFrame *aFrame);
 
   static const nsIFrame* FlowRootFor(const nsIFrame *aFrame)
   {
     while (!(aFrame->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT)) {
       aFrame = aFrame->GetParent();
     }
     return aFrame;
   }
 
   nsIFrame *mBFCFrame;
-  nscoord mNCAWidth;
+  nscoord mNCAISize;
   nscoord mTextAmount, mTextThreshold;
   bool mInflationEnabled; // for this BFC
   bool mTextDirty;
 };
 
 #endif /* !defined(nsFontInflationData_h_) */
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -500,17 +500,17 @@ nsHTMLReflowState::InitResizeFlags(nsPre
   bool isHResize = (frame->GetSize().width !=
                      ComputedWidth() + ComputedPhysicalBorderPadding().LeftRight()) ||
                      aPresContext->PresShell()->IsReflowOnZoomPending();
 
   if ((frame->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT) &&
       nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) {
     // Create our font inflation data if we don't have it already, and
     // give it our current width information.
-    bool dirty = nsFontInflationData::UpdateFontInflationDataWidthFor(*this) &&
+    bool dirty = nsFontInflationData::UpdateFontInflationDataISizeFor(*this) &&
                  // Avoid running this at the box-to-block interface
                  // (where we shouldn't be inflating anyway, and where
                  // reflow state construction is probably to construct a
                  // dummy parent reflow state anyway).
                  !mFlags.mDummyParentReflowState;
 
     if (dirty || (!frame->GetParent() && isHResize)) {
       // When font size inflation is enabled, a change in either: