Bug 885608 - Call ScheduleReflowSVGNonDisplayText on character data mutations in a non-display <text>. r=longsonr
authorCameron McCormack <cam@mcc.id.au>
Sat, 22 Jun 2013 12:38:57 +1000
changeset 136066 15ecbcd8e3fc5599c7e7e58f472e5b338d2b472a
parent 136065 7c8506b0729d23129ed4154823f2f2c4e2bc6614
child 136067 963013a5a11d6a7c180579ce96612eba1c3bc2de
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewerslongsonr
bugs885608
milestone24.0a1
Bug 885608 - Call ScheduleReflowSVGNonDisplayText on character data mutations in a non-display <text>. r=longsonr
layout/svg/crashtests/885608-1.svg
layout/svg/crashtests/crashtests.list
layout/svg/nsSVGTextFrame2.cpp
layout/svg/nsSVGTextFrame2.h
new file mode 100644
--- /dev/null
+++ b/layout/svg/crashtests/885608-1.svg
@@ -0,0 +1,13 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+
+<mask id="m"><text id="t">z</text></mask>
+
+<rect width="600" height="400" mask="url(#m)"/>
+
+<script>
+window.addEventListener("load", function() {
+  document.getElementById("t").firstChild.data = "ab";
+}, false);
+</script>
+
+</svg>
--- a/layout/svg/crashtests/crashtests.list
+++ b/layout/svg/crashtests/crashtests.list
@@ -163,8 +163,9 @@ load 849688-1.svg
 load 849688-2.svg
 load 860378-1.svg
 load 868904-1.svg
 load 873806-1.svg
 load 876831-1.svg
 load 877029-1.svg
 load 880925-1.svg
 load 881031-1.svg
+load 885608-1.svg
--- a/layout/svg/nsSVGTextFrame2.cpp
+++ b/layout/svg/nsSVGTextFrame2.cpp
@@ -3131,16 +3131,25 @@ nsSVGTextFrame2::MutationObserver::Conte
                                        nsIContent* aChild,
                                        int32_t aIndexInContainer,
                                        nsIContent* aPreviousSibling)
 {
   mFrame->NotifyGlyphMetricsChange();
 }
 
 void
+nsSVGTextFrame2::MutationObserver::CharacterDataChanged(
+                                                 nsIDocument* aDocument,
+                                                 nsIContent* aContent,
+                                                 CharacterDataChangeInfo* aInfo)
+{
+  mFrame->NotifyGlyphMetricsChange();
+}
+
+void
 nsSVGTextFrame2::MutationObserver::AttributeChanged(
                                                 nsIDocument* aDocument,
                                                 mozilla::dom::Element* aElement,
                                                 int32_t aNameSpaceID,
                                                 nsIAtom* aAttribute,
                                                 int32_t aModType)
 {
   if (!aElement->IsSVG()) {
@@ -3241,17 +3250,17 @@ nsSVGTextFrame2::NotifySVGChanged(uint32
   }
 
   if (needNewBounds) {
     // Ancestor changes can't affect how we render from the perspective of
     // any rendering observers that we may have, so we don't need to
     // invalidate them. We also don't need to invalidate ourself, since our
     // changed ancestor will have invalidated its entire area, which includes
     // our area.
-    nsSVGUtils::ScheduleReflowSVG(this);
+    ScheduleReflowSVG();
   }
 
   if (needGlyphMetricsUpdate) {
     // If we are positioned using percentage values we need to update our
     // position whenever our viewport's dimensions change.  But only do this if
     // we have been reflowed once, otherwise the glyph positioning will be
     // wrong.  (We need to wait until bidi reordering has been done.)
     if (!(mState & NS_FRAME_FIRST_REFLOW)) {
@@ -4763,21 +4772,31 @@ nsSVGTextFrame2::ShouldRenderAsPath(nsRe
                                  style->mStrokeWidth) == 0)) {
     return true;
   }
 
   return false;
 }
 
 void
+nsSVGTextFrame2::ScheduleReflowSVG()
+{
+  if (mState & NS_STATE_SVG_NONDISPLAY_CHILD) {
+    ScheduleReflowSVGNonDisplayText();
+  } else {
+    nsSVGUtils::ScheduleReflowSVG(this);
+  }
+}
+
+void
 nsSVGTextFrame2::NotifyGlyphMetricsChange()
 {
   mPositioningDirty = true;
   nsSVGEffects::InvalidateRenderingObservers(this);
-  nsSVGUtils::ScheduleReflowSVG(this);
+  ScheduleReflowSVG();
 }
 
 void
 nsSVGTextFrame2::UpdateGlyphPositioning()
 {
   nsIFrame* kid = GetFirstPrincipalChild();
   if (!kid) {
     return;
--- a/layout/svg/nsSVGTextFrame2.h
+++ b/layout/svg/nsSVGTextFrame2.h
@@ -275,16 +275,22 @@ public:
 
   /**
    * Schedules mPositions to be recomputed and the covered region to be
    * updated.
    */
   void NotifyGlyphMetricsChange();
 
   /**
+   * Calls ScheduleReflowSVGNonDisplayText if this is a non-display frame,
+   * and nsSVGUtils::ScheduleReflowSVG otherwise.
+   */
+  void ScheduleReflowSVG();
+
+  /**
    * Reflows the anonymous block frame of this non-display nsSVGTextFrame2.
    *
    * When we are under nsSVGDisplayContainerFrame::ReflowSVG, we need to
    * reflow any nsSVGTextFrame2 frames in the subtree in case they are
    * being observed (by being for example in a <mask>) and the change
    * that caused the reflow would not already have caused a reflow.
    *
    * Note that displayed nsSVGTextFrame2s are reflowed as needed, when PaintSVG
@@ -391,16 +397,17 @@ private:
 
     // nsISupports
     NS_DECL_ISUPPORTS
 
     // nsIMutationObserver
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
+    NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
     NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
 
   private:
     nsSVGTextFrame2* mFrame;
   };
 
   /**
    * Reflows the anonymous block child if it is dirty or has dirty