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: