Bug 804970, patch 5: Handle dynamic changes to the basis for 'rem' units by rebuilding all style data. r=bzbarsky
authorL. David Baron <dbaron@dbaron.org>
Fri, 26 Oct 2012 19:04:20 +0200
changeset 120184 b707050a4ac4b87a9145c3f562fd5cdd9049aad0
parent 120183 ba9ee31718012226b54c4eecb9bf45c760f962e4
child 120185 8f8cc2ad5f88d6b7bbcf169f0c675acb2246d938
push id273
push userlsblakk@mozilla.com
push dateThu, 14 Feb 2013 23:19:38 +0000
treeherdermozilla-release@c5e807a3f8b8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs804970
milestone19.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 804970, patch 5: Handle dynamic changes to the basis for 'rem' units by rebuilding all style data. r=bzbarsky
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/style/nsRuleNode.cpp
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -8302,16 +8302,35 @@ nsCSSFrameConstructor::RestyleElement(El
   if (aPrimaryFrame && aPrimaryFrame->GetContent() != aElement) {
     // XXXbz this is due to image maps messing with the primary frame pointer
     // of <area>s.  See bug 135040.  We can remove this block once that's fixed.
     aPrimaryFrame = nullptr;
   }
   NS_ASSERTION(!aPrimaryFrame || aPrimaryFrame->GetContent() == aElement,
                "frame/content mismatch");
 
+  // If we're restyling the root element and there are 'rem' units in
+  // use, handle dynamic changes to the definition of a 'rem' here.
+  if (GetPresContext()->UsesRootEMUnits() && aPrimaryFrame) {
+    nsStyleContext *oldContext = aPrimaryFrame->GetStyleContext();
+    if (!oldContext->GetParent()) { // check that we're the root element
+      nsRefPtr<nsStyleContext> newContext = mPresShell->StyleSet()->
+        ResolveStyleFor(aElement, nullptr /* == oldContext->GetParent() */);
+      if (oldContext->GetStyleFont()->mFont.size !=
+          newContext->GetStyleFont()->mFont.size) {
+        // The basis for 'rem' units has changed.
+        DoRebuildAllStyleData(aRestyleTracker, nsChangeHint(0));
+        if (aMinHint == 0) {
+          return;
+        }
+        aPrimaryFrame = aElement->GetPrimaryFrame();
+      }
+    }
+  }
+
   if (aMinHint & nsChangeHint_ReconstructFrame) {
     RecreateFramesForContent(aElement, false);
   } else if (aPrimaryFrame) {
     nsStyleChangeList changeList;
     ComputeStyleChangeFor(aPrimaryFrame, &changeList, aMinHint,
                           aRestyleTracker, aRestyleDescendants);
     ProcessRestyledFrames(changeList);
   } else {
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1656,16 +1656,17 @@ nsPresContext::UIResolutionChangedIntern
 void
 nsPresContext::RebuildAllStyleData(nsChangeHint aExtraHint)
 {
   if (!mShell) {
     // We must have been torn down. Nothing to do here.
     return;
   }
 
+  mUsesRootEMUnits = false;
   mUsesViewportUnits = false;
   RebuildUserFontSet();
   AnimationManager()->KeyframesListIsDirty();
 
   mShell->FrameConstructor()->RebuildAllStyleData(aExtraHint);
 }
 
 void
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -948,16 +948,24 @@ public:
   bool IsGlyph() const {
     return mIsGlyph;
   }
 
   void SetIsGlyph(bool aValue) {
     mIsGlyph = aValue;
   }
 
+  bool UsesRootEMUnits() const {
+    return mUsesRootEMUnits;
+  }
+
+  void SetUsesRootEMUnits(bool aValue) {
+    mUsesRootEMUnits = aValue;
+  }
+
   bool UsesViewportUnits() const {
     return mUsesViewportUnits;
   }
 
   void SetUsesViewportUnits(bool aValue) {
     mUsesViewportUnits = aValue;
   }
 
@@ -1211,17 +1219,19 @@ protected:
   unsigned              mMayHaveFixedBackgroundFrames : 1;
   // True if the requests in mInvalidateRequestsSinceLastPaint cover the
   // entire viewport
   unsigned              mAllInvalidated : 1;
 
   // Are we currently drawing an SVG glyph?
   unsigned              mIsGlyph : 1;
 
-  // Does the associated document use viewport units?
+  // Does the associated document use root-em (rem) units?
+  unsigned              mUsesRootEMUnits : 1;
+  // Does the associated document use viewport units (vw/vh/vmin/vmax)?
   unsigned              mUsesViewportUnits : 1;
 
   // Has there been a change to the viewport's dimensions?
   unsigned              mPendingViewportChange : 1;
 
   // Is the current mUserFontSet valid?
   unsigned              mUserFontSetDirty : 1;
   // Has GetUserFontSet() been called?
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -317,16 +317,17 @@ static nscoord CalcLengthWith(const nsCS
     aStyleFont ? aStyleFont : aStyleContext->GetStyleFont();
   if (aFontSize == -1) {
     // XXX Should this be styleFont->mSize instead to avoid taking minfontsize
     // prefs into account?
     aFontSize = styleFont->mFont.size;
   }
   switch (aValue.GetUnit()) {
     case eCSSUnit_RootEM: {
+      aPresContext->SetUsesRootEMUnits(true);
       nscoord rootFontSize;
 
       if (aUseProvidedRootEmSize) {
         // We should use the provided aFontSize as the reference length to
         // scale. This only happens when we are calculating font-size or
         // an equivalent (scriptminsize or CalcLengthWithInitialFont) on
         // the root element, in which case aFontSize is already the
         // value we want.