Add new tests to trickycubicstrokes

Adds cusps and flat beziers with 180 degree turns that confuse the
new tessellator.

Bug: skia:10419
Change-Id: I2529780da596fe365c1d2825e29145beedf5cb01
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/312118
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/gm/trickycubicstrokes.cpp b/gm/trickycubicstrokes.cpp
index a79de16..faf5c09 100644
--- a/gm/trickycubicstrokes.cpp
+++ b/gm/trickycubicstrokes.cpp
@@ -18,18 +18,39 @@
 #include "include/core/SkTypes.h"
 #include "src/core/SkGeometry.h"
 
-static constexpr float kStrokeWidth = 40;
+static constexpr float kStrokeWidth = 30;
 static constexpr int kCellSize = 200;
+static constexpr int kNumCols = 4;
+static constexpr int kNumRows = 4;
 
-static const SkPoint kCubics[][4] = {
-    {{122, 737}, {348, 553}, {403, 761}, {400, 760}},
-    {{244, 520}, {244, 518}, {1141, 634}, {394, 688}},
-    {{550, 194}, {138, 130}, {1035, 246}, {288, 300}},
-    {{226, 733}, {556, 779}, {-43, 471}, {348, 683}},
-    {{268, 204}, {492, 304}, {352, 23}, {433, 412}},
-    {{172, 480}, {396, 580}, {256, 299}, {338, 677}},
-    {{731, 340}, {318, 252}, {1026, -64}, {367, 265}},
-    {{475, 708}, {62, 620}, {770, 304}, {220, 659}},
+enum class CellFillMode {
+    kStretch,
+    kCenter
+};
+
+struct TrickyCubic {
+    SkPoint fPoints[4];
+    CellFillMode fFillMode;
+    float fScale = 1;
+};
+
+static const TrickyCubic kTrickyCubics[] = {
+    {{{122, 737}, {348, 553}, {403, 761}, {400, 760}}, CellFillMode::kStretch},
+    {{{244, 520}, {244, 518}, {1141, 634}, {394, 688}}, CellFillMode::kStretch},
+    {{{550, 194}, {138, 130}, {1035, 246}, {288, 300}}, CellFillMode::kStretch},
+    {{{226, 733}, {556, 779}, {-43, 471}, {348, 683}}, CellFillMode::kStretch},
+    {{{268, 204}, {492, 304}, {352, 23}, {433, 412}}, CellFillMode::kStretch},
+    {{{172, 480}, {396, 580}, {256, 299}, {338, 677}}, CellFillMode::kStretch},
+    {{{731, 340}, {318, 252}, {1026, -64}, {367, 265}}, CellFillMode::kStretch},
+    {{{475, 708}, {62, 620}, {770, 304}, {220, 659}}, CellFillMode::kStretch},
+    {{{0, 0}, {128, 128}, {128, 0}, {0, 128}}, CellFillMode::kCenter},  // Perfect cusp
+    {{{0,.01f}, {128,127.999f}, {128,.01f}, {0,127.99f}}, CellFillMode::kCenter},  // Near-cusp
+    {{{0,-.01f}, {128,128.001f}, {128,-.01f}, {0,128.001f}}, CellFillMode::kCenter},  // Near-cusp
+    {{{0,0}, {0,-10}, {0,-10}, {0,10}}, CellFillMode::kCenter, 1.098283f},  // Flat line with 180
+    {{{10,0}, {0,0}, {20,0}, {10,0}}, CellFillMode::kStretch},  // Flat line with 2 180s
+    {{{39,-39}, {40,-40}, {40,-40}, {0,0}}, CellFillMode::kStretch},  // Flat diagonal with 180
+    {{{40, 40}, {0, 0}, {200, 200}, {0, 0}}, CellFillMode::kStretch},  // Diag with an internal 180
+    {{{0,0}, {1e-2f,0}, {-1e-2f,0}, {0,0}}, CellFillMode::kCenter},  // Circle
 };
 
 static SkRect calc_tight_cubic_bounds(const SkPoint P[4], int depth=5) {
@@ -49,6 +70,11 @@
     return bounds;
 }
 
+enum class FillMode {
+    kCenter,
+    kScale
+};
+
 // This is a compilation of cubics that have given strokers grief. Feel free to add more.
 class TrickyCubicStrokesGM : public skiagm::GM {
 public:
@@ -61,7 +87,7 @@
     }
 
     SkISize onISize() override {
-        return SkISize::Make(3*kCellSize, 3*kCellSize);
+        return SkISize::Make(kNumCols * kCellSize, kNumRows * kCellSize);
     }
 
     void onOnceBeforeDraw() override {
@@ -74,27 +100,39 @@
     void onDraw(SkCanvas* canvas) override {
         canvas->clear(SK_ColorBLACK);
 
-        for (size_t i = 0; i < SK_ARRAY_COUNT(kCubics); ++i) {
-            this->drawStroke(canvas, kCubics[i],
-                             SkRect::MakeXYWH((i%3) * kCellSize, (i/3) * kCellSize, kCellSize,
-                                              kCellSize));
+        for (size_t i = 0; i < SK_ARRAY_COUNT(kTrickyCubics); ++i) {
+            const auto& trickyCubic = kTrickyCubics[i];
+            SkPoint p[7];
+            memcpy(p, trickyCubic.fPoints, sizeof(SkPoint) * 4);
+            for (int j = 0; j < 4; ++j) {
+                p[j] *= trickyCubic.fScale;
+            }
+            this->drawStroke(canvas, p, i, trickyCubic.fFillMode);
         }
     }
 
-    void drawStroke(SkCanvas* canvas, const SkPoint P[4], const SkRect& location) {
-        SkRect strokeBounds = calc_tight_cubic_bounds(P);
+    void drawStroke(SkCanvas* canvas, const SkPoint p[4], int cellID, CellFillMode fillMode) {
+        auto cellRect = SkRect::MakeXYWH((cellID % kNumCols) * kCellSize,
+                                         (cellID / kNumCols) * kCellSize,
+                                         kCellSize, kCellSize);
+
+        SkRect strokeBounds = calc_tight_cubic_bounds(p);
         strokeBounds.outset(kStrokeWidth, kStrokeWidth);
 
         SkMatrix matrix;
-        matrix.setRectToRect(strokeBounds, location, SkMatrix::kCenter_ScaleToFit);
-
-        SkPath path;
-        path.moveTo(P[0]);
-        path.cubicTo(P[1], P[2], P[3]);
+        if (fillMode == CellFillMode::kStretch) {
+            matrix.setRectToRect(strokeBounds, cellRect, SkMatrix::kCenter_ScaleToFit);
+        } else {
+            matrix.setTranslate(cellRect.x() + kStrokeWidth +
+                                (cellRect.width() - strokeBounds.width()) / 2,
+                                cellRect.y() + kStrokeWidth +
+                                (cellRect.height() - strokeBounds.height()) / 2);
+        }
 
         SkAutoCanvasRestore acr(canvas, true);
         canvas->concat(matrix);
-        canvas->drawPath(path, fStrokePaint);
+        fStrokePaint.setStrokeWidth(kStrokeWidth / matrix.getMaxScale());
+        canvas->drawPath(SkPath().moveTo(p[0]).cubicTo(p[1], p[2], p[3]), fStrokePaint);
     }
 
 private: