Bug 1417841 - Don't reset <textPath> first character coordinate to 0 when an ancestor text content element specifies an explicit position coordinate. r?longsonr draft
authorCameron McCormack <cam@mcc.id.au>
Thu, 16 Nov 2017 13:19:11 +0800
changeset 699009 b0e19c4fa8a802a24895257e0678e8c402b800a4
parent 698679 f41930a869a84af81df1a88d8e82323ff3a6509a
child 740496 75a92497f9220882601303fd9f5fc09101e08ea9
push id89424
push userbmo:cam@mcc.id.au
push dateThu, 16 Nov 2017 10:13:23 +0000
reviewerslongsonr
bugs1417841
milestone59.0a1
Bug 1417841 - Don't reset <textPath> first character coordinate to 0 when an ancestor text content element specifies an explicit position coordinate. r?longsonr MozReview-Commit-ID: KpJCuYwXxXC
layout/reftests/svg/text/reftest.list
layout/reftests/svg/text/textpath-inherit-position-ref.svg
layout/reftests/svg/text/textpath-inherit-position.svg
layout/reftests/svg/text/textpath-reset-position-ref.svg
layout/reftests/svg/text/textpath-reset-position.svg
layout/reftests/svg/textPath-02.svg
layout/svg/SVGTextFrame.cpp
--- a/layout/reftests/svg/text/reftest.list
+++ b/layout/reftests/svg/text/reftest.list
@@ -114,16 +114,18 @@ fuzzy-if(skiaContent,1,15) == textpath.s
 == textpath-a.svg textpath-a-ref.svg
 == textpath-anchor-middle.svg textpath-anchor-middle-ref.svg
 == textpath-anchor-end.svg textpath-anchor-end-ref.svg
 == textpath-invalid-parent.svg textpath-invalid-parent-ref.svg
 == textpath-multiline.svg textpath-multiline-ref.svg
 == textpath-multiline-2.svg textpath-multiline-2-ref.svg
 == textpath-after.svg textpath-after-ref.svg
 == textpath-after-anchor-end.svg textpath-after-anchor-end-ref.svg
+== textpath-reset-position.svg textpath-reset-position-ref.svg
+== textpath-inherit-position.svg textpath-inherit-position-ref.svg
 
 == textLength.svg textLength-ref.svg
 fuzzy-if(skiaContent,1,200) == textLength-2.svg textLength-2-ref.svg
 fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.[12]/.test(http.oscpu),4,17) fuzzy-if(skiaContent,4,100) == textLength-3.svg textLength-3-ref.svg
 == textLength-4.svg textLength-4-ref.svg
 == textLength-5.svg textLength-5-ref.svg
 == textLength-6.svg textLength-6-ref.svg
 
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/text/textpath-inherit-position-ref.svg
@@ -0,0 +1,10 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+  <g transform="translate(150,50)" style="font: 32px sans-serif">
+    <path id="p" d="M 100,100 l 100,100"/>
+    <text x="0 20 40 60 80">hello <textPath xlink:href="#p"><tspan x="50">there</tspan></textPath></text>
+  </g>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/text/textpath-inherit-position.svg
@@ -0,0 +1,10 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+  <g transform="translate(150,50)" style="font: 32px sans-serif">
+    <path id="p" d="M 100,100 l 100,100"/>
+    <text x="0 20 40 60 80 100 50">hello <textPath xlink:href="#p">there</textPath></text>
+  </g>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/text/textpath-reset-position-ref.svg
@@ -0,0 +1,10 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+  <g transform="translate(150,50)" style="font: 32px sans-serif">
+    <path id="p" d="M 100,100 l 100,100"/>
+    <text x="50">hello <textPath xlink:href="#p"><tspan x="0">there</tspan></textPath></text>
+  </g>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/text/textpath-reset-position.svg
@@ -0,0 +1,10 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+  <g transform="translate(150,50)" style="font: 32px sans-serif">
+    <path id="p" d="M 100,100 l 100,100"/>
+    <text x="50">hello <textPath xlink:href="#p">there</textPath></text>
+  </g>
+</svg>
--- a/layout/reftests/svg/textPath-02.svg
+++ b/layout/reftests/svg/textPath-02.svg
@@ -3,13 +3,13 @@
      http://creativecommons.org/publicdomain/zero/1.0/
 -->
 <svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
   <title>Test effect on startOffset of a scale transform on a textPath's path</title>
   <defs>
     <path id="path" d="M20,20 C20,150 150,150 150,20" pathLength="100" transform="scale(2,1)" fill="none" stroke="black"/>
   </defs>
   <rect width="100%" height="100%" fill="lime"/>
-  <text y="50">
+  <text>
     <textPath xlink:href="#path" font-size="20" fill="red" startOffset="50">FAIL</textPath>
   </text>
   <rect x="160" y="80" width="100" height="60" fill="lime"/>
 </svg>
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -4576,25 +4576,32 @@ SVGTextFrame::ResolvePositionsForNode(ns
   }
 
   // Skip past elements that aren't text content elements.
   if (!IsTextContentElement(aContent)) {
     return true;
   }
 
   if (aContent->IsSVGElement(nsGkAtoms::textPath)) {
-    // <textPath> elements are as if they are specified with x="0" y="0", but
-    // only if they actually have some text content.
+    // <textPath> elements behave as if they have x="0" y="0" on them, but only
+    // if there is not a value for the coordinates that got inherited from a
+    // parent.  We skip this if there is no text content, so that empty
+    // <textPath>s don't interrupt the layout of text in the parent element.
     if (HasTextContent(aContent)) {
       if (MOZ_UNLIKELY(aIndex >= mPositions.Length())) {
         MOZ_ASSERT_UNREACHABLE("length of mPositions does not match characters "
                                "found by iterating content");
         return false;
       }
-      mPositions[aIndex].mPosition = gfxPoint();
+      if (!mPositions[aIndex].IsXSpecified()) {
+        mPositions[aIndex].mPosition.x = 0.0;
+      }
+      if (!mPositions[aIndex].IsYSpecified()) {
+        mPositions[aIndex].mPosition.y = 0.0;
+      }
       mPositions[aIndex].mStartOfChunk = true;
     }
   } else if (!aContent->IsSVGElement(nsGkAtoms::a)) {
     // We have a text content element that can have x/y/dx/dy/rotate attributes.
     nsSVGElement* element = static_cast<nsSVGElement*>(aContent);
 
     // Get x, y, dx, dy.
     SVGUserUnitList x, y, dx, dy;