int SkConic::chopIntoQuadsPOW2(SkPoint pts[], int pow2) const {
SkASSERT(pow2 >= 0);
+ const int quadCount = 1 << pow2;
+ const int ptCount = 2 * quadCount + 1;
*pts = fPts[0];
SkDEBUGCODE(SkPoint* endPts =) subdivide(*this, pts + 1, pow2);
- SkASSERT(endPts - pts == (2 * (1 << pow2) + 1));
+ SkASSERT(endPts - pts == ptCount);
+ if (!SkPointsAreFinite(pts, ptCount)) {
+ // if we generated a non-finite, pin ourselves to the middle of the hull,
+ // as our first and last are already on the first/last pts of the hull.
+ for (int i = 1; i < ptCount - 1; ++i) {
+ pts[i] = fPts[1];
+ }
+ }
return 1 << pow2;
}
}
}
+static void test_this_conic_to_quad(skiatest::Reporter* r, const SkPoint pts[3], SkScalar w) {
+ SkAutoConicToQuads quadder;
+ const SkPoint* qpts = quadder.computeQuads(pts, w, 0.25);
+ const int qcount = quadder.countQuads();
+ const int pcount = qcount * 2 + 1;
+
+ REPORTER_ASSERT(r, SkPointsAreFinite(qpts, pcount));
+}
+
+/**
+ * We need to ensure that when a conic is approximated by quads, that we always return finite
+ * values in the quads.
+ *
+ * Inspired by crbug_627414
+ */
+static void test_conic_to_quads(skiatest::Reporter* reporter) {
+ const SkPoint triples[] = {
+ { 0, 0 }, { 1, 0 }, { 1, 1 },
+ { 3.58732e-43f, 2.72084f }, { 3.00392f, 3.00392f },
+ { 0, 0 }, { 100000, 0 }, { 100000, 100000 },
+ { 0, 0 }, { 1e30f, 0 }, { 1e30f, 1e30f },
+ };
+ const int N = sizeof(triples) / sizeof(SkPoint);
+
+ for (int i = 0; i < N; i += 3) {
+ const SkPoint* pts = &triples[i];
+
+ SkRect bounds;
+ bounds.set(pts, 3);
+
+ SkScalar w = 1e30f;
+ do {
+ w *= 2;
+ test_this_conic_to_quad(reporter, pts, w);
+ } while (SkScalarIsFinite(w));
+ test_this_conic_to_quad(reporter, pts, SK_ScalarNaN);
+ }
+}
+
static void test_cubic_tangents(skiatest::Reporter* reporter) {
SkPoint pts[] = {
{ 10, 20}, {10, 20}, {20, 30}, {30, 40},
test_cubic_tangents(reporter);
test_quad_tangents(reporter);
test_conic_tangents(reporter);
+ test_conic_to_quads(reporter);
}
#endif
}
+#include "SkSurface.h"
+static void test_fuzz_crbug_627414(skiatest::Reporter* reporter) {
+ SkPath path;
+ path.moveTo(0, 0);
+ path.conicTo(3.58732e-43f, 2.72084f, 3.00392f, 3.00392f, 8.46e+37f);
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+
+ auto surf = SkSurface::MakeRasterN32Premul(100, 100);
+ surf->getCanvas()->drawPath(path, paint);
+}
+
// Inspired by http://ie.microsoft.com/testdrive/Performance/Chalkboard/
// which triggered an assert, from a tricky cubic. This test replicates that
// example, so we can ensure that we handle it (in SkEdge.cpp), and don't
DEF_TEST(Paths, reporter) {
test_crbug_629455(reporter);
+ test_fuzz_crbug_627414(reporter);
test_path_crbug364224();
SkTSize<SkScalar>::Make(3,4);