diff options
-rw-r--r-- | src/pathops/SkAddIntersections.cpp | 2 | ||||
-rw-r--r-- | src/pathops/SkDConicLineIntersection.cpp | 11 | ||||
-rw-r--r-- | src/pathops/SkIntersections.h | 8 | ||||
-rw-r--r-- | src/pathops/SkOpBuilder.cpp | 19 | ||||
-rwxr-xr-x | src/pathops/SkOpCoincidence.cpp | 3 | ||||
-rw-r--r-- | src/pathops/SkPathOpsCommon.cpp | 3 | ||||
-rw-r--r-- | src/pathops/SkPathOpsCommon.h | 5 | ||||
-rw-r--r-- | src/pathops/SkPathOpsOp.cpp | 7 | ||||
-rw-r--r-- | src/pathops/SkPathOpsSimplify.cpp | 3 | ||||
-rw-r--r-- | src/pathops/SkPathOpsTightBounds.cpp | 3 | ||||
-rw-r--r-- | src/pathops/SkPathOpsTypes.cpp | 4 | ||||
-rw-r--r-- | src/pathops/SkPathOpsTypes.h | 3 | ||||
-rwxr-xr-x | tests/PathOpsAngleIdeas.cpp | 2 | ||||
-rw-r--r-- | tests/PathOpsAngleTest.cpp | 4 | ||||
-rw-r--r-- | tests/PathOpsBuilderTest.cpp | 22 | ||||
-rw-r--r-- | tests/PathOpsExtendedTest.cpp | 19 | ||||
-rw-r--r-- | tests/PathOpsExtendedTest.h | 2 | ||||
-rw-r--r-- | tests/PathOpsOpTest.cpp | 50 |
18 files changed, 141 insertions, 29 deletions
diff --git a/src/pathops/SkAddIntersections.cpp b/src/pathops/SkAddIntersections.cpp index 43d29d93e0..07666e796d 100644 --- a/src/pathops/SkAddIntersections.cpp +++ b/src/pathops/SkAddIntersections.cpp @@ -280,7 +280,7 @@ bool AddIntersectTs(SkOpContour* test, SkOpContour* next, SkOpCoincidence* coinc continue; } int pts = 0; - SkIntersections ts; + SkIntersections ts { SkDEBUGCODE(test->globalState()) }; bool swap = false; SkDQuad quad1, quad2; SkDConic conic1, conic2; diff --git a/src/pathops/SkDConicLineIntersection.cpp b/src/pathops/SkDConicLineIntersection.cpp index e6d775f76e..2d906072fa 100644 --- a/src/pathops/SkDConicLineIntersection.cpp +++ b/src/pathops/SkDConicLineIntersection.cpp @@ -103,9 +103,14 @@ public: for (int index = 0; index < roots; ++index) { double conicT = rootVals[index]; double lineT = this->findLineT(conicT); - SkDEBUGCODE(SkDPoint conicPt = fConic.ptAtT(conicT)); - SkDEBUGCODE(SkDPoint linePt = fLine->ptAtT(lineT)); - SkASSERT(conicPt.approximatelyEqual(linePt)); +#ifdef SK_DEBUG + if (!fIntersections->debugGlobalState() + || !fIntersections->debugGlobalState()->debugSkipAssert()) { + SkDEBUGCODE(SkDPoint conicPt = fConic.ptAtT(conicT)); + SkDEBUGCODE(SkDPoint linePt = fLine->ptAtT(lineT)); + SkASSERT(conicPt.approximatelyEqual(linePt)); + } +#endif SkDPoint pt; if (this->pinTs(&conicT, &lineT, &pt, kPointUninitialized) && this->uniqueAnswer(conicT, pt)) { diff --git a/src/pathops/SkIntersections.h b/src/pathops/SkIntersections.h index b733ed0ea7..474142b269 100644 --- a/src/pathops/SkIntersections.h +++ b/src/pathops/SkIntersections.h @@ -15,9 +15,10 @@ class SkIntersections { public: - SkIntersections() + SkIntersections(SkDEBUGCODE(SkOpGlobalState* globalState = nullptr)) : fSwap(0) #ifdef SK_DEBUG + SkDEBUGPARAMS(fDebugGlobalState(globalState)) , fDepth(0) #endif { @@ -102,6 +103,10 @@ public: return intersect(cubic, line); } +#ifdef SK_DEBUG + SkOpGlobalState* debugGlobalState() { return fDebugGlobalState; } +#endif + bool hasT(double t) const { SkASSERT(t == 0 || t == 1); return fUsed > 0 && (t == 0 ? fT[0][0] == 0 : fT[0][fUsed - 1] == 1); @@ -309,6 +314,7 @@ private: bool fAllowNear; bool fSwap; #ifdef SK_DEBUG + SkOpGlobalState* fDebugGlobalState; int fDepth; #endif #if DEBUG_T_SECT_LOOP_COUNT diff --git a/src/pathops/SkOpBuilder.cpp b/src/pathops/SkOpBuilder.cpp index 4f53dee056..67aa92fe26 100644 --- a/src/pathops/SkOpBuilder.cpp +++ b/src/pathops/SkOpBuilder.cpp @@ -25,7 +25,7 @@ static bool one_contour(const SkPath& path) { return true; } -void FixWinding(SkPath* path) { +bool FixWinding(SkPath* path) { SkPath::FillType fillType = path->getFillType(); if (fillType == SkPath::kInverseEvenOdd_FillType) { fillType = SkPath::kInverseWinding_FillType; @@ -40,14 +40,17 @@ void FixWinding(SkPath* path) { *path = temp; } path->setFillType(fillType); - return; + return true; } SkChunkAlloc allocator(4096); SkOpContourHead contourHead; - SkOpGlobalState globalState(nullptr, &contourHead SkDEBUGPARAMS(nullptr)); + SkOpGlobalState globalState(nullptr, &contourHead SkDEBUGPARAMS(false) + SkDEBUGPARAMS(nullptr)); SkOpEdgeBuilder builder(*path, &contourHead, &allocator, &globalState); builder.finish(&allocator); - SkASSERT(contourHead.next()); + if (!contourHead.next()) { + return false; + } contourHead.resetReverse(); bool writePath = false; SkOpSpan* topSpan; @@ -69,7 +72,7 @@ void FixWinding(SkPath* path) { } if (!writePath) { path->setFillType(fillType); - return; + return true; } SkPath empty; SkPathWriter woundPath(empty); @@ -83,6 +86,7 @@ void FixWinding(SkPath* path) { } while ((test = test->next())); *path = *woundPath.nativePath(); path->setFillType(fillType); + return true; } void SkOpBuilder::add(const SkPath& path, SkPathOp op) { @@ -160,7 +164,10 @@ bool SkOpBuilder::resolve(SkPath* result) { } if (!fPathRefs[index].isEmpty()) { // convert the even odd result back to winding form before accumulating it - FixWinding(&fPathRefs[index]); + if (!FixWinding(&fPathRefs[index])) { + *result = original; + return false; + } sum.addPath(fPathRefs[index]); } } diff --git a/src/pathops/SkOpCoincidence.cpp b/src/pathops/SkOpCoincidence.cpp index 130d1daff7..42ee5c6091 100755 --- a/src/pathops/SkOpCoincidence.cpp +++ b/src/pathops/SkOpCoincidence.cpp @@ -90,6 +90,9 @@ bool SkOpCoincidence::addExpanded(SkChunkAlloc* allocator } SkOpSpanBase* test = start->upCast()->next(); SkOpSpanBase* oTest = coin->fFlipped ? oStart->prev() : oStart->upCast()->next(); + if (!oTest) { + return false; + } while (test != end || oTest != oEnd) { if (!test->ptT()->contains(oTest->ptT())) { // use t ranges to guess which one is missing diff --git a/src/pathops/SkPathOpsCommon.cpp b/src/pathops/SkPathOpsCommon.cpp index c9ef7a4196..340b306d60 100644 --- a/src/pathops/SkPathOpsCommon.cpp +++ b/src/pathops/SkPathOpsCommon.cpp @@ -198,7 +198,8 @@ public: void Assemble(const SkPathWriter& path, SkPathWriter* simple) { SkChunkAlloc allocator(4096); // FIXME: constant-ize, tune SkOpContourHead contour; - SkOpGlobalState globalState(nullptr, &contour SkDEBUGPARAMS(nullptr)); + SkOpGlobalState globalState(nullptr, &contour SkDEBUGPARAMS(false) + SkDEBUGPARAMS(nullptr)); #if DEBUG_SHOW_TEST_NAME SkDebugf("</div>\n"); #endif diff --git a/src/pathops/SkPathOpsCommon.h b/src/pathops/SkPathOpsCommon.h index 73bc0f42cc..856a984ce5 100644 --- a/src/pathops/SkPathOpsCommon.h +++ b/src/pathops/SkPathOpsCommon.h @@ -22,11 +22,12 @@ SkOpSegment* FindChase(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** startPtr, SkOpSpan* FindSortableTop(SkOpContourHead* ); SkOpSegment* FindUndone(SkOpContourHead* , SkOpSpanBase** startPtr, SkOpSpanBase** endPtr); -void FixWinding(SkPath* path); +bool FixWinding(SkPath* path); bool SortContourList(SkOpContourHead** , bool evenOdd, bool oppEvenOdd); bool HandleCoincidence(SkOpContourHead* , SkOpCoincidence* , SkChunkAlloc* ); bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result, - bool expectSuccess SkDEBUGPARAMS(const char* testName)); + bool expectSuccess SkDEBUGPARAMS(bool skipAssert) + SkDEBUGPARAMS(const char* testName)); #if DEBUG_ACTIVE_SPANS void DebugShowActiveSpans(SkOpContourHead* ); #endif diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp index 257cb8ee69..b71ca9e481 100644 --- a/src/pathops/SkPathOpsOp.cpp +++ b/src/pathops/SkPathOpsOp.cpp @@ -246,12 +246,13 @@ extern void (*gVerboseFinalize)(); #endif bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result, - bool expectSuccess SkDEBUGPARAMS(const char* testName)) { + bool expectSuccess SkDEBUGPARAMS(bool skipAssert) SkDEBUGPARAMS(const char* testName)) { SkChunkAlloc allocator(4096); // FIXME: add a constant expression here, tune SkOpContour contour; SkOpContourHead* contourList = static_cast<SkOpContourHead*>(&contour); SkOpCoincidence coincidence; - SkOpGlobalState globalState(&coincidence, contourList SkDEBUGPARAMS(testName)); + SkOpGlobalState globalState(&coincidence, contourList + SkDEBUGPARAMS(skipAssert) SkDEBUGPARAMS(testName)); #if DEBUGGING_PATHOPS_FROM_HOST dump_op(one, two, op); #endif @@ -454,6 +455,6 @@ bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) { } return true; #else - return OpDebug(one, two, op, result, true SkDEBUGPARAMS(nullptr)); + return OpDebug(one, two, op, result, true SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr)); #endif } diff --git a/src/pathops/SkPathOpsSimplify.cpp b/src/pathops/SkPathOpsSimplify.cpp index 97f0350db2..fa1003054e 100644 --- a/src/pathops/SkPathOpsSimplify.cpp +++ b/src/pathops/SkPathOpsSimplify.cpp @@ -180,7 +180,8 @@ bool Simplify(const SkPath& path, SkPath* result) { SkOpCoincidence coincidence; SkOpContour contour; SkOpContourHead* contourList = static_cast<SkOpContourHead*>(&contour); - SkOpGlobalState globalState(&coincidence, contourList SkDEBUGPARAMS(nullptr)); + SkOpGlobalState globalState(&coincidence, contourList SkDEBUGPARAMS(false) + SkDEBUGPARAMS(nullptr)); #if DEBUG_SORT SkPathOpsDebug::gSortCount = SkPathOpsDebug::gSortCountDefault; #endif diff --git a/src/pathops/SkPathOpsTightBounds.cpp b/src/pathops/SkPathOpsTightBounds.cpp index ac5d6aae0b..19593c228b 100644 --- a/src/pathops/SkPathOpsTightBounds.cpp +++ b/src/pathops/SkPathOpsTightBounds.cpp @@ -11,7 +11,8 @@ bool TightBounds(const SkPath& path, SkRect* result) { SkChunkAlloc allocator(4096); // FIXME: constant-ize, tune SkOpContour contour; SkOpContourHead* contourList = static_cast<SkOpContourHead*>(&contour); - SkOpGlobalState globalState(nullptr, contourList SkDEBUGPARAMS(nullptr)); + SkOpGlobalState globalState(nullptr, contourList SkDEBUGPARAMS(false) + SkDEBUGPARAMS(nullptr)); // turn path into list of segments SkOpEdgeBuilder builder(path, &contour, &allocator, &globalState); if (!builder.finish(&allocator)) { diff --git a/src/pathops/SkPathOpsTypes.cpp b/src/pathops/SkPathOpsTypes.cpp index 1ed484afee..bad1bc7a8b 100644 --- a/src/pathops/SkPathOpsTypes.cpp +++ b/src/pathops/SkPathOpsTypes.cpp @@ -213,6 +213,7 @@ double SkDCubeRoot(double x) { } SkOpGlobalState::SkOpGlobalState(SkOpCoincidence* coincidence, SkOpContourHead* head + SkDEBUGPARAMS(bool debugSkipAssert) SkDEBUGPARAMS(const char* testName)) : fCoincidence(coincidence) , fContourHead(head) @@ -226,7 +227,8 @@ SkOpGlobalState::SkOpGlobalState(SkOpCoincidence* coincidence, SkOpContourHead* SkDEBUGPARAMS(fContourID(0)) SkDEBUGPARAMS(fPtTID(0)) SkDEBUGPARAMS(fSegmentID(0)) - SkDEBUGPARAMS(fSpanID(0)) { + SkDEBUGPARAMS(fSpanID(0)) + SkDEBUGPARAMS(fDebugSkipAssert(debugSkipAssert)) { if (coincidence) { coincidence->debugSetGlobalState(this); } diff --git a/src/pathops/SkPathOpsTypes.h b/src/pathops/SkPathOpsTypes.h index b35c97ef06..00c3e5fe93 100644 --- a/src/pathops/SkPathOpsTypes.h +++ b/src/pathops/SkPathOpsTypes.h @@ -31,6 +31,7 @@ class SkIntersectionHelper; class SkOpGlobalState { public: SkOpGlobalState(SkOpCoincidence* coincidence, SkOpContourHead* head + SkDEBUGPARAMS(bool debugSkipAssert) SkDEBUGPARAMS(const char* testName)); enum Phase { @@ -69,6 +70,7 @@ public: const class SkOpPtT* debugPtT(int id) const; bool debugRunFail() const; const class SkOpSegment* debugSegment(int id) const; + bool debugSkipAssert() const { return fDebugSkipAssert; } const class SkOpSpanBase* debugSpan(int id) const; const char* debugTestName() const { return fDebugTestName; } #endif @@ -152,6 +154,7 @@ private: int fPtTID; int fSegmentID; int fSpanID; + bool fDebugSkipAssert; #endif #if DEBUG_T_SECT_LOOP_COUNT int fDebugLoopCount[3]; diff --git a/tests/PathOpsAngleIdeas.cpp b/tests/PathOpsAngleIdeas.cpp index 8fc100ee02..2e3c7b9066 100755 --- a/tests/PathOpsAngleIdeas.cpp +++ b/tests/PathOpsAngleIdeas.cpp @@ -419,7 +419,7 @@ static void testQuadAngles(skiatest::Reporter* reporter, const SkDQuad& quad1, c SkPoint shortQuads[2][3]; SkOpContourHead contour; - SkOpGlobalState state(nullptr, &contour SkDEBUGPARAMS(nullptr)); + SkOpGlobalState state(nullptr, &contour SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr)); contour.init(&state, false, false); makeSegment(&contour, quad1, shortQuads[0], allocator); makeSegment(&contour, quad1, shortQuads[1], allocator); diff --git a/tests/PathOpsAngleTest.cpp b/tests/PathOpsAngleTest.cpp index faf5da50f2..6389c305bb 100644 --- a/tests/PathOpsAngleTest.cpp +++ b/tests/PathOpsAngleTest.cpp @@ -235,7 +235,7 @@ static const int circleDataSetSize = (int) SK_ARRAY_COUNT(circleDataSet); DEF_TEST(PathOpsAngleCircle, reporter) { SkChunkAlloc allocator(4096); SkOpContourHead contour; - SkOpGlobalState state(nullptr, &contour SkDEBUGPARAMS(nullptr)); + SkOpGlobalState state(nullptr, &contour SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr)); contour.init(&state, false, false); for (int index = 0; index < circleDataSetSize; ++index) { CircleData& data = circleDataSet[index]; @@ -427,7 +427,7 @@ struct FourPoints { DEF_TEST(PathOpsAngleAfter, reporter) { SkChunkAlloc allocator(4096); SkOpContourHead contour; - SkOpGlobalState state(nullptr, &contour SkDEBUGPARAMS(nullptr)); + SkOpGlobalState state(nullptr, &contour SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr)); contour.init(&state, false, false); for (int index = intersectDataSetsSize - 1; index >= 0; --index) { IntersectData* dataArray = intersectDataSets[index]; diff --git a/tests/PathOpsBuilderTest.cpp b/tests/PathOpsBuilderTest.cpp index e191ecee5e..e29b4bc473 100644 --- a/tests/PathOpsBuilderTest.cpp +++ b/tests/PathOpsBuilderTest.cpp @@ -301,3 +301,25 @@ DEF_TEST(Issue569540, reporter) { SkPath result; builder.resolve(&result); } + +DEF_TEST(SkOpBuilderFuzz665, reporter) { + SkPath path; + path.setFillType(SkPath::kEvenOdd_FillType); +path.moveTo(SkBits2Float(0xcc4264a7), SkBits2Float(0x4bb12e50)); // -5.0959e+07f, 2.32235e+07f +path.lineTo(SkBits2Float(0xcc4264b0), SkBits2Float(0x4bb12e48)); // -5.0959e+07f, 2.32234e+07f +path.lineTo(SkBits2Float(0xcc4264a7), SkBits2Float(0x4bb12e50)); // -5.0959e+07f, 2.32235e+07f +path.close(); + SkPath path1(path); + path.reset(); + path.setFillType(SkPath::kWinding_FillType); +path.moveTo(SkBits2Float(0x43213333), SkBits2Float(0x43080000)); // 161.2f, 136 +path.lineTo(SkBits2Float(0x43038000), SkBits2Float(0x43080000)); // 131.5f, 136 +path.cubicTo(SkBits2Float(0x43038000), SkBits2Float(0x42f00000), SkBits2Float(0x42f16666), SkBits2Float(0x42d53333), SkBits2Float(0x42d3cccd), SkBits2Float(0x42cd6666)); // 131.5f, 120, 120.7f, 106.6f, 105.9f, 102.7f +path.lineTo(SkBits2Float(0x42e33333), SkBits2Float(0x42940000)); // 113.6f, 74 + SkPath path2(path); + SkOpBuilder builder; + builder.add(path1, kUnion_SkPathOp); + builder.add(path2, kUnion_SkPathOp); + SkPath result; + builder.resolve(&result); +} diff --git a/tests/PathOpsExtendedTest.cpp b/tests/PathOpsExtendedTest.cpp index b5bf5b8d9f..572766086a 100644 --- a/tests/PathOpsExtendedTest.cpp +++ b/tests/PathOpsExtendedTest.cpp @@ -488,15 +488,17 @@ static void showName(const SkPath& a, const SkPath& b, const SkPathOp shapeOp) { #endif bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result, - bool expectSuccess SkDEBUGPARAMS(const char* testName)); + bool expectSuccess SkDEBUGPARAMS(bool skipAssert) + SkDEBUGPARAMS(const char* testName)); static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, - const SkPathOp shapeOp, const char* testName, bool expectSuccess) { + const SkPathOp shapeOp, const char* testName, bool expectSuccess, bool skipAssert) { #if 0 && DEBUG_SHOW_TEST_NAME showName(a, b, shapeOp); #endif SkPath out; - if (!OpDebug(a, b, shapeOp, &out, expectSuccess SkDEBUGPARAMS(testName))) { + if (!OpDebug(a, b, shapeOp, &out, expectSuccess SkDEBUGPARAMS(skipAssert) + SkDEBUGPARAMS(testName))) { SkDebugf("%s did not expect failure\n", __FUNCTION__); REPORTER_ASSERT(reporter, 0); return false; @@ -536,17 +538,22 @@ static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkP bool testPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, const SkPathOp shapeOp, const char* testName) { - return innerPathOp(reporter, a, b, shapeOp, testName, true); + return innerPathOp(reporter, a, b, shapeOp, testName, true, false); } bool testPathOpCheck(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, const SkPathOp shapeOp, const char* testName, bool checkFail) { - return innerPathOp(reporter, a, b, shapeOp, testName, checkFail); + return innerPathOp(reporter, a, b, shapeOp, testName, checkFail, false); } bool testPathOpFailCheck(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, const SkPathOp shapeOp, const char* testName) { - return innerPathOp(reporter, a, b, shapeOp, testName, false); + return innerPathOp(reporter, a, b, shapeOp, testName, false, false); +} + +bool testPathSkipAssertOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, + const SkPathOp shapeOp, const char* testName) { + return innerPathOp(reporter, a, b, shapeOp, testName, true, true); } bool testPathFailOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, diff --git a/tests/PathOpsExtendedTest.h b/tests/PathOpsExtendedTest.h index 17073833cb..0a6f4ab91f 100644 --- a/tests/PathOpsExtendedTest.h +++ b/tests/PathOpsExtendedTest.h @@ -44,6 +44,8 @@ extern bool testPathOpFailCheck(skiatest::Reporter* reporter, const SkPath& a, c const SkPathOp , const char* testName); extern bool testPathFailOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, const SkPathOp , const char* testName); +extern bool testPathSkipAssertOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, + const SkPathOp , const char* testName); extern bool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& state, const char* pathStr); extern bool testSimplify(skiatest::Reporter* reporter, const SkPath& path, const char* filename); diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp index 00a8f52477..d75c9a6fb6 100644 --- a/tests/PathOpsOpTest.cpp +++ b/tests/PathOpsOpTest.cpp @@ -5836,7 +5836,57 @@ SkPath path2(path); testPathFailOp(reporter, path1, path2, (SkPathOp) 1, filename); } +static void fuzz1450_0(skiatest::Reporter* reporter, const char* filename) { +SkPath path; +path.moveTo(SkBits2Float(0x43b40000), SkBits2Float(0xcf000000)); // 360, -2.14748e+09f +path.conicTo(SkBits2Float(0x4e800002), SkBits2Float(0xcf000000), SkBits2Float(0x4e800002), SkBits2Float(0xce7ffffe), SkBits2Float(0x3f3504f4)); // 1.07374e+09f, -2.14748e+09f, 1.07374e+09f, -1.07374e+09f, 0.707107f +path.conicTo(SkBits2Float(0x4e800002), SkBits2Float(0x43800001), SkBits2Float(0x43348000), SkBits2Float(0x43800001), SkBits2Float(0x3f3504f4)); // 1.07374e+09f, 256, 180.5f, 256, 0.707107f +SkPath path1(path); +path.reset(); +path.moveTo(SkBits2Float(0x43b40000), SkBits2Float(0x45816000)); // 360, 4140 +path.conicTo(SkBits2Float(0x43b40005), SkBits2Float(0x458a945d), SkBits2Float(0x45610000), SkBits2Float(0x458a945d), SkBits2Float(0x3f3504f3)); // 360, 4434.55f, 3600, 4434.55f, 0.707107f +path.conicTo(SkBits2Float(0x45d5bfff), SkBits2Float(0x458a945d), SkBits2Float(0x45d5bfff), SkBits2Float(0x45816000), SkBits2Float(0x3f3504f3)); // 6840, 4434.55f, 6840, 4140, 0.707107f +path.lineTo(SkBits2Float(0x42c80000), SkBits2Float(0x44000000)); // 100, 512 +path.lineTo(SkBits2Float(0x42000000), SkBits2Float(0x41800000)); // 32, 16 +path.lineTo(SkBits2Float(0x43b40000), SkBits2Float(0x44800000)); // 360, 1024 +path.lineTo(SkBits2Float(0x43b40000), SkBits2Float(0x45816000)); // 360, 4140 +path.close(); +SkPath path2(path); +testPathSkipAssertOp(reporter, path1, path2, kUnion_SkPathOp, filename); +} + +static void fuzz1450_1(skiatest::Reporter* reporter, const char* filename) { +SkPath path; +path.setFillType(SkPath::kEvenOdd_FillType); +path.moveTo(SkBits2Float(0x4e800002), SkBits2Float(0xce7ffffe)); // 1.07374e+09f, -1.07374e+09f +path.conicTo(SkBits2Float(0x4e800002), SkBits2Float(0xcf000000), SkBits2Float(0x43b40000), SkBits2Float(0xcf000000), SkBits2Float(0x3f3504f4)); // 1.07374e+09f, -2.14748e+09f, 360, -2.14748e+09f, 0.707107f +path.lineTo(SkBits2Float(0x43348000), SkBits2Float(0x43800001)); // 180.5f, 256 +path.lineTo(SkBits2Float(0x42000000), SkBits2Float(0x41800000)); // 32, 16 +path.lineTo(SkBits2Float(0x42c80000), SkBits2Float(0x44000000)); // 100, 512 +path.lineTo(SkBits2Float(0x43553abd), SkBits2Float(0x440f3cbd)); // 213.229f, 572.949f +path.lineTo(SkBits2Float(0x43b40000), SkBits2Float(0x44800000)); // 360, 1024 +path.lineTo(SkBits2Float(0x43b40000), SkBits2Float(0x45816000)); // 360, 4140 +path.conicTo(SkBits2Float(0x43b40005), SkBits2Float(0x458a945d), SkBits2Float(0x45610000), SkBits2Float(0x458a945d), SkBits2Float(0x3f3504f3)); // 360, 4434.55f, 3600, 4434.55f, 0.707107f +path.conicTo(SkBits2Float(0x45d5bfff), SkBits2Float(0x458a945d), SkBits2Float(0x45d5bfff), SkBits2Float(0x45816000), SkBits2Float(0x3f3504f3)); // 6840, 4434.55f, 6840, 4140, 0.707107f +path.lineTo(SkBits2Float(0x43553abd), SkBits2Float(0x440f3cbd)); // 213.229f, 572.949f +path.lineTo(SkBits2Float(0x43348000), SkBits2Float(0x43800001)); // 180.5f, 256 +path.conicTo(SkBits2Float(0x4e800002), SkBits2Float(0x43800001), SkBits2Float(0x4e800002), SkBits2Float(0xce7ffffe), SkBits2Float(0x3f3504f4)); // 1.07374e+09f, 256, 1.07374e+09f, -1.07374e+09f, 0.707107f +path.close(); +SkPath path1(path); +path.reset(); +path.moveTo(SkBits2Float(0x42fe0000), SkBits2Float(0x43a08000)); // 127, 321 +path.lineTo(SkBits2Float(0x45d5c000), SkBits2Float(0x43870000)); // 6840, 270 +path.lineTo(SkBits2Float(0xd0a00000), SkBits2Float(0x4cbebc20)); // -2.14748e+10f, 1e+08 +path.lineTo(SkBits2Float(0x451f7000), SkBits2Float(0x42800000)); // 2551, 64 +path.lineTo(SkBits2Float(0x42fe0000), SkBits2Float(0x43a08000)); // 127, 321 +path.close(); +SkPath path2(path); +testPathFailOp(reporter, path1, path2, kUnion_SkPathOp, filename); +} + static struct TestDesc failTests[] = { + TEST(fuzz1450_1), + TEST(fuzz1450_0), TEST(bug597926_0), TEST(fuzz535151), TEST(fuzz753_91), |