Bug 717870 - whitespace compression setting need to be recalculated when text is added. r=dholbert
authorRobert Longson <longsonr@gmail.com>
Sat, 14 Jan 2012 10:07:26 +0000
changeset 85717 256c575375073285c36b73eca8db37142a2322ba
parent 85716 c7511462f15fad0e0e7955e5073fa13c9737c771
child 85718 2fb55a6e7c14af15d59e5d4ae3064af365f7e3f1
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs717870
milestone12.0a1
Bug 717870 - whitespace compression setting need to be recalculated when text is added. r=dholbert
layout/reftests/svg/dynamic-text-07-ref.svg
layout/reftests/svg/dynamic-text-07.svg
layout/reftests/svg/reftest.list
layout/svg/base/src/nsSVGGlyphFrame.h
layout/svg/base/src/nsSVGTextFrame.cpp
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/dynamic-text-07-ref.svg
@@ -0,0 +1,11 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg">
+  <title>Reference to check whitespace handling</title>
+
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=717870 -->
+
+  <text x="10" y="50" font-size="50">A B</text>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/dynamic-text-07.svg
@@ -0,0 +1,23 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait" onload="m();">
+  <title>Testcase to check whitespace handling</title>
+
+  <!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=717870 -->
+
+  <text id="t" x="10" y="50" font-size="50">A </text>
+  <script>
+    function m()
+    {
+      // Force frame construction
+      document.documentElement.getBoundingClientRect();
+
+      // A dynamic change
+      document.getElementById("t").appendChild(document.createTextNode("B"));
+      
+      document.documentElement.removeAttribute("class");
+    }
+  </script>
+</svg>
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -94,16 +94,17 @@ include svg-integration/reftest.list
 == dynamic-small-object-scaled-up-02.svg pass.svg
 == dynamic-switch-01.svg pass.svg
 == dynamic-text-01.svg dynamic-text-01-ref.svg
 == dynamic-text-02.svg dynamic-text-02-ref.svg
 == dynamic-text-03.svg dynamic-text-03-ref.svg
 fails-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == dynamic-text-04.svg dynamic-text-04-ref.svg # bug 421587 for WinXP
 == dynamic-text-05.svg pass.svg
 == dynamic-text-06.svg pass.svg
+== dynamic-text-07.svg dynamic-text-07-ref.svg
 == dynamic-textPath-01.svg dynamic-textPath-01-ref.svg
 == dynamic-use-01.svg pass.svg
 == dynamic-use-02.svg pass.svg
 == dynamic-use-03.svg pass.svg
 == dynamic-use-04.svg pass.svg
 == dynamic-use-05.svg pass.svg
 random == dynamic-use-nested-01.svg dynamic-use-nested-01-ref.svg # bug 467498
 == dynamic-use-remove-width.svg dynamic-use-remove-width-ref.svg
--- a/layout/svg/base/src/nsSVGGlyphFrame.h
+++ b/layout/svg/base/src/nsSVGGlyphFrame.h
@@ -116,20 +116,26 @@ public:
   void GetEffectiveRotate(PRInt32 strLength,
                           nsTArray<float> &aRotate);
   PRUint16 GetTextAnchor();
   bool IsAbsolutelyPositioned();
   bool IsTextEmpty() const {
     return mContent->GetText()->GetLength() == 0;
   }
   void SetTrimLeadingWhitespace(bool aTrimLeadingWhitespace) {
-    mTrimLeadingWhitespace = aTrimLeadingWhitespace;
+    if (mTrimLeadingWhitespace != aTrimLeadingWhitespace) {
+      mTrimLeadingWhitespace = aTrimLeadingWhitespace;
+      ClearTextRun();
+    }
   }
   void SetTrimTrailingWhitespace(bool aTrimTrailingWhitespace) {
-    mTrimTrailingWhitespace = aTrimTrailingWhitespace;
+    if (mTrimTrailingWhitespace != aTrimTrailingWhitespace) {
+      mTrimTrailingWhitespace = aTrimTrailingWhitespace;
+      ClearTextRun();
+    }
   }
   bool EndsWithWhitespace() const;
   bool IsAllWhitespace() const;
 
   // nsIFrame interface:
   NS_IMETHOD  CharacterDataChanged(CharacterDataChangeInfo* aInfo);
 
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
@@ -188,17 +194,20 @@ public:
   // These do not use the global transform if NS_STATE_NONDISPLAY_CHILD
   virtual PRUint32 GetNumberOfChars();
   virtual float GetComputedTextLength();
   virtual float GetSubStringLength(PRUint32 charnum, PRUint32 fragmentChars);
   virtual PRInt32 GetCharNumAtPosition(nsIDOMSVGPoint *point);
   NS_IMETHOD_(nsSVGGlyphFrame *) GetFirstGlyphFrame();
   NS_IMETHOD_(nsSVGGlyphFrame *) GetNextGlyphFrame();
   NS_IMETHOD_(void) SetWhitespaceCompression(bool aCompressWhitespace) {
-    mCompressWhitespace = aCompressWhitespace;
+    if (mCompressWhitespace != aCompressWhitespace) {
+      mCompressWhitespace = aCompressWhitespace;
+      ClearTextRun();
+    }
   }
 
 protected:
   friend class CharacterIterator;
 
   // Use a power of 2 here. It's not so important to match
   // nsDeviceContext::AppUnitsPerDevPixel, but since we do a lot of
   // multiplying by 1/GetTextRunUnitsFactor, it's good for it to be a
--- a/layout/svg/base/src/nsSVGTextFrame.cpp
+++ b/layout/svg/base/src/nsSVGTextFrame.cpp
@@ -293,30 +293,44 @@ nsSVGTextFrame::NotifyGlyphMetricsChange
   UpdateGlyphPositioning(false);
 }
 
 void
 nsSVGTextFrame::SetWhitespaceHandling(nsSVGGlyphFrame *aFrame)
 {
   SetWhitespaceCompression();
 
+  nsSVGGlyphFrame* firstFrame = aFrame;
   bool trimLeadingWhitespace = true;
   nsSVGGlyphFrame* lastNonWhitespaceFrame = aFrame;
 
+  // If the previous frame ended with whitespace
+  // then display of leading whitespace should be suppressed
+  // when we are compressing whitespace.
   while (aFrame) {
     if (!aFrame->IsAllWhitespace()) {
       lastNonWhitespaceFrame = aFrame;
     }
 
     aFrame->SetTrimLeadingWhitespace(trimLeadingWhitespace);
     trimLeadingWhitespace = aFrame->EndsWithWhitespace();
 
     aFrame = aFrame->GetNextGlyphFrame();
   }
 
+  // When there is only whitespace left we need to trim off
+  // the end of the last frame that isn't entirely whitespace.
+  // Making sure that we reset earlier frames as they may once
+  // have been the last non-whitespace frame.
+  aFrame = firstFrame;
+  while (aFrame != lastNonWhitespaceFrame) {
+    aFrame->SetTrimTrailingWhitespace(false);
+    aFrame = aFrame->GetNextGlyphFrame();
+  }
+
   lastNonWhitespaceFrame->SetTrimTrailingWhitespace(true);
 }
 
 void
 nsSVGTextFrame::UpdateGlyphPositioning(bool aForceGlobalTransform)
 {
   if (mMetricsState == suspended || !mPositioningDirty)
     return;