Bug 1289701 - Find the root style context by walkng up the style context tree instead of calling ResolveStyleFor or getting it from root element's primary frame. r=dbaron
authorHiroyuki Ikezoe <hiikezoe@mozilla-japan.org>
Wed, 30 Nov 2016 07:46:27 +0900
changeset 324749 2e6d1dafee00c988288f4b8e3023d4df7bf792fc
parent 324748 5897fbfa16c965eed37783bbe0c2edfd919edcf6
child 324750 754af8c55a9d7f6e786eb1258192fbdd8b364a23
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersdbaron
bugs1289701
milestone53.0a1
Bug 1289701 - Find the root style context by walkng up the style context tree instead of calling ResolveStyleFor or getting it from root element's primary frame. r=dbaron The only call site of CalcLengthWith() with a null style context is CalcLengthWithInitialFont(). CalcLengthWithInitialFont() calls CalcLengthWith() with a valid nsStyleFont and aUseProvidedRootEmSize true, so we can get the rem unit font size from the nsStyleFont when called from CalcLengthWithInitialFont(). MozReview-Commit-ID: A9LKfQEozaB
layout/style/nsRuleNode.cpp
layout/style/nsRuleNode.h
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -437,34 +437,39 @@ static nsSize CalcViewportUnitsScale(nsP
         viewportSize.width -= sizes.LeftRight();
       }
     }
   }
 
   return viewportSize;
 }
 
+// If |aStyleFont| is nullptr, aStyleContext->StyleFont() is used.
+//
+// In case that |aValue| is rem unit, if |aStyleContext| is null, callers must
+// specify a valid |aStyleFont| and |aUseProvidedRootEmSize| must be true so
+// that we can get the length from |aStyleFont|.
 static nscoord CalcLengthWith(const nsCSSValue& aValue,
                               nscoord aFontSize,
                               const nsStyleFont* aStyleFont,
                               nsStyleContext* aStyleContext,
                               nsPresContext* aPresContext,
                               bool aUseProvidedRootEmSize,
                               // aUseUserFontSet should always be true
                               // except when called from
                               // CalcLengthWithInitialFont.
                               bool aUseUserFontSet,
                               RuleNodeCacheConditions& aConditions)
 {
   NS_ASSERTION(aValue.IsLengthUnit() || aValue.IsCalcUnit(),
                "not a length or calc unit");
   NS_ASSERTION(aStyleFont || aStyleContext,
                "Must have style data");
-  NS_ASSERTION(!aStyleFont || !aStyleContext,
-               "Duplicate sources of data");
+  NS_ASSERTION(aStyleContext || aUseProvidedRootEmSize,
+               "Must have style context or specify aUseProvidedRootEmSize");
   NS_ASSERTION(aPresContext, "Must have prescontext");
 
   if (aValue.IsFixedLengthUnit()) {
     return aValue.GetFixedLength(aPresContext);
   }
   if (aValue.IsPixelLengthUnit()) {
     return aValue.GetPixelLength();
   }
@@ -549,31 +554,22 @@ static nscoord CalcLengthWith(const nsCS
         // This is the root element (XXX we don't really know this, but
         // nsRuleNode::SetFont makes the same assumption!), so we should
         // use StyleFont on this context to get the root element's
         // font size.
         rootFontSize = styleFont->mFont.size;
       } else {
         // This is not the root element or we are calculating something other
         // than font size, so rem is relative to the root element's font size.
-        RefPtr<nsStyleContext> rootStyle;
-        const nsStyleFont *rootStyleFont = styleFont;
-        Element* docElement = aPresContext->Document()->GetRootElement();
-
-        if (docElement) {
-          nsIFrame* rootFrame = docElement->GetPrimaryFrame();
-          if (rootFrame) {
-            rootStyle = rootFrame->StyleContext();
-          } else {
-            rootStyle = aPresContext->StyleSet()->AsGecko()->ResolveStyleFor(docElement,
-                                                                             nullptr);
-          }
-          rootStyleFont = rootStyle->StyleFont();
+        // Find the root style context by walking up the style context tree.
+        nsStyleContext* rootStyle = aStyleContext;
+        while (rootStyle->GetParent()) {
+          rootStyle = rootStyle->GetParent();
         }
-
+        const nsStyleFont *rootStyleFont = rootStyle->StyleFont();
         rootFontSize = rootStyleFont->mFont.size;
       }
 
       return ScaleCoordRound(aValue, float(rootFontSize));
     }
     default:
       // Fall through to the code for units that can't be stored in the
       // rule tree because they depend on font data.
@@ -3318,40 +3314,44 @@ struct SetFontSizeCalcOps : public css::
   // resolve coeff_type (BasicCoordCalcOps and FloatCoeffsAlreadyNormalizedOps
   // both have |typedef float coeff_type|).
   typedef float coeff_type;
 
   // The parameters beyond aValue that we need for CalcLengthWith.
   const nscoord mParentSize;
   const nsStyleFont* const mParentFont;
   nsPresContext* const mPresContext;
+  nsStyleContext* const mStyleContext;
   const bool mAtRoot;
   RuleNodeCacheConditions& mConditions;
 
   SetFontSizeCalcOps(nscoord aParentSize, const nsStyleFont* aParentFont,
-                     nsPresContext* aPresContext, bool aAtRoot,
+                     nsPresContext* aPresContext,
+                     nsStyleContext* aStyleContext,
+                     bool aAtRoot,
                      RuleNodeCacheConditions& aConditions)
     : mParentSize(aParentSize),
       mParentFont(aParentFont),
       mPresContext(aPresContext),
+      mStyleContext(aStyleContext),
       mAtRoot(aAtRoot),
       mConditions(aConditions)
   {
   }
 
   result_type ComputeLeafValue(const nsCSSValue& aValue)
   {
     nscoord size;
     if (aValue.IsLengthUnit()) {
       // Note that font-based length units use the parent's size
       // unadjusted for scriptlevel changes. A scriptlevel change
       // between us and the parent is simply ignored.
       size = CalcLengthWith(aValue, mParentSize,
                             mParentFont,
-                            nullptr, mPresContext, mAtRoot,
+                            mStyleContext, mPresContext, mAtRoot,
                             true, mConditions);
       if (!aValue.IsRelativeLengthUnit() && mParentFont->mAllowZoom) {
         size = nsStyleFont::ZoomText(mPresContext, size);
       }
     }
     else if (eCSSUnit_Percent == aValue.GetUnit()) {
       mConditions.SetUncacheable();
       // Note that % units use the parent's size unadjusted for scriptlevel
@@ -3365,16 +3365,17 @@ struct SetFontSizeCalcOps : public css::
     }
 
     return size;
   }
 };
 
 /* static */ void
 nsRuleNode::SetFontSize(nsPresContext* aPresContext,
+                        nsStyleContext* aContext,
                         const nsRuleData* aRuleData,
                         const nsStyleFont* aFont,
                         const nsStyleFont* aParentFont,
                         nscoord* aSize,
                         const nsFont& aSystemFont,
                         nscoord aParentSize,
                         nscoord aScriptLevelAdjustedParentSize,
                         bool aUsedStartStruct,
@@ -3431,17 +3432,18 @@ nsRuleNode::SetFontSize(nsPresContext* a
     } else {
       NS_NOTREACHED("unexpected value");
     }
   }
   else if (sizeValue->IsLengthUnit() ||
            sizeValue->GetUnit() == eCSSUnit_Percent ||
            sizeValue->IsCalcUnit()) {
     SetFontSizeCalcOps ops(aParentSize, aParentFont,
-                           aPresContext, aAtRoot,
+                           aPresContext, aContext,
+                           aAtRoot,
                            aConditions);
     *aSize = css::ComputeCalc(*sizeValue, ops);
     if (*aSize < 0) {
       MOZ_ASSERT(sizeValue->IsCalcUnit(),
                  "negative lengths and percents should be rejected by parser");
       *aSize = 0;
     }
     // The calc ops will always zoom its result according to the value
@@ -3777,17 +3779,17 @@ nsRuleNode::SetFont(nsPresContext* aPres
   const nsCSSValue* scriptMinSizeValue = aRuleData->ValueForScriptMinSize();
   if (scriptMinSizeValue->IsLengthUnit()) {
     // scriptminsize in font units (em, ex) has to be interpreted relative
     // to the parent font, or the size definitions are circular and we
     //
     aFont->mScriptMinSize =
       CalcLengthWith(*scriptMinSizeValue, aParentFont->mSize,
                      aParentFont,
-                     nullptr, aPresContext, atRoot, true,
+                     aContext, aPresContext, atRoot, true /* aUseUserFontSet */,
                      aConditions);
   }
 
   // -moz-script-size-multiplier: factor, inherit, initial
   SetFactor(*aRuleData->ValueForScriptSizeMultiplier(),
             aFont->mScriptSizeMultiplier,
             aConditions, aParentFont->mScriptSizeMultiplier,
             NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER,
@@ -4019,17 +4021,18 @@ nsRuleNode::SetFont(nsPresContext* aPres
   // Compute whether we're affected by scriptMinSize *before* calling
   // SetFontSize, since aParentFont might be the same as aFont.  If it
   // is, calling SetFontSize might throw off our calculation.
   bool affectedByScriptMinSize =
     aParentFont->mSize != aParentFont->mScriptUnconstrainedSize ||
     scriptLevelAdjustedParentSize !=
       scriptLevelAdjustedUnconstrainedParentSize;
 
-  SetFontSize(aPresContext, aRuleData, aFont, aParentFont,
+  SetFontSize(aPresContext, aContext,
+              aRuleData, aFont, aParentFont,
               &aFont->mSize,
               systemFont, aParentFont->mSize, scriptLevelAdjustedParentSize,
               aUsedStartStruct, atRoot, aConditions);
   if (!aPresContext->Document()->GetMathMLEnabled()) {
     MOZ_ASSERT(!affectedByScriptMinSize);
     // If MathML is not enabled, we don't need to mark this node as
     // uncacheable.  If it becomes enabled, code in
     // nsMathMLElementFactory will rebuild the rule tree and style data
@@ -4049,17 +4052,18 @@ nsRuleNode::SetFont(nsPresContext* aPres
     // see previous else-if
     aConditions.SetUncacheable();
 
     // Use a separate conditions object because it might get a
     // *different* font-size dependency.  We can ignore it because we've
     // already called SetUncacheable.
     RuleNodeCacheConditions unconstrainedConditions;
 
-    SetFontSize(aPresContext, aRuleData, aFont, aParentFont,
+    SetFontSize(aPresContext, aContext,
+                aRuleData, aFont, aParentFont,
                 &aFont->mScriptUnconstrainedSize,
                 systemFont, aParentFont->mScriptUnconstrainedSize,
                 scriptLevelAdjustedUnconstrainedParentSize,
                 aUsedStartStruct, atRoot, unconstrainedConditions);
   }
   NS_ASSERTION(aFont->mScriptUnconstrainedSize <= aFont->mSize,
                "scriptminsize should never be making things bigger");
 
--- a/layout/style/nsRuleNode.h
+++ b/layout/style/nsRuleNode.h
@@ -750,16 +750,17 @@ protected:
     ComputeEffectsData(void* aStartStruct,
                        const nsRuleData* aRuleData,
                        nsStyleContext* aContext, nsRuleNode* aHighestNode,
                        RuleDetail aRuleDetail,
                        const mozilla::RuleNodeCacheConditions aConditions);
 
   // helpers for |ComputeFontData| that need access to |mNoneBits|:
   static void SetFontSize(nsPresContext* aPresContext,
+                          nsStyleContext* aContext,
                           const nsRuleData* aRuleData,
                           const nsStyleFont* aFont,
                           const nsStyleFont* aParentFont,
                           nscoord* aSize,
                           const nsFont& aSystemFont,
                           nscoord aParentSize,
                           nscoord aScriptLevelAdjustedParentSize,
                           bool aUsedStartStruct,