replace arcto quads with a conic

also, remove code used only for
the quad generation

R=reed@google.com
BUG=578885
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1612543003

Review URL: https://codereview.chromium.org/1612543003
diff --git a/samplecode/SampleQuadStroker.cpp b/samplecode/SampleQuadStroker.cpp
index 88f7dfd..eae683f 100644
--- a/samplecode/SampleQuadStroker.cpp
+++ b/samplecode/SampleQuadStroker.cpp
@@ -77,7 +77,10 @@
 }
 
 static void erase(SkSurface* surface) {
-    surface->getCanvas()->clear(SK_ColorTRANSPARENT);
+    SkCanvas* canvas = surface->getCanvas();
+    if (canvas) {
+        canvas->clear(SK_ColorTRANSPARENT);
+    }
 }
 
 struct StrokeTypeButton {
@@ -97,10 +100,11 @@
     };
 
     enum {
-        kCount = 15
+        kCount = 18
     };
     SkPoint fPts[kCount];
     SkRect fWeightControl;
+    SkRect fRadiusControl;
     SkRect fErrorControl;
     SkRect fWidthControl;
     SkRect fBounds;
@@ -111,12 +115,14 @@
     StrokeTypeButton fCubicButton;
     StrokeTypeButton fConicButton;
     StrokeTypeButton fQuadButton;
+    StrokeTypeButton fArcButton;
     StrokeTypeButton fRRectButton;
     CircleTypeButton fCircleButton;
     StrokeTypeButton fTextButton;
     SkString fText;
     SkScalar fTextSize;
     SkScalar fWeight;
+    SkScalar fRadius;
     SkScalar fWidth, fDWidth;
     SkScalar fWidthScale;
     int fW, fH, fZoom;
@@ -147,32 +153,39 @@
         fPts[8].set(150, 200);
         fPts[9].set(250, 150);
 
-        fPts[10].set(200, 200); // rrect
-        fPts[11].set(400, 400);
+        fPts[10].set(250, 200);  // arc
+        fPts[11].set(250, 300);
+        fPts[12].set(150, 350);
 
-        fPts[12].set(250, 250);  // oval
-        fPts[13].set(450, 450);
+        fPts[13].set(200, 200); // rrect
+        fPts[14].set(400, 400);
+
+        fPts[15].set(250, 250);  // oval
+        fPts[16].set(450, 450);
 
         fText = "a";
         fTextSize = 12;
         fWidth = 50;
         fDWidth = 0.25f;
         fWeight = 1;
+        fRadius = 150;
 
         fCubicButton.fLabel = 'C';
         fCubicButton.fEnabled = false;
         fConicButton.fLabel = 'K';
-        fConicButton.fEnabled = true;
+        fConicButton.fEnabled = false;
         fQuadButton.fLabel = 'Q';
         fQuadButton.fEnabled = false;
+        fArcButton.fLabel = 'A';
+        fArcButton.fEnabled = true;
         fRRectButton.fLabel = 'R';
         fRRectButton.fEnabled = false;
         fCircleButton.fLabel = 'O';
-        fCircleButton.fEnabled = false;
-        fCircleButton.fFill = false;
+        fCircleButton.fEnabled = true;
+        fCircleButton.fFill = true;
         fTextButton.fLabel = 'T';
         fTextButton.fEnabled = false;
-        fAnimate = true;
+        fAnimate = false;
         setAsNeeded();
     }
 
@@ -205,6 +218,7 @@
     }
 
     void onSizeChange() override {
+        fRadiusControl.setXYWH(this->width() - 200, 30, 30, 400);
         fWeightControl.setXYWH(this->width() - 150, 30, 30, 400);
         fErrorControl.setXYWH(this->width() - 100, 30, 30, 400);
         fWidthControl.setXYWH(this->width() -  50, 30, 30, 400);
@@ -215,6 +229,8 @@
         buttonOffset += 50;
         fQuadButton.fBounds.setXYWH(this->width() - 50, SkIntToScalar(buttonOffset), 30, 30);
         buttonOffset += 50;
+        fArcButton.fBounds.setXYWH(this->width() - 50, SkIntToScalar(buttonOffset), 30, 30);
+        buttonOffset += 50;
         fRRectButton.fBounds.setXYWH(this->width() - 50, SkIntToScalar(buttonOffset), 30, 30);
         buttonOffset += 50;
         fCircleButton.fBounds.setXYWH(this->width() - 50, SkIntToScalar(buttonOffset), 30, 30);
@@ -519,13 +535,47 @@
     void setAsNeeded() {
         if (fConicButton.fEnabled || fCubicButton.fEnabled || fQuadButton.fEnabled) {
             setForSingles();
-        } else if (fRRectButton.fEnabled || fCircleButton.fEnabled) {
+        } else if (fRRectButton.fEnabled || fCircleButton.fEnabled || fArcButton.fEnabled) {
             setForGeometry();
         } else {
             setForText();
         }
     }
 
+    bool arcCenter(SkPoint* center) {
+        SkPath path;
+        path.moveTo(fPts[10]);
+        path.arcTo(fPts[11], fPts[12], fRadius);
+        SkPath::Iter iter(path, false);
+        SkPoint pts[4];
+        iter.next(pts);
+        if (SkPath::kLine_Verb == iter.next(pts)) {
+            iter.next(pts);
+        }
+        SkVector before = pts[0] - pts[1];
+        SkVector after = pts[1] - pts[2];
+        before.setLength(fRadius);
+        after.setLength(fRadius);
+        SkVector beforeCCW, afterCCW;
+        before.rotateCCW(&beforeCCW);
+        after.rotateCCW(&afterCCW);
+        beforeCCW += pts[0];
+        afterCCW += pts[2];
+        *center = beforeCCW;
+        if (SkScalarNearlyEqual(beforeCCW.fX, afterCCW.fX)
+                && SkScalarNearlyEqual(beforeCCW.fY, afterCCW.fY)) {
+            return true;
+        }
+        SkVector beforeCW, afterCW;
+        before.rotateCW(&beforeCW);
+        after.rotateCW(&afterCW);
+        beforeCW += pts[0];
+        afterCW += pts[2];
+        *center = beforeCW;
+        return SkScalarNearlyEqual(beforeCW.fX, afterCW.fX)
+                && SkScalarNearlyEqual(beforeCCW.fY, afterCW.fY);
+    }
+
     void onDrawContent(SkCanvas* canvas) override {
         SkPath path;
         SkScalar width = fWidth;
@@ -553,10 +603,23 @@
             draw_stroke(canvas, path, width, 950, false);
         }
 
+        if (fArcButton.fEnabled) {
+            path.reset();
+            path.moveTo(fPts[10]);
+            path.arcTo(fPts[11], fPts[12], fRadius);
+            setForGeometry();
+            draw_stroke(canvas, path, width, 950, false);
+            SkPath pathPts;
+            pathPts.moveTo(fPts[10]);
+            pathPts.lineTo(fPts[11]);
+            pathPts.lineTo(fPts[12]);
+            draw_points(canvas, pathPts, SK_ColorDKGRAY, true);
+        }
+
         if (fRRectButton.fEnabled) {
             SkScalar rad = 32;
             SkRect r;
-            r.set(&fPts[10], 2);
+            r.set(&fPts[13], 2);
             path.reset();
             SkRRect rr;
             rr.setRectXY(r, rad, rad);
@@ -579,10 +642,17 @@
         if (fCircleButton.fEnabled) {
             path.reset();
             SkRect r;
-            r.set(&fPts[12], 2);
+            r.set(&fPts[15], 2);
             path.addOval(r);
             setForGeometry();
             if (fCircleButton.fFill) {
+                if (fArcButton.fEnabled) {
+                    SkPoint center;
+                    if (arcCenter(&center)) {
+                        r.set(center.fX - fRadius, center.fY - fRadius, center.fX + fRadius, 
+                                center.fY + fRadius);
+                    }
+                }
                 draw_fill(canvas, r, width);
             } else {
                 draw_stroke(canvas, path, width, 950, false);
@@ -611,6 +681,9 @@
         if (fConicButton.fEnabled) {
             draw_control(canvas, fWeightControl, fWeight, 0, 5, "weight");
         }
+        if (fArcButton.fEnabled) {
+            draw_control(canvas, fRadiusControl, fRadius, 0, 500, "radius");
+        }
 #ifdef SK_DEBUG
         draw_control(canvas, fErrorControl, gDebugStrokerError, kStrokerErrorMin, kStrokerErrorMax,
                 "error");
@@ -620,6 +693,7 @@
         draw_button(canvas, fQuadButton);
         draw_button(canvas, fCubicButton);
         draw_button(canvas, fConicButton);
+        draw_button(canvas, fArcButton);
         draw_button(canvas, fRRectButton);
         draw_button(canvas, fCircleButton);
         draw_button(canvas, fTextButton);
@@ -643,39 +717,46 @@
         if (fWeightControl.contains(rectPt)) {
             return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 1);
         }
+        if (fRadiusControl.contains(rectPt)) {
+            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 2);
+        }
 #ifdef SK_DEBUG
         if (fErrorControl.contains(rectPt)) {
-            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 2);
+            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 3);
         }
 #endif
         if (fWidthControl.contains(rectPt)) {
-            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 3);
+            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 4);
         }
         if (fCubicButton.fBounds.contains(rectPt)) {
             fCubicButton.fEnabled ^= true;
-            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 4);
+            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 5);
         }
         if (fConicButton.fBounds.contains(rectPt)) {
             fConicButton.fEnabled ^= true;
-            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 5);
+            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 6);
         }
         if (fQuadButton.fBounds.contains(rectPt)) {
             fQuadButton.fEnabled ^= true;
-            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 6);
+            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 7);
+        }
+        if (fArcButton.fBounds.contains(rectPt)) {
+            fArcButton.fEnabled ^= true;
+            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 8);
         }
         if (fRRectButton.fBounds.contains(rectPt)) {
             fRRectButton.fEnabled ^= true;
-            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 7);
+            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 9);
         }
         if (fCircleButton.fBounds.contains(rectPt)) {
             bool wasEnabled = fCircleButton.fEnabled;
             fCircleButton.fEnabled = !fCircleButton.fFill;
             fCircleButton.fFill = wasEnabled && !fCircleButton.fFill;
-            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 8);
+            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 10);
         }
         if (fTextButton.fBounds.contains(rectPt)) {
             fTextButton.fEnabled ^= true;
-            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 9);
+            return new MyClick(this, (int) SK_ARRAY_COUNT(fPts) + 11);
         }
         return this->INHERITED::onFindClickHandler(x, y, modi);
     }
@@ -693,15 +774,17 @@
             this->inval(nullptr);
         } else if (index == (int) SK_ARRAY_COUNT(fPts) + 1) {
             fWeight = MapScreenYtoValue(click->fICurr.fY, fWeightControl, 0, 5);
+        } else if (index == (int) SK_ARRAY_COUNT(fPts) + 2) {
+            fRadius = MapScreenYtoValue(click->fICurr.fY, fRadiusControl, 0, 500);
         }
 #ifdef SK_DEBUG
-        else if (index == (int) SK_ARRAY_COUNT(fPts) + 2) {
+        else if (index == (int) SK_ARRAY_COUNT(fPts) + 3) {
             gDebugStrokerError = SkTMax(FLT_EPSILON, MapScreenYtoValue(click->fICurr.fY,
                     fErrorControl, kStrokerErrorMin, kStrokerErrorMax));
             gDebugStrokerErrorSet = true;
         }
 #endif
-        else if (index == (int) SK_ARRAY_COUNT(fPts) + 3) {
+        else if (index == (int) SK_ARRAY_COUNT(fPts) + 4) {
             fWidth = SkTMax(FLT_EPSILON, MapScreenYtoValue(click->fICurr.fY, fWidthControl,
                     kWidthMin, kWidthMax));
             fAnimate = fWidth <= kWidthMin;
diff --git a/src/core/SkGeometry.cpp b/src/core/SkGeometry.cpp
index 2ea3095..04e396c 100644
--- a/src/core/SkGeometry.cpp
+++ b/src/core/SkGeometry.cpp
@@ -951,6 +951,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+#ifdef SK_SUPPORT_LEGACY_ARCTO
 /*  Find t value for quadratic [a, b, c] = d.
     Return 0 if there is no solution within [0, 1)
 */
@@ -1120,7 +1121,7 @@
     matrix.mapPoints(quadPoints, pointCount);
     return pointCount;
 }
-
+#endif
 
 ///////////////////////////////////////////////////////////////////////////////
 //
diff --git a/src/core/SkGeometry.h b/src/core/SkGeometry.h
index 0fd5a61..6a8546a 100644
--- a/src/core/SkGeometry.h
+++ b/src/core/SkGeometry.h
@@ -194,6 +194,7 @@
     kCCW_SkRotationDirection
 };
 
+#ifdef SK_SUPPORT_LEGACY_ARCTO
 /** Maximum number of points needed in the quadPoints[] parameter for
     SkBuildQuadArc()
 */
@@ -207,6 +208,7 @@
 */
 int SkBuildQuadArc(const SkVector& unitStart, const SkVector& unitStop,
                    SkRotationDirection, const SkMatrix*, SkPoint quadPoints[]);
+#endif
 
 struct SkConic {
     SkConic() {}
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index 4c148c5..c77a25b 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -1301,13 +1301,16 @@
         return;
     }
 
-    SkScalar dist = SkScalarMulDiv(radius, SK_Scalar1 - cosh, sinh);
-    if (dist < 0) {
-        dist = -dist;
-    }
+    SkScalar dist = SkScalarAbs(SkScalarMulDiv(radius, SK_Scalar1 - cosh, sinh));
 
     SkScalar xx = x1 - SkScalarMul(dist, before.fX);
     SkScalar yy = y1 - SkScalarMul(dist, before.fY);
+#ifndef SK_SUPPORT_LEGACY_ARCTO
+    after.setLength(dist);
+    this->lineTo(xx, yy);
+    SkScalar weight = SkScalarSqrt(SK_ScalarHalf + cosh * SK_ScalarHalf);
+    this->conicTo(x1, y1, x1 + after.fX, y1 + after.fY, weight);
+#else
     SkRotationDirection arcDir;
 
     // now turn before/after into normals
@@ -1336,6 +1339,7 @@
     for (int i = 1; i < count; i += 2) {
         this->quadTo(pts[i], pts[i+1]);
     }
+#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////