Bug 1414926 - Make -moz-font-smoothing-background-color changes only cause repaints, not reflows. r=emilio
authorMarkus Stange <mstange@themasta.com>
Tue, 07 Nov 2017 23:01:29 -0500
changeset 444079 7279b117245bfa6fb87f4b404f5c187838a603c7
parent 444073 a2bf3b8c08ea588d1ab6b23b41ca665a4cf305a0
child 444080 a82270f0b8a9fcc07cbb24dcb561bea40f77a83f
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1414926
milestone58.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 1414926 - Make -moz-font-smoothing-background-color changes only cause repaints, not reflows. r=emilio This case is hit by hovering over menu items, so the optimization is somewhat worthwhile. As a side-effect, not causing reflows also avoids a XUL <select> popup positioning bug. MozReview-Commit-ID: AOrijytoHHL
gfx/src/nsFont.cpp
gfx/src/nsFont.h
gfx/thebes/gfxFontFamilyList.h
layout/style/nsStyleStruct.cpp
--- a/gfx/src/nsFont.cpp
+++ b/gfx/src/nsFont.cpp
@@ -37,42 +37,52 @@ nsFont::nsFont()
 }
 
 nsFont::~nsFont()
 {
 }
 
 bool nsFont::Equals(const nsFont& aOther) const
 {
-  if ((style == aOther.style) &&
-      (systemFont == aOther.systemFont) &&
-      (weight == aOther.weight) &&
-      (stretch == aOther.stretch) &&
-      (size == aOther.size) &&
-      (sizeAdjust == aOther.sizeAdjust) &&
-      (fontlist == aOther.fontlist) &&
-      (kerning == aOther.kerning) &&
-      (synthesis == aOther.synthesis) &&
-      (fontFeatureSettings == aOther.fontFeatureSettings) &&
-      (fontVariationSettings == aOther.fontVariationSettings) &&
-      (languageOverride == aOther.languageOverride) &&
-      (variantAlternates == aOther.variantAlternates) &&
-      (variantCaps == aOther.variantCaps) &&
-      (variantEastAsian == aOther.variantEastAsian) &&
-      (variantLigatures == aOther.variantLigatures) &&
-      (variantNumeric == aOther.variantNumeric) &&
-      (variantPosition == aOther.variantPosition) &&
-      (variantWidth == aOther.variantWidth) &&
-      (alternateValues == aOther.alternateValues) &&
-      (featureValueLookup == aOther.featureValueLookup) &&
-      (smoothing == aOther.smoothing) &&
-      (fontSmoothingBackgroundColor == aOther.fontSmoothingBackgroundColor)) {
-    return true;
+  return CalcDifference(aOther) == MaxDifference::eNone;
+}
+
+nsFont::MaxDifference
+nsFont::CalcDifference(const nsFont& aOther) const
+{
+  if ((style != aOther.style) ||
+      (systemFont != aOther.systemFont) ||
+      (weight != aOther.weight) ||
+      (stretch != aOther.stretch) ||
+      (size != aOther.size) ||
+      (sizeAdjust != aOther.sizeAdjust) ||
+      (fontlist != aOther.fontlist) ||
+      (kerning != aOther.kerning) ||
+      (synthesis != aOther.synthesis) ||
+      (fontFeatureSettings != aOther.fontFeatureSettings) ||
+      (fontVariationSettings != aOther.fontVariationSettings) ||
+      (languageOverride != aOther.languageOverride) ||
+      (variantAlternates != aOther.variantAlternates) ||
+      (variantCaps != aOther.variantCaps) ||
+      (variantEastAsian != aOther.variantEastAsian) ||
+      (variantLigatures != aOther.variantLigatures) ||
+      (variantNumeric != aOther.variantNumeric) ||
+      (variantPosition != aOther.variantPosition) ||
+      (variantWidth != aOther.variantWidth) ||
+      (alternateValues != aOther.alternateValues) ||
+      (featureValueLookup != aOther.featureValueLookup)) {
+    return MaxDifference::eLayoutAffecting;
   }
-  return false;
+
+  if ((smoothing != aOther.smoothing) ||
+      (fontSmoothingBackgroundColor != aOther.fontSmoothingBackgroundColor)) {
+    return MaxDifference::eVisual;
+  }
+
+  return MaxDifference::eNone;
 }
 
 nsFont& nsFont::operator=(const nsFont& aOther) = default;
 
 void
 nsFont::CopyAlternates(const nsFont& aOther)
 {
   variantAlternates = aOther.variantAlternates;
--- a/gfx/src/nsFont.h
+++ b/gfx/src/nsFont.h
@@ -138,16 +138,24 @@ struct nsFont {
   bool operator!=(const nsFont& aOther) const {
     return !Equals(aOther);
   }
 
   bool Equals(const nsFont& aOther) const;
 
   nsFont& operator=(const nsFont& aOther);
 
+  enum class MaxDifference : uint8_t {
+    eNone,
+    eVisual,
+    eLayoutAffecting
+  };
+
+  MaxDifference CalcDifference(const nsFont& aOther) const;
+
   void CopyAlternates(const nsFont& aOther);
 
   // Add featureSettings into style
   void AddFontFeaturesToStyle(gfxFontStyle *aStyle,
                               bool aVertical) const;
 
   void AddFontVariationsToStyle(gfxFontStyle *aStyle) const;
 };
--- a/gfx/thebes/gfxFontFamilyList.h
+++ b/gfx/thebes/gfxFontFamilyList.h
@@ -441,11 +441,16 @@ protected:
     FontFamilyType             mDefaultFontType; // none, serif or sans-serif
 };
 
 inline bool
 operator==(const FontFamilyList& a, const FontFamilyList& b) {
     return a.Equals(b);
 }
 
+inline bool
+operator!=(const FontFamilyList& a, const FontFamilyList& b) {
+    return !a.Equals(b);
+}
+
 } // namespace mozilla
 
 #endif /* GFX_FONT_FAMILY_LIST_H */
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -194,28 +194,35 @@ nsStyleFont::EnableZoom(nsPresContext* a
 }
 
 nsChangeHint
 nsStyleFont::CalcDifference(const nsStyleFont& aNewData) const
 {
   MOZ_ASSERT(mAllowZoom == aNewData.mAllowZoom,
              "expected mAllowZoom to be the same on both nsStyleFonts");
   if (mSize != aNewData.mSize ||
-      mFont != aNewData.mFont ||
       mLanguage != aNewData.mLanguage ||
       mExplicitLanguage != aNewData.mExplicitLanguage ||
       mMathVariant != aNewData.mMathVariant ||
       mMathDisplay != aNewData.mMathDisplay ||
       mMinFontSizeRatio != aNewData.mMinFontSizeRatio) {
-    // If only mFont.fontSmoothingBackgroundColor changes, we really only need
-    // a repaint hint rather than a reflow+repaint hint, but it's not worth
-    // worth optimizing.
     return NS_STYLE_HINT_REFLOW;
   }
 
+  switch (mFont.CalcDifference(aNewData.mFont)) {
+    case nsFont::MaxDifference::eLayoutAffecting:
+      return NS_STYLE_HINT_REFLOW;
+
+    case nsFont::MaxDifference::eVisual:
+      return NS_STYLE_HINT_VISUAL;
+
+    case nsFont::MaxDifference::eNone:
+      break;
+  }
+
   // XXX Should any of these cause a non-nsChangeHint_NeutralChange change?
   if (mGenericID != aNewData.mGenericID ||
       mScriptLevel != aNewData.mScriptLevel ||
       mScriptUnconstrainedSize != aNewData.mScriptUnconstrainedSize ||
       mScriptMinSize != aNewData.mScriptMinSize ||
       mScriptSizeMultiplier != aNewData.mScriptSizeMultiplier) {
     return nsChangeHint_NeutralChange;
   }