diff options
-rwxr-xr-x | src/pathops/SkOpCoincidence.cpp | 11 | ||||
-rw-r--r-- | src/pathops/SkOpCoincidence.h | 2 | ||||
-rw-r--r-- | src/pathops/SkPathOpsCommon.cpp | 4 | ||||
-rw-r--r-- | tests/PathOpsOpTest.cpp | 24 |
4 files changed, 37 insertions, 4 deletions
diff --git a/src/pathops/SkOpCoincidence.cpp b/src/pathops/SkOpCoincidence.cpp index c0147bcfd9..130d1daff7 100755 --- a/src/pathops/SkOpCoincidence.cpp +++ b/src/pathops/SkOpCoincidence.cpp @@ -634,16 +634,22 @@ void SkOpCoincidence::fixUp(SkOpPtT* deleted, SkOpPtT* kept) { } /* this sets up the coincidence links in the segments when the coincidence crosses multiple spans */ -void SkOpCoincidence::mark() { +bool SkOpCoincidence::mark() { SkCoincidentSpans* coin = fHead; if (!coin) { - return; + return true; } do { SkOpSpanBase* end = coin->fCoinPtTEnd->span(); + if (end->deleted()) { + return false; + } SkOpSpanBase* oldEnd = end; SkOpSpan* start = coin->fCoinPtTStart->span()->starter(&end); SkOpSpanBase* oEnd = coin->fOppPtTEnd->span(); + if (oEnd->deleted()) { + return false; + } SkOpSpanBase* oOldEnd = oEnd; SkOpSpanBase* oStart = coin->fOppPtTStart->span()->starter(&oEnd); bool flipped = (end == oldEnd) != (oEnd == oOldEnd); @@ -668,6 +674,7 @@ void SkOpCoincidence::mark() { } } while (true); } while ((coin = coin->fNext)); + return true; } bool SkOpCoincidence::overlap(const SkOpPtT* coin1s, const SkOpPtT* coin1e, diff --git a/src/pathops/SkOpCoincidence.h b/src/pathops/SkOpCoincidence.h index 96bd21ac48..344866ff36 100644 --- a/src/pathops/SkOpCoincidence.h +++ b/src/pathops/SkOpCoincidence.h @@ -92,7 +92,7 @@ public: return !fHead; } - void mark(); + bool mark(); private: bool addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over1s, SkOpPtT* over1e, diff --git a/src/pathops/SkPathOpsCommon.cpp b/src/pathops/SkPathOpsCommon.cpp index 829f8a50d5..86a8cb0bef 100644 --- a/src/pathops/SkPathOpsCommon.cpp +++ b/src/pathops/SkPathOpsCommon.cpp @@ -494,7 +494,9 @@ bool HandleCoincidence(SkOpContourHead* contourList, SkOpCoincidence* coincidenc } DEBUG_COINCIDENCE_HEALTH(contourList, "expand2"); // the expanded ranges may not align -- add the missing spans - coincidence->mark(); // mark spans of coincident segments as coincident + if (!coincidence->mark()) { // mark spans of coincident segments as coincident + return false; + } DEBUG_COINCIDENCE_HEALTH(contourList, "mark1"); // look for coincidence missed earlier if (missingCoincidence(contourList, coincidence, allocator)) { diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp index 1443198bc8..2af941498d 100644 --- a/tests/PathOpsOpTest.cpp +++ b/tests/PathOpsOpTest.cpp @@ -5792,7 +5792,31 @@ path.lineTo(SkBits2Float(0x40f8fbe0), SkBits2Float(0xcf223cc0)); // 7.78075f, - testPathFailOp(reporter, path1, path2, (SkPathOp) 2, filename); } +static void bug597926_0(skiatest::Reporter* reporter, const char* filename) { +SkPath path; +path.setFillType((SkPath::FillType) 0); +path.moveTo(SkBits2Float(0x43b38000), SkBits2Float(0x433e0000)); // 359, 190 +path.lineTo(SkBits2Float(0x40c00000), SkBits2Float(0x449ce000)); // 6, 1255 +path.cubicTo(SkBits2Float(0x438c0000), SkBits2Float(0x4497a000), SkBits2Float(0x43e40000), SkBits2Float(0x44750000), SkBits2Float(0x41000000), SkBits2Float(0x44aa2000)); // 280, 1213, 456, 980, 8, 1361 +path.moveTo(SkBits2Float(0x43290000), SkBits2Float(0x4431c000)); // 169, 711 +path.lineTo(SkBits2Float(0xd987d6ba), SkBits2Float(0xd93d0ad4)); // -4.7794e+15f, -3.32567e+15f +path.conicTo(SkBits2Float(0x43cc8000), SkBits2Float(0x445b8000), SkBits2Float(0xd888b096), SkBits2Float(0xd9a1ebfa), SkBits2Float(0x3ebcb199)); // 409, 878, -1.20234e+15f, -5.69712e+15f, 0.368542f +path.cubicTo(SkBits2Float(0x43c00000), SkBits2Float(0x443a8000), SkBits2Float(0x42380000), SkBits2Float(0x4421c000), SkBits2Float(0x42500000), SkBits2Float(0x448ca000)); // 384, 746, 46, 647, 52, 1125 +path.quadTo(SkBits2Float(0x43948000), SkBits2Float(0x42ac0000), SkBits2Float(0x43880000), SkBits2Float(0x4487e000)); // 297, 86, 272, 1087 +SkPath path1(path); +path.reset(); +path.setFillType((SkPath::FillType) 0); +path.moveTo(SkBits2Float(0xc51d735c), SkBits2Float(0xc49db029)); // -2519.21f, -1261.51f +path.cubicTo(SkBits2Float(0xc51d1dbd), SkBits2Float(0xc49d7a3f), SkBits2Float(0xc51c524a), SkBits2Float(0xc49d1610), SkBits2Float(0xc51d1a96), SkBits2Float(0xc49d86a6)); // -2513.86f, -1259.82f, -2501.14f, -1256.69f, -2513.66f, -1260.21f +path.cubicTo(SkBits2Float(0xc51cd471), SkBits2Float(0xc49d54d0), SkBits2Float(0xc51c2e51), SkBits2Float(0xc49d0081), SkBits2Float(0xc51d197b), SkBits2Float(0xc49d7927)); // -2509.28f, -1258.65f, -2498.89f, -1256.02f, -2513.59f, -1259.79f +path.quadTo(SkBits2Float(0xc51bf7eb), SkBits2Float(0xc49cf010), SkBits2Float(0xc51ba866), SkBits2Float(0xc49cb9e6)); // -2495.49f, -1255.5f, -2490.52f, -1253.81f +path.cubicTo(SkBits2Float(0xc51bac0d), SkBits2Float(0xc49cc50e), SkBits2Float(0xc51c29eb), SkBits2Float(0xc49cfb01), SkBits2Float(0xc51c5bca), SkBits2Float(0xc49d1fa6)); // -2490.75f, -1254.16f, -2498.62f, -1255.84f, -2501.74f, -1256.99f +SkPath path2(path); +testPathFailOp(reporter, path1, path2, (SkPathOp) 1, filename); +} + static struct TestDesc failTests[] = { + TEST(bug597926_0), TEST(fuzz535151), TEST(fuzz753_91), TEST(fuzz714), |