Add conic fill support to the tessellator

This started out as a sandbox to experiment with a Wang's formula
analog for rational quadratics, but it quickly became apparent that
running Wang's formula on the down-projected points was an upper bound
on what the rational version would have been (for both w<1 and w>1).

This CL therefore adds conic support by upgrading the tessellation
shaders to use ratoinal cubics, converting every path verb to a
rational cubic, and then running Wang's formula on the down-projected
points. In the future we can always drop in a better formula if we
work one out.

Bug: skia:10419
Change-Id: I97021ea56afea54fdbe76745bacd3251e350fd97
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/337156
Reviewed-by: Tyler Denniston <tdenniston@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/samplecode/SampleTessellatedWedge.cpp b/samplecode/SampleTessellatedWedge.cpp
index 929489c..6465d75 100644
--- a/samplecode/SampleTessellatedWedge.cpp
+++ b/samplecode/SampleTessellatedWedge.cpp
@@ -20,6 +20,8 @@
 #include "src/gpu/GrRenderTargetContextPriv.h"
 #include "src/gpu/tessellate/GrPathTessellateOp.h"
 
+static float kConicWeight = .5;
+
 // This sample enables wireframe and visualizes the triangulation generated by
 // GrTessellateWedgeShader.
 class TessellatedWedge : public Sample {
@@ -35,9 +37,9 @@
         fPath.transform(SkMatrix::Scale(200, 200));
         fPath.transform(SkMatrix::Translate(300, 300));
 #else
-        fPath.moveTo(100, 200);
-        fPath.cubicTo(100, 100, 400, 100, 400, 200);
-        fPath.lineTo(250, 500);
+        fPath.moveTo(100, 300);
+        fPath.conicTo(300, 100, 500, 300, kConicWeight);
+        fPath.cubicTo(433, 366, 366, 433, 300, 500);
 #endif
     }
 
@@ -107,6 +109,14 @@
     }
 
     fLastViewMatrix = canvas->getTotalMatrix();
+
+
+    SkString caption;
+    caption.printf("w=%f  (=/- and +/_ to change)", kConicWeight);
+    SkFont font(nullptr, 20);
+    SkPaint captionPaint;
+    captionPaint.setColor(SK_ColorWHITE);
+    canvas->drawString(caption, 10, 30, font, captionPaint);
 }
 
 class TessellatedWedge::Click : public Sample::Click {
@@ -145,6 +155,32 @@
     return true;
 }
 
+static SkPath update_weight(const SkPath& path) {
+    SkPath path_;
+    for (auto [verb, pts, _] : SkPathPriv::Iterate(path)) {
+        switch (verb) {
+            case SkPathVerb::kMove:
+                path_.moveTo(pts[0]);
+                break;
+            case SkPathVerb::kLine:
+                path_.lineTo(pts[1]);
+                break;
+            case SkPathVerb::kQuad:
+                path_.quadTo(pts[1], pts[2]);
+                break;
+            case SkPathVerb::kCubic:
+                path_.cubicTo(pts[1], pts[2], pts[3]);
+                break;
+            case SkPathVerb::kConic:
+                path_.conicTo(pts[1], pts[2], (kConicWeight != 1) ? kConicWeight : .99f);
+                break;
+            default:
+                SkUNREACHABLE;
+        }
+    }
+    return path_;
+}
+
 bool TessellatedWedge::onChar(SkUnichar unichar) {
     switch (unichar) {
         case 'w':
@@ -155,6 +191,22 @@
             fPath.dump();
             return true;
         }
+        case '+':
+            kConicWeight *= 2;
+            fPath = update_weight(fPath);
+            return true;
+        case '=':
+            kConicWeight *= 5/4.f;
+            fPath = update_weight(fPath);
+            return true;
+        case '_':
+            kConicWeight *= .5f;
+            fPath = update_weight(fPath);
+            return true;
+        case '-':
+            kConicWeight *= 4/5.f;
+            fPath = update_weight(fPath);
+            return true;
     }
     return false;
 }