Reland: Ensure arcTo (SVG) ends at the targeted point

Floating-point errors in the calculations in arcTo can cause the final
point to differ significantly enough from the supplied target point that
a subsequent 'close' operation inserts a lineTo to close the curve. This
can result in bad miters on curves with thick outlines.

The fix is to ensure that the final point used is *exactly* the point
that was supplied.

The fix is now staged behind a flag so that we can fix Chromium test
failures before turning it on.

Bug: chromium:1001768
Change-Id: I82d872f2ae39b5486f7d810a61ba00eeda1b3a62
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/270503
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Mike Reed <reed@google.com>
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index 5afe53a..87163a5 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -1262,6 +1262,12 @@
         this->conicTo(mapped[0], mapped[1], w);
         startTheta = endTheta;
     }
+
+#ifndef SK_LEGACY_PATH_ARCTO_ENDPOINT
+    // The final point should match the input point (by definition); replace it to
+    // ensure that rounding errors in the above math don't cause any problems.
+    this->setLastPt(x, y);
+#endif
     return *this;
 }
 
diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp
index b94c45f..60b1029 100644
--- a/tests/PathTest.cpp
+++ b/tests/PathTest.cpp
@@ -3908,6 +3908,20 @@
     p.reset();
     p.arcTo(noOvalHeight, 0, 360, false);
     REPORTER_ASSERT(reporter, p.isEmpty());
+
+#ifndef SK_LEGACY_PATH_ARCTO_ENDPOINT
+    // Inspired by http://code.google.com/p/chromium/issues/detail?id=1001768
+    {
+      p.reset();
+      p.moveTo(216, 216);
+      p.arcTo(216, 108, 0, SkPath::ArcSize::kLarge_ArcSize, SkPathDirection::kCW, 216, 0);
+      p.arcTo(270, 135, 0, SkPath::ArcSize::kLarge_ArcSize, SkPathDirection::kCCW, 216, 216);
+
+      // The 'arcTo' call should end up exactly at the starting location.
+      int n = p.countPoints();
+      REPORTER_ASSERT(reporter, p.getPoint(0) == p.getPoint(n - 1));
+    }
+#endif
 }
 
 static void test_addPath(skiatest::Reporter* reporter) {