keep SVG arcs axis aligned with suppression

another attempt at https://skia-review.googlesource.com/c/skia/+/79423

this time, bracket change with SK_SUPPORT_LEGACY_SVG_ARC_TO
to avoid prematurely changing SVG layout test results.

R=djsollen@google.com
Bug: b:69622768
Change-Id: Ia929f89d4f4292dfead191a381cdb431f743726a
Reviewed-on: https://skia-review.googlesource.com/82723
Commit-Queue: Cary Clark <caryclark@google.com>
Reviewed-by: Derek Sollenberger <djsollen@google.com>
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index c433424..422c2b9 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -1417,7 +1417,12 @@
     pointTransform.setRotate(angle);
     pointTransform.preScale(rx, ry);
 
+#ifdef SK_SUPPORT_LEGACY_SVG_ARC_TO
     int segments = SkScalarCeilToInt(SkScalarAbs(thetaArc / (SK_ScalarPI / 2)));
+#else
+    // the arc may be slightly bigger than 1/4 circle, so allow up to 1/3rd
+    int segments = SkScalarCeilToInt(SkScalarAbs(thetaArc / (2 * SK_ScalarPI / 3)));
+#endif
     SkScalar thetaWidth = thetaArc / segments;
     SkScalar t = SkScalarTan(0.5f * thetaWidth);
     if (!SkScalarIsFinite(t)) {
@@ -1425,6 +1430,14 @@
     }
     SkScalar startTheta = theta1;
     SkScalar w = SkScalarSqrt(SK_ScalarHalf + SkScalarCos(thetaWidth) * SK_ScalarHalf);
+#ifndef SK_SUPPORT_LEGACY_SVG_ARC_TO
+    auto scalar_is_integer = [](SkScalar scalar) -> bool {
+        return scalar == SkScalarFloorToScalar(scalar);
+    };
+    bool expectIntegers = SkScalarNearlyZero(SK_ScalarPI/2 - SkScalarAbs(thetaWidth)) &&
+        scalar_is_integer(rx) && scalar_is_integer(ry) &&
+        scalar_is_integer(x) && scalar_is_integer(y);
+#endif
     for (int i = 0; i < segments; ++i) {
         SkScalar endTheta = startTheta + thetaWidth;
         SkScalar cosEndTheta, sinEndTheta = SkScalarSinCos(endTheta, &cosEndTheta);
@@ -1435,6 +1448,19 @@
         unitPts[0].offset(t * sinEndTheta, -t * cosEndTheta);
         SkPoint mapped[2];
         pointTransform.mapPoints(mapped, unitPts, (int) SK_ARRAY_COUNT(unitPts));
+        /*
+        Computing the arc width introduces rounding errors that cause arcs to start
+        outside their marks. A round rect may lose convexity as a result. If the input
+        values are on integers, place the conic on integers as well.
+         */
+#ifndef SK_SUPPORT_LEGACY_SVG_ARC_TO
+        if (expectIntegers) {
+            SkScalar* mappedScalars = &mapped[0].fX;
+            for (unsigned index = 0; index < sizeof(mapped) / sizeof(SkScalar); ++index) {
+                mappedScalars[index] = SkScalarRoundToScalar(mappedScalars[index]);
+            }
+        }
+#endif
         this->conicTo(mapped[0], mapped[1], w);
         startTheta = endTheta;
     }