diff options
-rw-r--r-- | src/pathops/SkDLineIntersection.cpp | 11 | ||||
-rw-r--r-- | src/pathops/SkIntersections.cpp | 1 | ||||
-rw-r--r-- | src/pathops/SkIntersections.h | 5 | ||||
-rw-r--r-- | src/pathops/SkPathOpsConic.cpp | 8 | ||||
-rw-r--r-- | src/pathops/SkPathOpsCubic.cpp | 13 | ||||
-rw-r--r-- | src/pathops/SkPathOpsQuad.cpp | 8 | ||||
-rw-r--r-- | src/pathops/SkPathOpsTSect.h | 2 | ||||
-rw-r--r-- | tests/PathOpsCubicIntersectionTest.cpp | 5 | ||||
-rw-r--r-- | tests/PathOpsOpTest.cpp | 14 |
9 files changed, 60 insertions, 7 deletions
diff --git a/src/pathops/SkDLineIntersection.cpp b/src/pathops/SkDLineIntersection.cpp index 5fd8e7fdb7..bfbbc7e07e 100644 --- a/src/pathops/SkDLineIntersection.cpp +++ b/src/pathops/SkDLineIntersection.cpp @@ -12,11 +12,16 @@ void SkIntersections::cleanUpParallelLines(bool parallel) { removeOne(1); } if (fUsed == 2 && !parallel) { - bool startMatch = fT[0][0] == 0 || fT[1][0] == 0 || fT[1][0] == 1; - bool endMatch = fT[0][1] == 1 || fT[1][1] == 0 || fT[1][1] == 1; + bool startMatch = fT[0][0] == 0 || zero_or_one(fT[1][0]); + bool endMatch = fT[0][1] == 1 || zero_or_one(fT[1][1]); if ((!startMatch && !endMatch) || approximately_equal(fT[0][0], fT[0][1])) { SkASSERT(startMatch || endMatch); - removeOne(endMatch); + if (startMatch && endMatch && (fT[0][0] != 0 || !zero_or_one(fT[1][0])) + && fT[0][1] == 1 && zero_or_one(fT[1][1])) { + removeOne(0); + } else { + removeOne(endMatch); + } } } if (fUsed == 2) { diff --git a/src/pathops/SkIntersections.cpp b/src/pathops/SkIntersections.cpp index 7caf04bf4d..9683796a5b 100644 --- a/src/pathops/SkIntersections.cpp +++ b/src/pathops/SkIntersections.cpp @@ -87,6 +87,7 @@ int SkIntersections::insert(double one, double two, const SkDPoint& pt) { fT[0][index] = one; fT[1][index] = two; ++fUsed; + SkASSERT(fUsed <= SK_ARRAY_COUNT(fPt)); return index; } diff --git a/src/pathops/SkIntersections.h b/src/pathops/SkIntersections.h index c12db38b6c..ac9276beec 100644 --- a/src/pathops/SkIntersections.h +++ b/src/pathops/SkIntersections.h @@ -188,6 +188,7 @@ public: } void setMax(int max) { + SkASSERT(max <= (int) SK_ARRAY_COUNT(fPt)); fMax = max; } @@ -286,9 +287,9 @@ private: void cleanUpParallelLines(bool parallel); void computePoints(const SkDLine& line, int used); - SkDPoint fPt[10]; // FIXME: since scans store points as SkPoint, this should also + SkDPoint fPt[12]; // FIXME: since scans store points as SkPoint, this should also SkDPoint fPt2[2]; // used by nearly same to store alternate intersection point - double fT[2][10]; + double fT[2][12]; uint16_t fIsCoincident[2]; // bit set for each curve's coincident T bool fNearlySame[2]; // true if end points nearly match unsigned char fUsed; diff --git a/src/pathops/SkPathOpsConic.cpp b/src/pathops/SkPathOpsConic.cpp index 82353d67b5..013136bd82 100644 --- a/src/pathops/SkPathOpsConic.cpp +++ b/src/pathops/SkPathOpsConic.cpp @@ -48,6 +48,14 @@ SkDVector SkDConic::dxdyAtT(double t) const { conic_eval_tan(&fPts[0].fX, fWeight, t), conic_eval_tan(&fPts[0].fY, fWeight, t) }; + if (result.fX == 0 && result.fY == 0) { + if (zero_or_one(t)) { + result = fPts[2] - fPts[0]; + } else { + // incomplete + SkDebugf("!k"); + } + } return result; } diff --git a/src/pathops/SkPathOpsCubic.cpp b/src/pathops/SkPathOpsCubic.cpp index 972c510643..f82bc3530c 100644 --- a/src/pathops/SkPathOpsCubic.cpp +++ b/src/pathops/SkPathOpsCubic.cpp @@ -474,6 +474,19 @@ static double derivative_at_t(const double* src, double t) { // OPTIMIZE? compute t^2, t(1-t), and (1-t)^2 and pass them to another version of derivative at t? SkDVector SkDCubic::dxdyAtT(double t) const { SkDVector result = { derivative_at_t(&fPts[0].fX, t), derivative_at_t(&fPts[0].fY, t) }; + if (result.fX == 0 && result.fY == 0) { + if (t == 0) { + result = fPts[2] - fPts[0]; + } else if (t == 1) { + result = fPts[3] - fPts[1]; + } else { + // incomplete + SkDebugf("!c"); + } + if (result.fX == 0 && result.fY == 0 && zero_or_one(t)) { + result = fPts[3] - fPts[0]; + } + } return result; } diff --git a/src/pathops/SkPathOpsQuad.cpp b/src/pathops/SkPathOpsQuad.cpp index 717d8bc03d..12b9658ce7 100644 --- a/src/pathops/SkPathOpsQuad.cpp +++ b/src/pathops/SkPathOpsQuad.cpp @@ -161,6 +161,14 @@ SkDVector SkDQuad::dxdyAtT(double t) const { double c = t; SkDVector result = { a * fPts[0].fX + b * fPts[1].fX + c * fPts[2].fX, a * fPts[0].fY + b * fPts[1].fY + c * fPts[2].fY }; + if (result.fX == 0 && result.fY == 0) { + if (zero_or_one(t)) { + result = fPts[2] - fPts[0]; + } else { + // incomplete + SkDebugf("!q"); + } + } return result; } diff --git a/src/pathops/SkPathOpsTSect.h b/src/pathops/SkPathOpsTSect.h index 4cf5978d95..50e12791f7 100644 --- a/src/pathops/SkPathOpsTSect.h +++ b/src/pathops/SkPathOpsTSect.h @@ -1907,7 +1907,7 @@ void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1, SkDEBUGCODE(sect1->fOppSect = sect2); SkDEBUGCODE(sect2->fOppSect = sect1); intersections->reset(); - intersections->setMax(TCurve::kMaxIntersections * 3); // give extra for slop + intersections->setMax(TCurve::kMaxIntersections + 3); // give extra for slop SkTSpan<TCurve, OppCurve>* span1 = sect1->fHead; SkTSpan<OppCurve, TCurve>* span2 = sect2->fHead; int oppSect, sect = sect1->intersects(span1, sect2, span2, &oppSect); diff --git a/tests/PathOpsCubicIntersectionTest.cpp b/tests/PathOpsCubicIntersectionTest.cpp index 138e6f484f..75a5cc3ef4 100644 --- a/tests/PathOpsCubicIntersectionTest.cpp +++ b/tests/PathOpsCubicIntersectionTest.cpp @@ -653,6 +653,11 @@ static void cubicIntersectionSelfTest(skiatest::Reporter* reporter) { } static const SkDCubic coinSet[] = { + {{{297.04998779296875, 43.928997039794922}, {297.04998779296875, 43.928997039794922}, + {300.69699096679688, 45.391998291015625}, {306.92498779296875, 43.08599853515625}}}, + {{{297.04998779296875, 43.928997039794922}, {297.04998779296875, 43.928997039794922}, + {300.69699096679688, 45.391998291015625}, {306.92498779296875, 43.08599853515625}}}, + {{{2, 3}, {0, 4}, {3, 2}, {5, 3}}}, {{{2, 3}, {0, 4}, {3, 2}, {5, 3}}}, diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp index 637bd042d2..fbe0116eb5 100644 --- a/tests/PathOpsOpTest.cpp +++ b/tests/PathOpsOpTest.cpp @@ -5153,13 +5153,25 @@ static void cubics45u(skiatest::Reporter* reporter, const char* filename) { testPathOp(reporter, path, pathB, kUnion_SkPathOp, filename); } +static void fuzz38(skiatest::Reporter* reporter, const char* filename) { + SkPath path, pathB; + path.moveTo(100.34f, 303.312f); + path.lineTo(-1e+08, 303.312f); + path.lineTo(102, 310.156f); + path.lineTo(100.34f, 310.156f); + path.lineTo(100.34f, 303.312f); + path.close(); + testPathOpCheck(reporter, path, pathB, kUnion_SkPathOp, filename, FLAGS_runFail); +} + static void (*skipTest)(skiatest::Reporter* , const char* filename) = 0; -static void (*firstTest)(skiatest::Reporter* , const char* filename) = loops63i; +static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0; static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0; #define TEST(name) { name, #name } static struct TestDesc tests[] = { + TEST(fuzz38), TEST(cubics44d), TEST(cubics45u), TEST(loops61i), |