Correct bisector angle calculation for markers
authorpdr@google.com <pdr@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Mar 2013 20:35:36 +0000 (20:35 +0000)
committerpdr@google.com <pdr@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Mar 2013 20:35:36 +0000 (20:35 +0000)
https://bugs.webkit.org/show_bug.cgi?id=112054

Reviewed by Stephen Chenney.

Source/WebCore:

The SVG marker spec states that mid markers with orient=auto should be aligned with their
x-axis along the bisector of the incoming (in) and outgoing (out) angles. Previously we
calculated this bisector angle as:
    bisector = (in + out) / 2;
Angles cannot be averaged this way! Consider in=90deg and out=-180deg: the bisector should
be 135deg but a naive average gives -45deg. This patch corrects for the discontinuity in
angle values with:
    bisector = (in + out + 360) / 2   // if |in - out| > 180
    bisector = (in + out) / 2         // otherwise
This patch includes an exhaustive test of angle values.

Test: svg/custom/marker-orient-auto.html

* rendering/svg/SVGMarkerData.h:
(WebCore::SVGMarkerData::currentAngle):

LayoutTests:

* platform/chromium-linux/svg/custom/marker-orient-auto-expected.png: Added.
* platform/chromium-linux/svg/custom/marker-orient-auto-expected.txt: Added.
* platform/chromium/TestExpectations:
* svg/custom/marker-orient-auto.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@146510 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/platform/chromium-linux/svg/custom/marker-orient-auto-expected.png [new file with mode: 0644]
LayoutTests/platform/chromium-linux/svg/custom/marker-orient-auto-expected.txt [new file with mode: 0644]
LayoutTests/platform/chromium/TestExpectations
LayoutTests/svg/custom/marker-orient-auto.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/svg/SVGMarkerData.h

index 3b563d4..3fedb0e 100644 (file)
@@ -1,3 +1,15 @@
+2013-03-21  Philip Rogers  <pdr@google.com>
+
+        Correct bisector angle calculation for markers
+        https://bugs.webkit.org/show_bug.cgi?id=112054
+
+        Reviewed by Stephen Chenney.
+
+        * platform/chromium-linux/svg/custom/marker-orient-auto-expected.png: Added.
+        * platform/chromium-linux/svg/custom/marker-orient-auto-expected.txt: Added.
+        * platform/chromium/TestExpectations:
+        * svg/custom/marker-orient-auto.html: Added.
+
 2013-03-21  Harald Alvestrand  <hta@google.com>
 
         Expose the Type field of an RTCStatsReport
diff --git a/LayoutTests/platform/chromium-linux/svg/custom/marker-orient-auto-expected.png b/LayoutTests/platform/chromium-linux/svg/custom/marker-orient-auto-expected.png
new file mode 100644 (file)
index 0000000..5e21df8
Binary files /dev/null and b/LayoutTests/platform/chromium-linux/svg/custom/marker-orient-auto-expected.png differ
diff --git a/LayoutTests/platform/chromium-linux/svg/custom/marker-orient-auto-expected.txt b/LayoutTests/platform/chromium-linux/svg/custom/marker-orient-auto-expected.txt
new file mode 100644 (file)
index 0000000..62b7ec3
--- /dev/null
@@ -0,0 +1,15 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x561
+  RenderBlock {HTML} at (0,0) size 800x561
+    RenderBody {BODY} at (8,8) size 784x545
+      RenderText {#text} at (0,0) size 748x39
+        text run at (0,0) width 748: "Test for wkbug.com/112054. This test passes if the green star has orange markers pointing outside only and the blue star has"
+        text run at (0,20) width 216: "orange markers pointing inside only."
+      RenderBR {BR} at (216,20) size 0x19
+      RenderSVGRoot {svg} at (15,55) size 394x206
+        RenderSVGResourceMarker {marker} [id="marker"] [markerUnits=strokeWidth] [ref at (0,0)] [angle=auto]
+          RenderSVGPath {path} at (8,48) size 5x6 [stroke={[type=SOLID] [color=#000000] [stroke width=0.50]}] [fill={[type=SOLID] [color=#FFA500]}] [data="M 0 0 L 4 0 L 2 5 L 0 0 Z"]
+        RenderSVGPath {path} at (15,55) size 206x206 [stroke={[type=SOLID] [color=#008000] [stroke width=2.00]}] [middle marker=marker] [data="M 156 189.674 L 158.215 180.153 L 152.243 162.166 L 140.89 142.551 L 129.972 127.983 L 125.867 122.175 L 132.54 124.637 L 149.437 131.413 L 171.321 137.302 L 190.242 138.415 L 198.865 133.811 L 193.699 125.513 L 176.757 117.016 L 154.86 111.175 L 136.839 108.593 L 129.829 107.389 L 136.288 104.412 L 153.027 97.2547 L 172.666 85.9447 L 186.832 73.3529 L 189.674 64 L 180.153 61.7849 L 162.166 67.7571 L 142.551 79.1098 L 127.983 90.0277 L 122.175 94.1329 L 124.637 87.4604 L 131.413 70.5627 L 137.302 48.6786 L 138.415 29.758 L 133.811 21.1348 L 125.513 26.3008 L 117.016 43.2431 L 111.175 65.14 L 108.593 83.1614 L 107.389 90.1711 L 104.412 83.7119 L 97.2547 66.9726 L 85.9447 47.3338 L 73.3529 33.1678 L 64 30.3257 L 61.7849 39.8466 L 67.7571 57.8344 L 79.1098 77.4485 L 90.0277 92.0169 L 94.1329 97.8248 L 87.4604 95.3626 L 70.5627 88.5873 L 48.6786 82.698 L 29.758 81.5848 L 21.1348 86.1886 L 26.3008 94.4873 L 43.2431 102.984 L 65.14 108.825 L 83.1614 111.407 L 90.1711 112.611 L 83.7119 115.588 L 66.9726 122.745 L 47.3338 134.055 L 33.1678 146.647 L 30.3257 156 L 39.8466 158.215 L 57.8344 152.243 L 77.4485 140.89 L 92.0169 129.972 L 97.8248 125.867 L 95.3626 132.54 L 88.5873 149.437 L 82.698 171.321 L 81.5848 190.242 L 86.1886 198.865 L 94.4873 193.699 L 102.984 176.757 L 108.825 154.86 L 111.407 136.839 L 112.611 129.829 L 115.588 136.288 L 122.745 153.027 L 134.055 172.666 L 146.647 186.832"]
+        RenderSVGPath {path} at (227,67) size 182x182 [stroke={[type=SOLID] [color=#0000FF] [stroke width=2.00]}] [middle marker=marker] [data="M 356 189.674 L 346.647 186.832 L 334.055 172.666 L 322.745 153.027 L 315.588 136.288 L 312.611 129.829 L 311.407 136.839 L 308.825 154.86 L 302.984 176.757 L 294.487 193.699 L 286.189 198.865 L 281.585 190.242 L 282.698 171.321 L 288.587 149.437 L 295.363 132.54 L 297.825 125.867 L 292.017 129.972 L 277.449 140.89 L 257.834 152.243 L 239.847 158.215 L 230.326 156 L 233.168 146.647 L 247.334 134.055 L 266.973 122.745 L 283.712 115.588 L 290.171 112.611 L 283.161 111.407 L 265.14 108.825 L 243.243 102.984 L 226.301 94.4873 L 221.135 86.1886 L 229.758 81.5848 L 248.679 82.698 L 270.563 88.5873 L 287.46 95.3626 L 294.133 97.8248 L 290.028 92.0169 L 279.11 77.4485 L 267.757 57.8344 L 261.785 39.8466 L 264 30.3257 L 273.353 33.1678 L 285.945 47.3338 L 297.255 66.9726 L 304.412 83.7119 L 307.389 90.1711 L 308.593 83.1614 L 311.175 65.14 L 317.016 43.2431 L 325.513 26.3008 L 333.811 21.1348 L 338.415 29.758 L 337.302 48.6786 L 331.413 70.5627 L 324.637 87.4604 L 322.175 94.1329 L 327.983 90.0277 L 342.551 79.1098 L 362.166 67.7571 L 380.153 61.7849 L 389.674 64 L 386.832 73.3529 L 372.666 85.9447 L 353.027 97.2547 L 336.288 104.412 L 329.829 107.389 L 336.839 108.593 L 354.86 111.175 L 376.757 117.016 L 393.699 125.513 L 398.865 133.811 L 390.242 138.415 L 371.321 137.302 L 349.437 131.413 L 332.54 124.637 L 325.867 122.175 L 329.972 127.983 L 340.89 142.551 L 352.243 162.166 L 358.215 180.153"]
+      RenderText {#text} at (0,0) size 0x0
index fc974a3..3225bdc 100644 (file)
@@ -1379,6 +1379,9 @@ webkit.org/b/85107 svg/as-image/animated-svg-as-image.html [ ImageOnlyFailure Pa
 
 webkit.org/b/93589 svg/dom/SVGScriptElement/script-change-externalResourcesRequired-while-loading.svg [ Failure Pass Timeout ]
 
+# This test needs a rebaseline after https://bugs.webkit.org/show_bug.cgi?id=112054
+webkit.org/b/112054 svg/custom/marker-orient-auto.html
+
 webkit.org/b/111626 [ Mac Debug ] svg/css/font-face-crash.html [ Pass Crash ]
 
 # -----------------------------------------------------------------
diff --git a/LayoutTests/svg/custom/marker-orient-auto.html b/LayoutTests/svg/custom/marker-orient-auto.html
new file mode 100644 (file)
index 0000000..1aa258d
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+  function startTest() {
+    starPath(document.getElementById("marker-path-cw"), true, 110, 110, 56, 8, 36, 80, Math.PI/6);
+    starPath(document.getElementById("marker-path-ccw"), false, 310, 110, 56, 8, 36, 80, Math.PI/6);
+  }
+
+  // Generate a star path
+  //   cw - true for clockwise, false for counter-clockwise
+  //   centered at (cx,cy)
+  //   radius r
+  //   s 'spikes' of length l
+  //   n total vertices
+  //   t rotation
+  function starPath(el, cw, cx, cy, r, s, l, n, t) {
+    var d = "";
+    for (var i=0; i<=2*Math.PI; i+=2*Math.PI/n) {
+      var a = cw ? i : -i;
+      var px = cx + (r+l*Math.cos(a*s))*Math.sin(a+t);
+      var py = cy + (r+l*Math.cos(a*s))*Math.cos(a+t);
+      d += (d.length ? "L" : "M") + px + " " + py;
+    }
+    el.setAttribute("d", d);
+  }
+</script>
+<style>
+#marker-path-cw {
+  stroke: green;
+}
+#marker-path-ccw {
+  stroke: blue;
+}
+.marker-path {
+  fill: none;
+  stroke-width: 2px;
+  marker-mid: url(#marker);
+}
+</style>
+</head>
+<body onload="startTest()">
+Test for wkbug.com/112054.
+This test passes if the green star has orange markers pointing outside only and the blue star has orange markers pointing inside only.<br/>
+<svg width="500" height="500">
+  <marker id="marker" markerWidth="15" markerHeight="15" orient="auto">
+    <!-- This marker points in the direction of the bisector angle. -->
+    <path d="M0 0L4 0L2 5L0 0Z" fill="orange" stroke-width='0.5px' stroke='black'/> 
+  </marker>
+  <path id="marker-path-cw" class="marker-path"/>
+  <path id="marker-path-ccw" class="marker-path"/>
+</svg>
+</body>
+</html>
index ed573e2..8b8bee7 100644 (file)
@@ -1,3 +1,26 @@
+2013-03-21  Philip Rogers  <pdr@google.com>
+
+        Correct bisector angle calculation for markers
+        https://bugs.webkit.org/show_bug.cgi?id=112054
+
+        Reviewed by Stephen Chenney.
+
+        The SVG marker spec states that mid markers with orient=auto should be aligned with their
+        x-axis along the bisector of the incoming (in) and outgoing (out) angles. Previously we
+        calculated this bisector angle as:
+            bisector = (in + out) / 2;
+        Angles cannot be averaged this way! Consider in=90deg and out=-180deg: the bisector should
+        be 135deg but a naive average gives -45deg. This patch corrects for the discontinuity in
+        angle values with:
+            bisector = (in + out + 360) / 2   // if |in - out| > 180
+            bisector = (in + out) / 2         // otherwise
+        This patch includes an exhaustive test of angle values.
+
+        Test: svg/custom/marker-orient-auto.html
+
+        * rendering/svg/SVGMarkerData.h:
+        (WebCore::SVGMarkerData::currentAngle):
+
 2013-03-21  Harald Alvestrand  <hta@google.com>
 
         Expose the Type field of an RTCStatsReport
index 09a542b..6c70f42 100644 (file)
@@ -82,19 +82,23 @@ public:
 private:
     float currentAngle(SVGMarkerType type) const
     {
-        FloatPoint inslopeChange(m_inslopePoints[1] - m_inslopePoints[0]);
-        FloatPoint outslopeChange(m_outslopePoints[1] - m_outslopePoints[0]);
+        // For details of this calculation, see: http://www.w3.org/TR/SVG/single-page.html#painting-MarkerElement
+        FloatPoint inSlope(m_inslopePoints[1] - m_inslopePoints[0]);
+        FloatPoint outSlope(m_outslopePoints[1] - m_outslopePoints[0]);
 
-        double inslope = rad2deg(inslopeChange.slopeAngleRadians());
-        double outslope = rad2deg(outslopeChange.slopeAngleRadians());
+        double inAngle = rad2deg(inSlope.slopeAngleRadians());
+        double outAngle = rad2deg(outSlope.slopeAngleRadians());
 
         switch (type) {
         case StartMarker:
-            return narrowPrecisionToFloat(outslope);
+            return narrowPrecisionToFloat(outAngle);
         case MidMarker:
-            return narrowPrecisionToFloat((inslope + outslope) / 2);
+            // WK193015: Prevent bugs due to angles being non-continuous.
+            if (fabs(inAngle - outAngle) > 180)
+                inAngle += 360;
+            return narrowPrecisionToFloat((inAngle + outAngle) / 2);
         case EndMarker:
-            return narrowPrecisionToFloat(inslope);
+            return narrowPrecisionToFloat(inAngle);
         }
 
         ASSERT_NOT_REACHED();