diff options
-rw-r--r-- | src/pathops/SkPathOpsTSect.h | 16 | ||||
-rw-r--r-- | src/pathops/SkPathOpsTypes.h | 5 | ||||
-rw-r--r-- | tests/PathOpsOpTest.cpp | 45 |
3 files changed, 61 insertions, 5 deletions
diff --git a/src/pathops/SkPathOpsTSect.h b/src/pathops/SkPathOpsTSect.h index 9032af83eb..db2e865a12 100644 --- a/src/pathops/SkPathOpsTSect.h +++ b/src/pathops/SkPathOpsTSect.h @@ -882,6 +882,7 @@ bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect SkDPoint last = fCurve.ptAtT(tStart); SkDPoint oppPt; bool flip = false; + bool contained = false; SkDEBUGCODE(bool down = tStep < 0); const OppCurve& opp = sect2->fCurve; do { @@ -908,6 +909,7 @@ bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect if (sect2->fHead->contains(oppTTest)) { *oppT = oppTTest; oppPt = work.fCoinStart.perpPt(); + contained = true; SkASSERT(down ? result > work.fStartT : result < work.fStartT); result = work.fStartT; continue; @@ -916,6 +918,9 @@ bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect tStep = -tStep; flip = true; } while (true); + if (!contained) { + return false; + } if (last.approximatelyEqual(fCurve[0])) { result = 0; } else if (last.approximatelyEqual(fCurve[TCurve::kPointLast])) { @@ -1923,10 +1928,10 @@ struct SkClosestRecord { fClosest = dist; } - bool matesWith(const SkClosestRecord& mate) const { + bool matesWith(const SkClosestRecord& mate SkDEBUGPARAMS(SkIntersections* i)) const { SkASSERT(fC1Span == mate.fC1Span || fC1Span->endT() <= mate.fC1Span->startT() || mate.fC1Span->endT() <= fC1Span->startT()); - SkASSERT(fC2Span == mate.fC2Span || fC2Span->endT() <= mate.fC2Span->startT() + SkOPOBJASSERT(i, fC2Span == mate.fC2Span || fC2Span->endT() <= mate.fC2Span->startT() || mate.fC2Span->endT() <= fC2Span->startT()); return fC1Span == mate.fC1Span || fC1Span->endT() == mate.fC1Span->startT() || fC1Span->startT() == mate.fC1Span->endT() @@ -1975,7 +1980,8 @@ struct SkClosestSect { fClosest.push_back().reset(); } - bool find(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2) { + bool find(const SkTSpan<TCurve, OppCurve>* span1, const SkTSpan<OppCurve, TCurve>* span2 + SkDEBUGPARAMS(SkIntersections* i)) { SkClosestRecord<TCurve, OppCurve>* record = &fClosest[fUsed]; record->findEnd(span1, span2, 0, 0); record->findEnd(span1, span2, 0, OppCurve::kPointLast); @@ -1986,7 +1992,7 @@ struct SkClosestSect { } for (int index = 0; index < fUsed; ++index) { SkClosestRecord<TCurve, OppCurve>* test = &fClosest[index]; - if (test->matesWith(*record)) { + if (test->matesWith(*record SkDEBUGPARAMS(i))) { if (test->fClosest > record->fClosest) { test->merge(*record); } @@ -2212,7 +2218,7 @@ void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1, SkTSpan<OppCurve, TCurve>* result2 = sect2->fHead; bool found = false; while (result2) { - found |= closest.find(result1, result2); + found |= closest.find(result1, result2 SkDEBUGPARAMS(intersections)); result2 = result2->fNext; } } while ((result1 = result1->fNext)); diff --git a/src/pathops/SkPathOpsTypes.h b/src/pathops/SkPathOpsTypes.h index ad9c931795..3b98c7b3af 100644 --- a/src/pathops/SkPathOpsTypes.h +++ b/src/pathops/SkPathOpsTypes.h @@ -183,9 +183,14 @@ private: #endif }; +#ifdef SK_DEBUG #define SkOPASSERT(cond) SkASSERT(this->globalState()->debugSkipAssert() || cond) #define SkOPOBJASSERT(obj, cond) SkASSERT((obj->debugGlobalState() && \ obj->debugGlobalState()->debugSkipAssert()) || cond) +#else +#define SkOPASSERT(cond) +#define SkOPOBJASSERT(obj, cond) +#endif // Use Almost Equal when comparing coordinates. Use epsilon to compare T values. bool AlmostEqualUlps(float a, float b); diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp index dff26434fd..b217fa3dd9 100644 --- a/tests/PathOpsOpTest.cpp +++ b/tests/PathOpsOpTest.cpp @@ -6533,7 +6533,52 @@ SkPath path2(path); testPathOpFail(reporter, path1, path2, kXOR_SkPathOp, filename); } +static void fuzz763_10(skiatest::Reporter* reporter, const char* filename) { + SkPath path; + path.setFillType((SkPath::FillType) 1); +path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x68556829)); // 0, 4.03114e+24f +path.lineTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0 +path.quadTo(SkBits2Float(0x6a4b7bc0), SkBits2Float(0x00000000), SkBits2Float(0x00000000), SkBits2Float(0x6a4b7bc4)); // 6.14991e+25f, 0, 0, 6.14991e+25f +path.lineTo(SkBits2Float(0x00000000), SkBits2Float(0x68556829)); // 0, 4.03114e+24f +path.close(); + + SkPath path1(path); + path.reset(); + path.setFillType((SkPath::FillType) 0); +path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0 +path.lineTo(SkBits2Float(0x5b2d2968), SkBits2Float(0x2a8c8f55)); // 4.87407e+16f, 2.49685e-13f +path.lineTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 0 +path.close(); +path.moveTo(SkBits2Float(0xc021211f), SkBits2Float(0x6a4b7b03)); // -2.51765f, 6.14982e+25f +path.conicTo(SkBits2Float(0x682d2fed), SkBits2Float(0x755b6829), SkBits2Float(0x5b292d2b), SkBits2Float(0xc92a8c55), SkBits2Float(0x081f2a21)); // 3.27141e+24f, 2.78131e+32f, 4.76189e+16f, -698565, 4.78968e-34f +path.lineTo(SkBits2Float(0xc021211f), SkBits2Float(0x6a4b7b03)); // -2.51765f, 6.14982e+25f +path.close(); +path.moveTo(SkBits2Float(0xc021211f), SkBits2Float(0x6a4b7b03)); // -2.51765f, 6.14982e+25f +path.conicTo(SkBits2Float(0x6a4b7bc0), SkBits2Float(0x2a8ced7a), SkBits2Float(0x21081f21), SkBits2Float(0x3a7bc003), SkBits2Float(0x47ed7a29)); // 6.14991e+25f, 2.50338e-13f, 4.61198e-19f, 0.00096035f, 121588 +path.lineTo(SkBits2Float(0xc021211f), SkBits2Float(0x6a4b7b03)); // -2.51765f, 6.14982e+25f +path.close(); +path.moveTo(SkBits2Float(0xc021211f), SkBits2Float(0x6a4b7b03)); // -2.51765f, 6.14982e+25f +path.quadTo(SkBits2Float(0x6829682d), SkBits2Float(0x292d555b), SkBits2Float(0x2a8c555b), SkBits2Float(0x081f2a29)); // 3.20001e+24f, 3.84878e-14f, 2.49282e-13f, 4.78969e-34f +path.conicTo(SkBits2Float(0x6a497b19), SkBits2Float(0x218ced7a), SkBits2Float(0x0321081f), SkBits2Float(0x6a3a7bc0), SkBits2Float(0x47ed3a7a)); // 6.08939e+25f, 9.54963e-19f, 4.7323e-37f, 5.63611e+25f, 121461 +path.lineTo(SkBits2Float(0xc021211f), SkBits2Float(0x6a4b7b03)); // -2.51765f, 6.14982e+25f +path.close(); +path.moveTo(SkBits2Float(0xc021211f), SkBits2Float(0x6a4b7b03)); // -2.51765f, 6.14982e+25f +path.quadTo(SkBits2Float(0x282a282a), SkBits2Float(0x8a3a21df), SkBits2Float(0x2728282a), SkBits2Float(0x8a3a2129)); // 9.4456e-15f, -8.96194e-33f, 2.33365e-15f, -8.96181e-33f +path.quadTo(SkBits2Float(0x8a284f9a), SkBits2Float(0x3a3ac2b3), SkBits2Float(0x2a292827), SkBits2Float(0x962be61d)); // -8.10388e-33f, 0.000712435f, 1.50241e-13f, -1.38859e-25f +path.lineTo(SkBits2Float(0x272a802a), SkBits2Float(0x2a8c2d29)); // 2.36617e-15f, 2.49003e-13f +path.lineTo(SkBits2Float(0xc021211f), SkBits2Float(0x6a4b7b03)); // -2.51765f, 6.14982e+25f +path.close(); +path.moveTo(SkBits2Float(0x4f9a3a29), SkBits2Float(0x3ab38a28)); // 5.17501e+09f, 0.00136978f +path.quadTo(SkBits2Float(0xc368305b), SkBits2Float(0x5b296855), SkBits2Float(0x2d8c5568), SkBits2Float(0x1f2a2172)); // -232.189f, 4.7684e+16f, 1.59541e-11f, 3.60266e-20f +path.lineTo(SkBits2Float(0x29c00321), SkBits2Float(0x5b4b7b13)); // 8.52706e-14f, 5.72747e+16f + + SkPath path2(path); + testPathOpSkipAssert(reporter, path1, path2, (SkPathOp) 4, filename); +} + + static struct TestDesc failTests[] = { + TEST(fuzz763_10), TEST(kfuzz2), TEST(fuzz763_7), TEST(fuzz763_6), |