Bug 1288938: Allow passing different reasons to dirty a non display SVG text frame. draft
authorEmilio Cobos Álvarez <ecoal95@gmail.com>
Sun, 31 Jul 2016 17:08:56 -0700
changeset 394801 313e2b9b489d4898c3b6fd571efdd3bac9dd1ae7
parent 394800 edf9756b21757df3291e6cece2389e6106ff4f80
child 526871 73033c9490ee0f687528a4e31d353531298d6ca1
push id24636
push userbmo:ealvarez@mozilla.com
push dateMon, 01 Aug 2016 01:49:07 +0000
bugs1288938
milestone50.0a1
Bug 1288938: Allow passing different reasons to dirty a non display SVG text frame. Otherwise, when a glyph changes, we might end up doing too much work, destroying the text-run and the observer that dirtied the frame, causing an assertion when trying to delete it from the observer set. MozReview-Commit-ID: LMQVr6pYFVM
layout/generic/nsFrame.cpp
layout/generic/nsTextFrame.cpp
layout/svg/SVGTextFrame.cpp
layout/svg/SVGTextFrame.h
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -838,17 +838,17 @@ nsFrame::DidSetStyleContext(nsStyleConte
     // Note that we must check NS_FRAME_FIRST_REFLOW on our SVGTextFrame's
     // anonymous block frame rather than our self, since NS_FRAME_FIRST_REFLOW
     // may be set on us if we're a new frame that has been inserted after the
     // document's first reflow. (In which case this DidSetStyleContext call may
     // be happening under frame construction under a Reflow() call.)
     if (anonBlock && !(anonBlock->GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
         (svgTextFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY) &&
         !(svgTextFrame->GetStateBits() & NS_STATE_SVG_TEXT_IN_REFLOW)) {
-      svgTextFrame->ScheduleReflowSVGNonDisplayText();
+      svgTextFrame->ScheduleReflowSVGNonDisplayText(nsIPresShell::eStyleChange);
     }
   }
 
   const nsStyleImageLayers *oldLayers = aOldStyleContext ?
                               &aOldStyleContext->StyleBackground()->mImage :
                               nullptr;
   const nsStyleImageLayers *newLayers = &StyleBackground()->mImage;
   AddAndRemoveImageAssociations(this, oldLayers, newLayers);
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -650,17 +650,17 @@ InvalidateFrameDueToGlyphsChanged(nsIFra
     // If this is a non-display text frame within SVG <text>, we need
     // to reflow the SVGTextFrame. (This is similar to reflowing the
     // SVGTextFrame in response to style changes, in
     // SVGTextFrame::DidSetStyleContext.)
     if (f->IsSVGText() && f->GetStateBits() & NS_FRAME_IS_NONDISPLAY) {
       auto svgTextFrame = static_cast<SVGTextFrame*>(
                             nsLayoutUtils::GetClosestFrameOfType(f,
                             nsGkAtoms::svgTextFrame));
-      svgTextFrame->ScheduleReflowSVGNonDisplayText();
+      svgTextFrame->ScheduleReflowSVGNonDisplayText(nsIPresShell::eResize);
     } else {
       // Theoretically we could just update overflow areas, perhaps using
       // OverflowChangedTracker, but that would do a bunch of work eagerly that
       // we should probably do lazily here since there could be a lot
       // of text frames affected and we'd like to coalesce the work. So that's
       // not easy to do well.
       shell->FrameNeedsReflow(f, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
     }
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -3317,17 +3317,17 @@ SVGTextFrame::DidSetStyleContext(nsStyle
     // on the parent of the <defs>, then in
     // nsSVGDisplayContainerFrame::ReflowSVG, we would find the non-display
     // <defs> container and then call ReflowSVGNonDisplayText on it.  If we do
     // not actually reflow the parent of the <defs>, then without this
     // DidSetStyleContext we would (a) not cause the <text>'s anonymous block
     // child to be reflowed when it is next painted, and (b) not cause the
     // <text> to be repainted anyway since the user of the <mask> would not
     // know it needs to be repainted.
-    ScheduleReflowSVGNonDisplayText();
+    ScheduleReflowSVGNonDisplayText(nsIPresShell::eStyleChange);
   }
 }
 
 void
 SVGTextFrame::ReflowSVGNonDisplayText()
 {
   MOZ_ASSERT(nsSVGUtils::AnyOuterSVGIsCallingReflowSVG(this),
              "only call ReflowSVGNonDisplayText when an outer SVG frame is "
@@ -3351,17 +3351,17 @@ SVGTextFrame::ReflowSVGNonDisplayText()
   // Finally, we need to actually reflow the anonymous block frame and update
   // mPositions, in case we are being reflowed immediately after a DOM
   // mutation that needs frame reconstruction.
   MaybeReflowAnonymousBlockChild();
   UpdateGlyphPositioning();
 }
 
 void
-SVGTextFrame::ScheduleReflowSVGNonDisplayText()
+SVGTextFrame::ScheduleReflowSVGNonDisplayText(nsIPresShell::IntrinsicDirty aReason)
 {
   MOZ_ASSERT(!nsSVGUtils::OuterSVGIsCallingReflowSVG(this),
              "do not call ScheduleReflowSVGNonDisplayText when the outer SVG "
              "frame is under ReflowSVG");
   MOZ_ASSERT(!(mState & NS_STATE_SVG_TEXT_IN_REFLOW),
              "do not call ScheduleReflowSVGNonDisplayText while reflowing the "
              "anonymous block child");
 
@@ -3390,17 +3390,17 @@ SVGTextFrame::ScheduleReflowSVGNonDispla
       f->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
     }
     f = f->GetParent();
   }
 
   MOZ_ASSERT(f, "should have found an ancestor frame to reflow");
 
   PresContext()->PresShell()->FrameNeedsReflow(
-    f, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
+    f, aReason, NS_FRAME_IS_DIRTY);
 }
 
 NS_IMPL_ISUPPORTS(SVGTextFrame::MutationObserver, nsIMutationObserver)
 
 void
 SVGTextFrame::MutationObserver::ContentAppended(nsIDocument* aDocument,
                                                 nsIContent* aContainer,
                                                 nsIContent* aFirstNewContent,
@@ -5292,17 +5292,17 @@ SVGTextFrame::ShouldRenderAsPath(nsTextF
 
   return false;
 }
 
 void
 SVGTextFrame::ScheduleReflowSVG()
 {
   if (mState & NS_FRAME_IS_NONDISPLAY) {
-    ScheduleReflowSVGNonDisplayText();
+    ScheduleReflowSVGNonDisplayText(nsIPresShell::eStyleChange);
   } else {
     nsSVGUtils::ScheduleReflowSVG(this);
   }
 }
 
 void
 SVGTextFrame::NotifyGlyphMetricsChange()
 {
--- a/layout/svg/SVGTextFrame.h
+++ b/layout/svg/SVGTextFrame.h
@@ -398,17 +398,17 @@ public:
    * be called on its closest display container frame, so that
    * nsSVGDisplayContainerFrame::ReflowSVG will call ReflowSVGNonDisplayText on
    * it.
    *
    * The only case where we have to do this is in response to a style change on
    * a non-display <text>. It is done in response to glyphs changes on
    * non-display <text> (i.e., animated SVG-in-OpenType glyphs).
    */
-  void ScheduleReflowSVGNonDisplayText();
+  void ScheduleReflowSVGNonDisplayText(nsIPresShell::IntrinsicDirty aReason);
 
   /**
    * Updates the mFontSizeScaleFactor value by looking at the range of
    * font-sizes used within the <text>.
    *
    * @return Whether mFontSizeScaleFactor changed.
    */
   bool UpdateFontSizeScaleFactor();