Bug 416581, part 1 - Move mLanguage from nsStyleVisibility to nsStyleFont. r=dbaron.
authorJonathan Watt <jwatt@jwatt.org>
Tue, 24 Jan 2012 13:09:55 +0000
changeset 86445 cfc432c9bfd14eb0d36fd893f4b41dd817915abc
parent 86444 a60f021bab003ce65863c84cda423673f1c73e8f
child 86446 15050562b814cbba3003632c5e35209b2489328e
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)
reviewersdbaron
bugs416581
milestone12.0a1
Bug 416581, part 1 - Move mLanguage from nsStyleVisibility to nsStyleFont. r=dbaron.
content/canvas/src/nsCanvasRenderingContext2D.cpp
content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
content/html/content/src/nsGenericHTMLElement.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsPresShell.cpp
layout/generic/nsTextFrameThebes.cpp
layout/mathml/nsMathMLChar.cpp
layout/style/nsCSSPropList.h
layout/style/nsRuleNode.cpp
layout/style/nsRuleNode.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/svg/base/src/nsSVGGlyphFrame.cpp
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -2535,17 +2535,17 @@ nsCanvasRenderingContext2D::SetFont(cons
     nsRefPtr<nsStyleContext> sc =
         styleSet->ResolveStyleForRules(parentContext, rules);
     if (!sc)
         return NS_ERROR_FAILURE;
     const nsStyleFont* fontStyle = sc->GetStyleFont();
 
     NS_ASSERTION(fontStyle, "Could not obtain font style");
 
-    nsIAtom* language = sc->GetStyleVisibility()->mLanguage;
+    nsIAtom* language = sc->GetStyleFont()->mLanguage;
     if (!language) {
         language = presShell->GetPresContext()->GetLanguageFromCharset();
     }
 
     // use CSS pixels instead of dev pixels to avoid being affected by page zoom
     const PRUint32 aupcp = nsPresContext::AppUnitsPerCSSPixel();
     // un-zoom the font size to avoid being affected by text-only zoom
     const nscoord fontSize = nsStyleFont::UnZoomText(parentContext->PresContext(), fontStyle->mFont.size);
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -2746,17 +2746,17 @@ nsCanvasRenderingContext2DAzure::SetFont
   if (!sc) {
     return NS_ERROR_FAILURE;
   }
 
   const nsStyleFont* fontStyle = sc->GetStyleFont();
 
   NS_ASSERTION(fontStyle, "Could not obtain font style");
 
-  nsIAtom* language = sc->GetStyleVisibility()->mLanguage;
+  nsIAtom* language = sc->GetStyleFont()->mLanguage;
   if (!language) {
     language = presShell->GetPresContext()->GetLanguageFromCharset();
   }
 
   // use CSS pixels instead of dev pixels to avoid being affected by page zoom
   const PRUint32 aupcp = nsPresContext::AppUnitsPerCSSPixel();
   // un-zoom the font size to avoid being affected by text-only zoom
   const nscoord fontSize = nsStyleFont::UnZoomText(parentContext->PresContext(), fontStyle->mFont.size);
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -1821,17 +1821,17 @@ nsGenericHTMLElement::MapCommonAttribute
         else if (value->Equals(nsGkAtoms::_false, eIgnoreCase)) {
             userModify->SetIntValue(NS_STYLE_USER_MODIFY_READ_ONLY,
                                     eCSSUnit_Enumerated);
         }
       }
     }
   }
 
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Visibility)) {
+  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Font)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::lang);
     if (value && value->Type() == nsAttrValue::eString) {
       aData->ValueForLang()->SetStringValue(value->GetStringValue(),
                                             eCSSUnit_Ident);
     }
   }
 }
 
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2054,17 +2054,17 @@ nsLayoutUtils::GetFontMetricsForStyleCon
   nsFont font = aStyleContext->GetStyleFont()->mFont;
   // We need to not run font.size through floats when it's large since
   // doing so would be lossy.  Fortunately, in such cases, aInflation is
   // guaranteed to be 1.0f.
   if (aInflation != 1.0f) {
     font.size = NSToCoordRound(font.size * aInflation);
   }
   return aStyleContext->PresContext()->DeviceContext()->GetMetricsFor(
-                  font, aStyleContext->GetStyleVisibility()->mLanguage,
+                  font, aStyleContext->GetStyleFont()->mLanguage,
                   fs, *aFontMetrics);
 }
 
 nsIFrame*
 nsLayoutUtils::FindChildContainingDescendant(nsIFrame* aParent, nsIFrame* aDescendantFrame)
 {
   nsIFrame* result = aDescendantFrame;
 
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -8648,17 +8648,17 @@ void ReflowCountMgr::PaintCount(const ch
       nsFont font("Times", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
                   NS_FONT_WEIGHT_NORMAL, NS_FONT_STRETCH_NORMAL, 0,
                   nsPresContext::CSSPixelsToAppUnits(11));
 
       nsRefPtr<nsFontMetrics> fm;
       aPresContext->DeviceContext()->GetMetricsFor(font,
         // We have one frame, therefore we must have a root...
         aPresContext->FrameManager()->GetRootFrame()->
-          GetStyleVisibility()->mLanguage,
+          GetStyleFont()->mLanguage,
         aPresContext->GetUserFontSet(), *getter_AddRefs(fm));
 
       aRenderingContext->SetFont(fm);
       char buf[16];
       sprintf(buf, "%d", counter->mCount);
       nscoord x = 0, y = fm->MaxAscent();
       nscoord width, height = fm->MaxHeight();
       aRenderingContext->SetTextRunRTL(false);
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -1514,17 +1514,17 @@ BuildTextRunsScanner::ContinueTextRunAcr
 
   nsStyleContext* sc2 = aFrame2->GetStyleContext();
   if (sc1 == sc2)
     return true;
   const nsStyleFont* fontStyle1 = sc1->GetStyleFont();
   const nsStyleFont* fontStyle2 = sc2->GetStyleFont();
   const nsStyleText* textStyle2 = sc2->GetStyleText();
   return fontStyle1->mFont.BaseEquals(fontStyle2->mFont) &&
-    sc1->GetStyleVisibility()->mLanguage == sc2->GetStyleVisibility()->mLanguage &&
+    sc1->GetStyleFont()->mLanguage == sc2->GetStyleFont()->mLanguage &&
     nsLayoutUtils::GetTextRunFlagsForStyle(sc1, textStyle1, fontStyle1) ==
       nsLayoutUtils::GetTextRunFlagsForStyle(sc2, textStyle2, fontStyle2);
 }
 
 void BuildTextRunsScanner::ScanFrame(nsIFrame* aFrame)
 {
   // First check if we can extend the current mapped frame block. This is common.
   if (mMappedFlows.Length() > 0) {
@@ -2167,17 +2167,17 @@ HasCompressedLeadingWhitespace(nsTextFra
 }
 
 void
 BuildTextRunsScanner::SetupBreakSinksForTextRun(gfxTextRun* aTextRun,
                                                 const void* aTextPtr,
                                                 PRUint32    aFlags)
 {
   // textruns have uniform language
-  nsIAtom* language = mMappedFlows[0].mStartFrame->GetStyleVisibility()->mLanguage;
+  nsIAtom* language = mMappedFlows[0].mStartFrame->GetStyleFont()->mLanguage;
   // We keep this pointed at the skip-chars data for the current mappedFlow.
   // This lets us cheaply check whether the flow has compressed initial
   // whitespace...
   gfxSkipCharsIterator iter(aTextRun->GetSkipChars());
 
   PRUint32 i;
   for (i = 0; i < mMappedFlows.Length(); ++i) {
     MappedFlow* mappedFlow = &mMappedFlows[i];
@@ -2555,17 +2555,17 @@ static PRInt32 FindChar(const nsTextFrag
         return (static_cast<const char*>(p) - str) + aOffset;
     }
   }
   return -1;
 }
 
 static bool IsChineseOrJapanese(nsIFrame* aFrame)
 {
-  nsIAtom* language = aFrame->GetStyleVisibility()->mLanguage;
+  nsIAtom* language = aFrame->GetStyleFont()->mLanguage;
   if (!language) {
     return false;
   }
   const PRUnichar *lang = language->GetUTF16String();
   return (!nsCRT::strncmp(lang, NS_LITERAL_STRING("ja").get(), 2) ||
           !nsCRT::strncmp(lang, NS_LITERAL_STRING("zh").get(), 2)) &&
          (language->GetLength() == 2 || lang[2] == '-');
 }
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -1050,17 +1050,17 @@ SetFontFamily(nsStyleContext*      aStyl
               const nsAString&     aDefaultFamily)
 {
   const nsAString& family =
     aGlyphCode.font ? aGlyphTable->FontNameFor(aGlyphCode) : aDefaultFamily;
   if (! family.Equals(aFont.name)) {
     aFont.name = family;
     nsRefPtr<nsFontMetrics> fm;
     aRenderingContext.DeviceContext()->GetMetricsFor(aFont,
-      aStyleContext->GetStyleVisibility()->mLanguage,
+      aStyleContext->GetStyleFont()->mLanguage,
       aStyleContext->PresContext()->GetUserFontSet(),
       *getter_AddRefs(fm));
     aRenderingContext.SetFont(fm);
   }
 }
 
 class nsMathMLChar::StretchEnumContext {
 public:
@@ -1462,17 +1462,17 @@ nsMathMLChar::StretchInternal(nsPresCont
   if (!maxWidth) {
     // Record the families in case there is no stretch.  But don't bother
     // storing families when they are just those from the StyleContext.
     mFamily = families;
   }
 
   nsRefPtr<nsFontMetrics> fm;
   aRenderingContext.DeviceContext()->GetMetricsFor(font,
-    mStyleContext->GetStyleVisibility()->mLanguage,
+    mStyleContext->GetStyleFont()->mLanguage,
     aPresContext->GetUserFontSet(), *getter_AddRefs(fm));
   aRenderingContext.SetFont(fm);
   aDesiredStretchSize =
     aRenderingContext.GetBoundingMetrics(mData.get(), PRUint32(mData.Length()));
 
   if (!maxWidth) {
     mUnscaledAscent = aDesiredStretchSize.ascent;
   }
@@ -2070,17 +2070,17 @@ nsMathMLChar::PaintForeground(nsPresCont
   aRenderingContext.SetColor(fgColor);
 
   nsFont theFont(styleContext->GetStyleFont()->mFont);
   if (! mFamily.IsEmpty()) {
     theFont.name = mFamily;
   }
   nsRefPtr<nsFontMetrics> fm;
   aRenderingContext.DeviceContext()->GetMetricsFor(theFont,
-    styleContext->GetStyleVisibility()->mLanguage,
+    styleContext->GetStyleFont()->mLanguage,
     aPresContext->GetUserFontSet(),
     *getter_AddRefs(fm));
   aRenderingContext.SetFont(fm);
 
   aRenderingContext.PushState();
   nsRect r = mRect + aPt;
   ApplyTransforms(aRenderingContext, r);
 
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -2960,17 +2960,17 @@ CSS_PROP_SVG(
 // not nsCSS* offsets).  Callers that care about these bogus fields can
 // define CSS_PROP_STUB_NOT_CSS to define a replacement for these
 // entries.
 #ifdef CSS_PROP_STUB_NOT_CSS
 CSS_PROP_STUB_NOT_CSS
 CSS_PROP_STUB_NOT_CSS
 CSS_PROP_STUB_NOT_CSS
 #else
-CSS_PROP_VISIBILITY(
+CSS_PROP_FONT(
     -x-lang,
     _x_lang,
     Lang,
     CSS_PROPERTY_PARSE_INACCESSIBLE,
     0,
     nsnull,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -182,107 +182,98 @@ static void EnsureBlockDisplay(PRUint8& 
     // make it a block
     display = NS_STYLE_DISPLAY_BLOCK;
   }
 }
 
 static nscoord CalcLengthWith(const nsCSSValue& aValue,
                               nscoord aFontSize,
                               const nsStyleFont* aStyleFont,
-                              const nsStyleVisibility* aStyleVisibility,
                               nsStyleContext* aStyleContext,
                               nsPresContext* aPresContext,
                               bool aUseProvidedRootEmSize,
                               bool aUseUserFontSet,
                               bool& aCanStoreInRuleTree);
 
 struct CalcLengthCalcOps : public css::BasicCoordCalcOps,
                            public css::NumbersAlreadyNormalizedOps
 {
   // All of the parameters to CalcLengthWith except aValue.
   const nscoord mFontSize;
   const nsStyleFont* const mStyleFont;
-  const nsStyleVisibility* const mStyleVisibility;
   nsStyleContext* const mStyleContext;
   nsPresContext* const mPresContext;
   const bool mUseProvidedRootEmSize;
   const bool mUseUserFontSet;
   bool& mCanStoreInRuleTree;
 
   CalcLengthCalcOps(nscoord aFontSize, const nsStyleFont* aStyleFont,
-                    const nsStyleVisibility* aStyleVisibility,
                     nsStyleContext* aStyleContext, nsPresContext* aPresContext,
                     bool aUseProvidedRootEmSize, bool aUseUserFontSet,
                     bool& aCanStoreInRuleTree)
     : mFontSize(aFontSize),
       mStyleFont(aStyleFont),
-      mStyleVisibility(aStyleVisibility),
       mStyleContext(aStyleContext),
       mPresContext(aPresContext),
       mUseProvidedRootEmSize(aUseProvidedRootEmSize),
       mUseUserFontSet(aUseUserFontSet),
       mCanStoreInRuleTree(aCanStoreInRuleTree)
   {
   }
 
   result_type ComputeLeafValue(const nsCSSValue& aValue)
   {
-    return CalcLengthWith(aValue, mFontSize, mStyleFont, mStyleVisibility,
+    return CalcLengthWith(aValue, mFontSize, mStyleFont,
                           mStyleContext, mPresContext, mUseProvidedRootEmSize,
                           mUseUserFontSet, mCanStoreInRuleTree);
   }
 };
 
 static inline nscoord ScaleCoord(const nsCSSValue &aValue, float factor)
 {
   return NSToCoordRoundWithClamp(aValue.GetFloatValue() * factor);
 }
 
 already_AddRefed<nsFontMetrics>
 GetMetricsFor(nsPresContext* aPresContext,
               nsStyleContext* aStyleContext,
               const nsStyleFont* aStyleFont,
-              const nsStyleVisibility* aStyleVisibility,
               nscoord aFontSize, // overrides value from aStyleFont
               bool aUseUserFontSet)
 {
   nsFont font = aStyleFont->mFont;
   font.size = aFontSize;
   gfxUserFontSet *fs = nsnull;
   if (aUseUserFontSet) {
     fs = aPresContext->GetUserFontSet();
   }
   nsRefPtr<nsFontMetrics> fm;
-  if (!aStyleVisibility) {
-    aStyleVisibility = aStyleContext->GetStyleVisibility();
-  }
   aPresContext->DeviceContext()->GetMetricsFor(font,
-                                               aStyleVisibility->mLanguage,
+                                               aStyleFont->mLanguage,
                                                fs, *getter_AddRefs(fm));
   return fm.forget();
 }
 
 static nscoord CalcLengthWith(const nsCSSValue& aValue,
                               nscoord aFontSize,
                               const nsStyleFont* aStyleFont,
-                              const nsStyleVisibility* aStyleVisibility,
                               nsStyleContext* aStyleContext,
                               nsPresContext* aPresContext,
                               bool aUseProvidedRootEmSize,
                               // aUseUserFontSet should always be true
                               // except when called from
                               // CalcLengthWithInitialFont.
                               bool aUseUserFontSet,
                               bool& aCanStoreInRuleTree)
 {
   NS_ASSERTION(aValue.IsLengthUnit() || aValue.IsCalcUnit(),
                "not a length or calc unit");
-  NS_ASSERTION((aStyleFont && aStyleVisibility) || aStyleContext,
+  NS_ASSERTION(aStyleFont || aStyleContext,
                "Must have style data");
-  NS_ASSERTION((!aStyleFont && !aStyleVisibility) || !aStyleContext,
+  NS_ASSERTION(!aStyleFont || !aStyleContext,
                "Duplicate sources of data");
   NS_ASSERTION(aPresContext, "Must have prescontext");
 
   if (aValue.IsFixedLengthUnit()) {
     return aValue.GetFixedLength(aPresContext);
   }
   if (aValue.IsPixelLengthUnit()) {
     return aValue.GetPixelLength();
@@ -336,23 +327,23 @@ static nscoord CalcLengthWith(const nsCS
     }
     case eCSSUnit_EM: {
       return ScaleCoord(aValue, float(aFontSize));
       // XXX scale against font metrics height instead?
     }
     case eCSSUnit_XHeight: {
       nsRefPtr<nsFontMetrics> fm =
         GetMetricsFor(aPresContext, aStyleContext, styleFont,
-                      aStyleVisibility, aFontSize, aUseUserFontSet);
+                      aFontSize, aUseUserFontSet);
       return ScaleCoord(aValue, float(fm->XHeight()));
     }
     case eCSSUnit_Char: {
       nsRefPtr<nsFontMetrics> fm =
         GetMetricsFor(aPresContext, aStyleContext, styleFont,
-                      aStyleVisibility, aFontSize, aUseUserFontSet);
+                      aFontSize, aUseUserFontSet);
       gfxFloat zeroWidth = (fm->GetThebesFontGroup()->GetFontAt(0)
                             ->GetMetrics().zeroOrAveCharWidth);
 
       return ScaleCoord(aValue, ceil(aPresContext->AppUnitsPerDevPixel() *
                                      zeroWidth));
     }
     // For properties for which lengths are the *only* units accepted in
     // calc(), we can handle calc() here and just compute a final
@@ -360,17 +351,17 @@ static nscoord CalcLengthWith(const nsCS
     // properties by not calling CalcLength in those cases:  SetCoord
     // only calls CalcLength for a calc when it is appropriate to do so.
     case eCSSUnit_Calc:
     case eCSSUnit_Calc_Plus:
     case eCSSUnit_Calc_Minus:
     case eCSSUnit_Calc_Times_L:
     case eCSSUnit_Calc_Times_R:
     case eCSSUnit_Calc_Divided: {
-      CalcLengthCalcOps ops(aFontSize, aStyleFont, aStyleVisibility,
+      CalcLengthCalcOps ops(aFontSize, aStyleFont,
                             aStyleContext, aPresContext,
                             aUseProvidedRootEmSize, aUseUserFontSet,
                             aCanStoreInRuleTree);
       return css::ComputeCalc(aValue, ops);
     }
     default:
       NS_NOTREACHED("unexpected unit");
       break;
@@ -381,17 +372,17 @@ static nscoord CalcLengthWith(const nsCS
 /* static */ nscoord
 nsRuleNode::CalcLength(const nsCSSValue& aValue,
                        nsStyleContext* aStyleContext,
                        nsPresContext* aPresContext,
                        bool& aCanStoreInRuleTree)
 {
   NS_ASSERTION(aStyleContext, "Must have style data");
 
-  return CalcLengthWith(aValue, -1, nsnull, nsnull,
+  return CalcLengthWith(aValue, -1, nsnull,
                         aStyleContext, aPresContext,
                         false, true, aCanStoreInRuleTree);
 }
 
 /* Inline helper function to redirect requests to CalcLength. */
 static inline nscoord CalcLength(const nsCSSValue& aValue,
                                  nsStyleContext* aStyleContext,
                                  nsPresContext* aPresContext,
@@ -400,20 +391,19 @@ static inline nscoord CalcLength(const n
   return nsRuleNode::CalcLength(aValue, aStyleContext,
                                 aPresContext, aCanStoreInRuleTree);
 }
 
 /* static */ nscoord
 nsRuleNode::CalcLengthWithInitialFont(nsPresContext* aPresContext,
                                       const nsCSSValue& aValue)
 {
-  nsStyleFont defaultFont(aPresContext);
-  nsStyleVisibility defaultVisibility(aPresContext); // FIXME: best language?
+  nsStyleFont defaultFont(aPresContext); // FIXME: best language?
   bool canStoreInRuleTree;
-  return CalcLengthWith(aValue, -1, &defaultFont, &defaultVisibility,
+  return CalcLengthWith(aValue, -1, &defaultFont,
                         nsnull, aPresContext,
                         true, false, canStoreInRuleTree);
 }
 
 struct LengthPercentPairCalcOps : public css::NumbersAlreadyNormalizedOps
 {
   typedef nsRuleNode::ComputedCalc result_type;
 
@@ -2486,43 +2476,40 @@ ComputeScriptLevelSize(const nsStyleFont
 }
 
 struct SetFontSizeCalcOps : public css::BasicCoordCalcOps,
                             public css::NumbersAlreadyNormalizedOps
 {
   // The parameters beyond aValue that we need for CalcLengthWith.
   const nscoord mParentSize;
   const nsStyleFont* const mParentFont;
-  const nsStyleVisibility* const mLanguageVisibility;
   nsPresContext* const mPresContext;
   const bool mAtRoot;
   bool& mCanStoreInRuleTree;
 
   SetFontSizeCalcOps(nscoord aParentSize, const nsStyleFont* aParentFont,
-                     const nsStyleVisibility* aLanguageVisibility,
                      nsPresContext* aPresContext, bool aAtRoot,
                      bool& aCanStoreInRuleTree)
     : mParentSize(aParentSize),
       mParentFont(aParentFont),
-      mLanguageVisibility(aLanguageVisibility),
       mPresContext(aPresContext),
       mAtRoot(aAtRoot),
       mCanStoreInRuleTree(aCanStoreInRuleTree)
   {
   }
 
   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, mLanguageVisibility,
+                            mParentFont,
                             nsnull, mPresContext, mAtRoot,
                             true, mCanStoreInRuleTree);
       if (!aValue.IsRelativeLengthUnit()) {
         size = nsStyleFont::ZoomText(mPresContext, size);
       }
     }
     else if (eCSSUnit_Percent == aValue.GetUnit()) {
       mCanStoreInRuleTree = false;
@@ -2540,17 +2527,16 @@ struct SetFontSizeCalcOps : public css::
   }
 };
 
 /* static */ void
 nsRuleNode::SetFontSize(nsPresContext* aPresContext,
                         const nsRuleData* aRuleData,
                         const nsStyleFont* aFont,
                         const nsStyleFont* aParentFont,
-                        const nsStyleVisibility* aLanguageVisibility,
                         nscoord* aSize,
                         const nsFont& aSystemFont,
                         nscoord aParentSize,
                         nscoord aScriptLevelAdjustedParentSize,
                         bool aUsedStartStruct,
                         bool aAtRoot,
                         bool& aCanStoreInRuleTree)
 {
@@ -2599,17 +2585,17 @@ nsRuleNode::SetFontSize(nsPresContext* a
       }
     } else {
       NS_NOTREACHED("unexpected value");
     }
   }
   else if (sizeValue->IsLengthUnit() ||
            sizeValue->GetUnit() == eCSSUnit_Percent ||
            sizeValue->IsCalcUnit()) {
-    SetFontSizeCalcOps ops(aParentSize, aParentFont, aLanguageVisibility,
+    SetFontSizeCalcOps ops(aParentSize, aParentFont,
                            aPresContext, aAtRoot, aCanStoreInRuleTree);
     *aSize = css::ComputeCalc(*sizeValue, ops);
     if (*aSize < 0) {
       NS_ABORT_IF_FALSE(sizeValue->IsCalcUnit(),
                         "negative lengths and percents should be rejected "
                         "by parser");
       *aSize = 0;
     }
@@ -2668,25 +2654,35 @@ static PRInt8 ClampTo8Bit(PRInt32 aValue
 /* static */ void
 nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext,
                     nscoord aMinFontSize,
                     PRUint8 aGenericFontID, const nsRuleData* aRuleData,
                     const nsStyleFont* aParentFont,
                     nsStyleFont* aFont, bool aUsedStartStruct,
                     bool& aCanStoreInRuleTree)
 {
+  bool atRoot = !aContext->GetParent();
+
+  // mLanguage must be set before before any of the CalcLengthWith (direct
+  // calls or calls via SetFontSize) for the cases where |aParentFont| is the
+  // same as |aFont|.
+  //
+  // -x-lang: string, inherit
+  // this is not a real CSS property, it is a html attribute mapped to CSS
+  const nsCSSValue* langValue = aRuleData->ValueForLang();
+  if (eCSSUnit_Ident == langValue->GetUnit()) {
+    nsAutoString lang;
+    langValue->GetStringValue(lang);
+
+    nsContentUtils::ASCIIToLower(lang);
+    aFont->mLanguage = do_GetAtom(lang);
+  }
+
   const nsFont* defaultVariableFont =
     aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID);
-  bool atRoot = !aContext->GetParent();
-  // We get '%', 'em', 'ex', and 'ch' units from aParentFont.  For 'ex'
-  // and 'ch' units we use font metrics, which depend on language.  It
-  // makes sense to use the language from the same style context as
-  // aParentFont.
-  const nsStyleVisibility *languageVisibility =
-    (atRoot ? aContext : aContext->GetParent())->GetStyleVisibility();
 
   // -moz-system-font: enum (never inherit!)
   nsFont systemFont;
   const nsCSSValue* systemFontValue = aRuleData->ValueForSystemFont();
   if (eCSSUnit_Enumerated == systemFontValue->GetUnit()) {
     nsSystemFontID sysID;
     switch (systemFontValue->GetIntValue()) {
       case NS_STYLE_FONT_CAPTION:       sysID = eSystemFont_Caption;      break;    // css2
@@ -2866,17 +2862,17 @@ nsRuleNode::SetFont(nsPresContext* aPres
   // -moz-script-min-size: length
   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, languageVisibility,
+                     aParentFont,
                      nsnull, aPresContext, atRoot, true,
                      aCanStoreInRuleTree);
   }
 
   // -moz-script-size-multiplier: factor, inherit, initial
   SetFactor(*aRuleData->ValueForScriptSizeMultiplier(),
             aFont->mScriptSizeMultiplier,
             aCanStoreInRuleTree, aParentFont->mScriptSizeMultiplier,
@@ -2935,30 +2931,30 @@ nsRuleNode::SetFont(nsPresContext* aPres
   nscoord scriptLevelAdjustedParentSize = aParentFont->mSize;
   nscoord scriptLevelAdjustedUnconstrainedParentSize;
   scriptLevelAdjustedParentSize =
     ComputeScriptLevelSize(aFont, aParentFont, aPresContext,
                            &scriptLevelAdjustedUnconstrainedParentSize);
   NS_ASSERTION(!aUsedStartStruct || aFont->mScriptUnconstrainedSize == aFont->mSize,
                "If we have a start struct, we should have reset everything coming in here");
   SetFontSize(aPresContext, aRuleData, aFont, aParentFont,
-              languageVisibility, &aFont->mSize,
+              &aFont->mSize,
               systemFont, aParentFont->mSize, scriptLevelAdjustedParentSize,
               aUsedStartStruct, atRoot, aCanStoreInRuleTree);
   if (aParentFont->mSize == aParentFont->mScriptUnconstrainedSize &&
       scriptLevelAdjustedParentSize == scriptLevelAdjustedUnconstrainedParentSize) {
     // Fast path: we have not been affected by scriptminsize so we don't
     // need to call SetFontSize again to compute the
     // scriptminsize-unconstrained size. This is OK even if we have a
     // start struct, because if we have a start struct then 'font-size'
     // was specified and so scriptminsize has no effect.
     aFont->mScriptUnconstrainedSize = aFont->mSize;
   } else {
     SetFontSize(aPresContext, aRuleData, aFont, aParentFont,
-                languageVisibility, &aFont->mScriptUnconstrainedSize,
+                &aFont->mScriptUnconstrainedSize,
                 systemFont, aParentFont->mScriptUnconstrainedSize,
                 scriptLevelAdjustedUnconstrainedParentSize,
                 aUsedStartStruct, atRoot, aCanStoreInRuleTree);
   }
   NS_ASSERTION(aFont->mScriptUnconstrainedSize <= aFont->mSize,
                "scriptminsize should never be making things bigger");
 
   // enforce the user' specified minimum font-size on the value that we expose
@@ -4708,27 +4704,16 @@ nsRuleNode::ComputeVisibilityData(void* 
               NS_STYLE_VISIBILITY_VISIBLE, 0, 0, 0, 0);
 
   // pointer-events: enum, inherit, initial
   SetDiscrete(*aRuleData->ValueForPointerEvents(), visibility->mPointerEvents,
               canStoreInRuleTree,
               SETDSC_ENUMERATED, parentVisibility->mPointerEvents,
               NS_STYLE_POINTER_EVENTS_AUTO, 0, 0, 0, 0);
 
-  // lang: string, inherit
-  // this is not a real CSS property, it is a html attribute mapped to CSS struture
-  const nsCSSValue* langValue = aRuleData->ValueForLang();
-  if (eCSSUnit_Ident == langValue->GetUnit()) {
-    nsAutoString lang;
-    langValue->GetStringValue(lang);
-
-    nsContentUtils::ASCIIToLower(lang);
-    visibility->mLanguage = do_GetAtom(lang);
-  }
-
   COMPUTE_END_INHERITED(Visibility, visibility)
 }
 
 const void*
 nsRuleNode::ComputeColorData(void* aStartStruct,
                              const nsRuleData* aRuleData,
                              nsStyleContext* aContext,
                              nsRuleNode* aHighestNode,
--- a/layout/style/nsRuleNode.h
+++ b/layout/style/nsRuleNode.h
@@ -595,17 +595,16 @@ protected:
                         RuleDetail aRuleDetail,
                         const bool aCanStoreInRuleTree);
 
   // helpers for |ComputeFontData| that need access to |mNoneBits|:
   static void SetFontSize(nsPresContext* aPresContext,
                           const nsRuleData* aRuleData,
                           const nsStyleFont* aFont,
                           const nsStyleFont* aParentFont,
-                          const nsStyleVisibility* aLanguageVisibility,
                           nscoord* aSize,
                           const nsFont& aSystemFont,
                           nscoord aParentSize,
                           nscoord aScriptLevelAdjustedParentSize,
                           bool aUsedStartStruct,
                           bool aAtRoot,
                           bool& aCanStoreInRuleTree);
 
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -125,47 +125,64 @@ static nsChangeHint CalcShadowDifference
 // --------------------
 // nsStyleFont
 //
 nsStyleFont::nsStyleFont(const nsFont& aFont, nsPresContext *aPresContext)
   : mFont(aFont),
     mGenericID(kGenericFont_NONE)
 {
   MOZ_COUNT_CTOR(nsStyleFont);
-  mSize = mFont.size = nsStyleFont::ZoomText(aPresContext, mFont.size);
-  mScriptUnconstrainedSize = mSize;
-  mScriptMinSize = aPresContext->CSSTwipsToAppUnits(
-      NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT));
-  mScriptLevel = 0;
-  mScriptSizeMultiplier = NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER;
+  Init(aPresContext);
 }
 
 nsStyleFont::nsStyleFont(const nsStyleFont& aSrc)
   : mFont(aSrc.mFont)
   , mSize(aSrc.mSize)
   , mGenericID(aSrc.mGenericID)
   , mScriptLevel(aSrc.mScriptLevel)
   , mScriptUnconstrainedSize(aSrc.mScriptUnconstrainedSize)
   , mScriptMinSize(aSrc.mScriptMinSize)
   , mScriptSizeMultiplier(aSrc.mScriptSizeMultiplier)
+  , mLanguage(aSrc.mLanguage)
 {
   MOZ_COUNT_CTOR(nsStyleFont);
 }
 
 nsStyleFont::nsStyleFont(nsPresContext* aPresContext)
   : mFont(*(aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID))),
     mGenericID(kGenericFont_NONE)
 {
   MOZ_COUNT_CTOR(nsStyleFont);
+  Init(aPresContext);
+}
+
+void
+nsStyleFont::Init(nsPresContext* aPresContext)
+{
   mSize = mFont.size = nsStyleFont::ZoomText(aPresContext, mFont.size);
   mScriptUnconstrainedSize = mSize;
   mScriptMinSize = aPresContext->CSSTwipsToAppUnits(
       NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT));
   mScriptLevel = 0;
   mScriptSizeMultiplier = NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER;
+
+  nsAutoString language;
+  aPresContext->Document()->GetContentLanguage(language);
+  language.StripWhitespace();
+
+  // Content-Language may be a comma-separated list of language codes,
+  // in which case the HTML5 spec says to treat it as unknown
+  if (!language.IsEmpty() &&
+      language.FindChar(PRUnichar(',')) == kNotFound) {
+    mLanguage = do_GetAtom(language);
+  } else {
+    // we didn't find a (usable) Content-Language, so we fall back
+    // to whatever the presContext guessed from the charset
+    mLanguage = aPresContext->GetLanguageFromCharset();
+  }
 }
 
 void* 
 nsStyleFont::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
   void* result = aContext->AllocateFromShell(sz);
   if (result)
     memset(result, 0, sz);
   return result;
@@ -174,20 +191,21 @@ nsStyleFont::operator new(size_t sz, nsP
 void 
 nsStyleFont::Destroy(nsPresContext* aContext) {
   this->~nsStyleFont();
   aContext->FreeToShell(sizeof(nsStyleFont), this);
 }
 
 nsChangeHint nsStyleFont::CalcDifference(const nsStyleFont& aOther) const
 {
-  if (mSize == aOther.mSize) {
-    return CalcFontDifference(mFont, aOther.mFont);
+  if (mSize != aOther.mSize ||
+      mLanguage != aOther.mLanguage) {
+    return NS_STYLE_HINT_REFLOW;
   }
-  return NS_STYLE_HINT_REFLOW;
+  return CalcFontDifference(mFont, aOther.mFont);
 }
 
 #ifdef DEBUG
 /* static */
 nsChangeHint nsStyleFont::MaxDifference()
 {
   return NS_STYLE_HINT_REFLOW;
 }
@@ -2308,61 +2326,41 @@ nsStyleVisibility::nsStyleVisibility(nsP
 {
   MOZ_COUNT_CTOR(nsStyleVisibility);
   PRUint32 bidiOptions = aPresContext->GetBidi();
   if (GET_BIDI_OPTION_DIRECTION(bidiOptions) == IBMBIDI_TEXTDIRECTION_RTL)
     mDirection = NS_STYLE_DIRECTION_RTL;
   else
     mDirection = NS_STYLE_DIRECTION_LTR;
 
-  nsAutoString language;
-  aPresContext->Document()->GetContentLanguage(language);
-  language.StripWhitespace();
-
-  // Content-Language may be a comma-separated list of language codes,
-  // in which case the HTML5 spec says to treat it as unknown
-  if (!language.IsEmpty() &&
-      language.FindChar(PRUnichar(',')) == kNotFound) {
-    mLanguage = do_GetAtom(language);
-  } else {
-    // we didn't find a (usable) Content-Language, so we fall back
-    // to whatever the presContext guessed from the charset
-    mLanguage = aPresContext->GetLanguageFromCharset();
-  }
-
   mVisible = NS_STYLE_VISIBILITY_VISIBLE;
   mPointerEvents = NS_STYLE_POINTER_EVENTS_AUTO;
 }
 
 nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource)
 {
   MOZ_COUNT_CTOR(nsStyleVisibility);
   mDirection = aSource.mDirection;
   mVisible = aSource.mVisible;
-  mLanguage = aSource.mLanguage;
   mPointerEvents = aSource.mPointerEvents;
 } 
 
 nsChangeHint nsStyleVisibility::CalcDifference(const nsStyleVisibility& aOther) const
 {
   nsChangeHint hint = nsChangeHint(0);
 
   if (mDirection != aOther.mDirection) {
     NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
-  } else if (mLanguage == aOther.mLanguage) {
-    if (mVisible != aOther.mVisible) {
-      if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
-          (NS_STYLE_VISIBILITY_COLLAPSE == aOther.mVisible)) {
-        NS_UpdateHint(hint, NS_STYLE_HINT_REFLOW);
-      } else {
-        NS_UpdateHint(hint, NS_STYLE_HINT_VISUAL);
-      }
+  } else if (mVisible != aOther.mVisible) {
+    if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
+        (NS_STYLE_VISIBILITY_COLLAPSE == aOther.mVisible)) {
+      NS_UpdateHint(hint, NS_STYLE_HINT_REFLOW);
+    } else {
+      NS_UpdateHint(hint, NS_STYLE_HINT_VISUAL);
     }
-  } else {
-    NS_UpdateHint(hint, NS_STYLE_HINT_REFLOW);
   }
   return hint;
 }
 
 #ifdef DEBUG
 /* static */
 nsChangeHint nsStyleVisibility::MaxDifference()
 {
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -108,16 +108,19 @@ struct nsCSSValueList;
 // change will be applied to all descendants must return true from
 // ForceCompare(), so that we will make sure to compare those structs in
 // nsStyleContext::CalcStyleDifference.
 
 struct nsStyleFont {
   nsStyleFont(const nsFont& aFont, nsPresContext *aPresContext);
   nsStyleFont(const nsStyleFont& aStyleFont);
   nsStyleFont(nsPresContext *aPresContext);
+private:
+  void Init(nsPresContext *aPresContext);
+public:
   ~nsStyleFont(void) {
     MOZ_COUNT_DTOR(nsStyleFont);
   }
 
   nsChangeHint CalcDifference(const nsStyleFont& aOther) const;
 #ifdef DEBUG
   static nsChangeHint MaxDifference();
 #endif
@@ -141,16 +144,17 @@ struct nsStyleFont {
                         // value is a kGenericFont_* constant, see nsFont.h.
 
   // MathML scriptlevel support
   PRInt8  mScriptLevel;          // [inherited]
   // The value mSize would have had if scriptminsize had never been applied
   nscoord mScriptUnconstrainedSize;
   nscoord mScriptMinSize;        // [inherited] length
   float   mScriptSizeMultiplier; // [inherited]
+  nsCOMPtr<nsIAtom> mLanguage;   // [inherited]
 };
 
 struct nsStyleGradientStop {
   nsStyleCoord mLocation; // percent, coord, none
   nscolor mColor;
 };
 
 class nsStyleGradient {
@@ -1332,17 +1336,16 @@ struct nsStyleVisibility {
   nsChangeHint CalcDifference(const nsStyleVisibility& aOther) const;
 #ifdef DEBUG
   static nsChangeHint MaxDifference();
 #endif
   static bool ForceCompare() { return false; }
 
   PRUint8 mDirection;                  // [inherited] see nsStyleConsts.h NS_STYLE_DIRECTION_*
   PRUint8   mVisible;                  // [inherited]
-  nsCOMPtr<nsIAtom> mLanguage;         // [inherited]
   PRUint8 mPointerEvents;              // [inherited] see nsStyleConsts.h
 
   bool IsVisible() const {
     return (mVisible == NS_STYLE_VISIBILITY_VISIBLE);
   }
 
   bool IsVisibleOrCollapsed() const {
     return ((mVisible == NS_STYLE_VISIBILITY_VISIBLE) ||
--- a/layout/svg/base/src/nsSVGGlyphFrame.cpp
+++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp
@@ -1569,17 +1569,17 @@ nsSVGGlyphFrame::EnsureTextRun(float *aD
       textRunSize = NS_MAX(textRunSize, double(CLAMP_MIN_SIZE));
       textRunSize = NS_MIN(textRunSize, double(CLAMP_MAX_SIZE));
     }
 
     const nsFont& font = fontData->mFont;
     bool printerFont = (presContext->Type() == nsPresContext::eContext_PrintPreview ||
                           presContext->Type() == nsPresContext::eContext_Print);
     gfxFontStyle fontStyle(font.style, font.weight, font.stretch, textRunSize,
-                           mStyleContext->GetStyleVisibility()->mLanguage,
+                           mStyleContext->GetStyleFont()->mLanguage,
                            font.sizeAdjust, font.systemFont,
                            printerFont,
                            font.featureSettings,
                            font.languageOverride);
 
     nsRefPtr<gfxFontGroup> fontGroup =
       gfxPlatform::GetPlatform()->CreateFontGroup(font.name, &fontStyle, presContext->GetUserFontSet());