Bug 855183 - Reflow SVG text sooner on full page zoom. r=longsonr
authorCameron McCormack <cam@mcc.id.au>
Thu, 28 Mar 2013 10:55:55 +1100
changeset 126485 40b1eec8a12a38689abe843fe42e98b8d08baa1f
parent 126484 a4ae083f9caf98377f343575707b75a5be1f69c3
child 126486 e3e6a4b4502851cd0aa8018d04593bc40abd82c4
push id24485
push userryanvm@gmail.com
push dateThu, 28 Mar 2013 12:31:20 +0000
treeherdermozilla-central@293498096b28 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslongsonr
bugs855183
milestone22.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 855183 - Reflow SVG text sooner on full page zoom. r=longsonr
layout/svg/nsSVGTextFrame2.cpp
layout/svg/nsSVGTextFrame2.h
--- a/layout/svg/nsSVGTextFrame2.cpp
+++ b/layout/svg/nsSVGTextFrame2.cpp
@@ -2819,24 +2819,30 @@ SVGTextDrawPathCallbacks::FillAndStroke(
 
 // -----------------------------------------------------------------------------
 // GlyphMetricsUpdater
 
 NS_IMETHODIMP
 GlyphMetricsUpdater::Run()
 {
   if (mFrame) {
-    mFrame->mPositioningDirty = true;
-    nsSVGUtils::InvalidateBounds(mFrame, false);
-    nsSVGUtils::ScheduleReflowSVG(mFrame);
-    mFrame->mGlyphMetricsUpdater = nullptr;
+    Run(mFrame);
   }
   return NS_OK;
 }
 
+void
+GlyphMetricsUpdater::Run(nsSVGTextFrame2* aFrame)
+{
+  aFrame->mPositioningDirty = true;
+  nsSVGUtils::InvalidateBounds(aFrame, false);
+  nsSVGUtils::ScheduleReflowSVG(aFrame);
+  aFrame->mGlyphMetricsUpdater = nullptr;
+}
+
 }
 
 // ============================================================================
 // nsSVGTextFrame2
 
 // ----------------------------------------------------------------------------
 // Display list item
 
@@ -4640,35 +4646,44 @@ nsSVGTextFrame2::ShouldRenderAsPath(nsRe
                                  style->mStrokeWidth) == 0)) {
     return true;
   }
 
   return false;
 }
 
 void
-nsSVGTextFrame2::NotifyGlyphMetricsChange()
+nsSVGTextFrame2::NotifyGlyphMetricsChange(uint32_t aFlags)
 {
-  // We need to perform the operations in GlyphMetricsUpdater in a
-  // script runner since we can get called just after a DOM mutation,
-  // before frames have been reconstructed, and UpdateGlyphPositioning
-  // will be called with out-of-date frames.  This occurs when the
-  // <text> element is being filtered, as the InvalidateBounds()
-  // call needs to call in to GetBBoxContribution() to determine the
-  // filtered region, and that needs to iterate over the text frames.
-  // We would flush frame construction, but that needs to be done
-  // inside a script runner.
-  //
-  // Much of the time, this will perform the GlyphMetricsUpdater
-  // operations immediately.
-  if (mGlyphMetricsUpdater) {
+  NS_ASSERTION(!aFlags || aFlags == ePositioningDirtyDueToMutation,
+               "unexpected aFlags value");
+
+  if (aFlags == ePositioningDirtyDueToMutation) {
+    // We need to perform the operations in GlyphMetricsUpdater in a
+    // script runner since we can get called just after a DOM mutation,
+    // before frames have been reconstructed, and UpdateGlyphPositioning
+    // will be called with out-of-date frames.  This occurs when the
+    // <text> element is being filtered, as the InvalidateBounds()
+    // call needs to call in to GetBBoxContribution() to determine the
+    // filtered region, and that needs to iterate over the text frames.
+    // We would flush frame construction, but that needs to be done
+    // inside a script runner.
+    //
+    // Much of the time, this will perform the GlyphMetricsUpdater
+    // operations immediately.
+    if (mGlyphMetricsUpdater) {
+      return;
+    }
+    mGlyphMetricsUpdater = new GlyphMetricsUpdater(this);
+    nsContentUtils::AddScriptRunner(mGlyphMetricsUpdater.get());
     return;
   }
-  mGlyphMetricsUpdater = new GlyphMetricsUpdater(this);
-  nsContentUtils::AddScriptRunner(mGlyphMetricsUpdater.get());
+
+  // Otherwise, we perform the glyph metrics update immediately.
+  GlyphMetricsUpdater::Run(this);
 }
 
 void
 nsSVGTextFrame2::UpdateGlyphPositioning(bool aForceGlobalTransform)
 {
   nsIFrame* kid = GetFirstPrincipalChild();
   if (!kid)
     return;
--- a/layout/svg/nsSVGTextFrame2.h
+++ b/layout/svg/nsSVGTextFrame2.h
@@ -122,16 +122,17 @@ private:
 /**
  * A runnable to mark glyph positions as needing to be recomputed
  * and to invalid the bounds of the nsSVGTextFrame2 frame.
  */
 class GlyphMetricsUpdater : public nsRunnable {
 public:
   NS_DECL_NSIRUNNABLE
   GlyphMetricsUpdater(nsSVGTextFrame2* aFrame) : mFrame(aFrame) { }
+  static void Run(nsSVGTextFrame2* aFrame);
   void Revoke() { mFrame = nullptr; }
 private:
   nsSVGTextFrame2* mFrame;
 };
 
 }
 
 /**
@@ -269,19 +270,26 @@ public:
                            mozilla::dom::SVGIRect** aResult);
   nsresult GetRotationOfChar(nsIContent* aContent, uint32_t aCharNum,
                              float* aResult);
 
   // nsSVGTextFrame2 methods:
 
   /**
    * Schedules mPositions to be recomputed and the covered region to be
-   * updated.
+   * updated.  The aFlags argument can take the ePositioningDirtyDueToMutation
+   * value to indicate that glyph metrics need to be recomputed due to
+   * a DOM mutation in the <text> element on one of its descendants.
    */
-  void NotifyGlyphMetricsChange();
+  void NotifyGlyphMetricsChange(uint32_t aFlags = 0);
+
+  /**
+   * Enum for NotifyGlyphMetricsChange's aFlags argument.
+   */
+  enum { ePositioningDirtyDueToMutation = 1 };
 
   /**
    * Updates the mFontSizeScaleFactor value by looking at the range of
    * font-sizes used within the <text>.
    */
   void UpdateFontSizeScaleFactor(bool aForceGlobalTransform);
 
   double GetFontSizeScaleFactor() const;