aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/pathops/SkOpBuilder.cpp2
-rwxr-xr-xsrc/pathops/SkOpCoincidence.cpp10
-rw-r--r--src/pathops/SkOpContour.h9
-rw-r--r--src/pathops/SkOpSegment.cpp9
-rw-r--r--src/pathops/SkOpSegment.h1
-rwxr-xr-xsrc/pathops/SkOpSpan.cpp10
-rw-r--r--src/pathops/SkOpSpan.h5
-rw-r--r--src/pathops/SkPathOpsCommon.cpp10
-rw-r--r--src/pathops/SkPathOpsCommon.h3
-rw-r--r--src/pathops/SkPathOpsOp.cpp6
-rw-r--r--src/pathops/SkPathOpsSimplify.cpp2
-rw-r--r--src/pathops/SkPathOpsTightBounds.cpp2
-rw-r--r--src/pathops/SkPathOpsTypes.cpp4
-rw-r--r--src/pathops/SkPathOpsTypes.h5
-rwxr-xr-xtests/PathOpsAngleIdeas.cpp2
-rw-r--r--tests/PathOpsAngleTest.cpp4
-rw-r--r--tests/PathOpsBuilderTest.cpp121
-rw-r--r--tests/PathOpsExtendedTest.cpp5
-rw-r--r--tests/PathOpsSimplifyTest.cpp65
19 files changed, 260 insertions, 15 deletions
diff --git a/src/pathops/SkOpBuilder.cpp b/src/pathops/SkOpBuilder.cpp
index 0d229a8c40..24a157afc5 100644
--- a/src/pathops/SkOpBuilder.cpp
+++ b/src/pathops/SkOpBuilder.cpp
@@ -44,7 +44,7 @@ void FixWinding(SkPath* path) {
}
SkChunkAlloc allocator(4096);
SkOpContourHead contourHead;
- SkOpGlobalState globalState(NULL, &contourHead);
+ SkOpGlobalState globalState(NULL, &contourHead SkDEBUGPARAMS(NULL));
SkOpEdgeBuilder builder(*path, &contourHead, &allocator, &globalState);
builder.finish(&allocator);
SkASSERT(contourHead.next());
diff --git a/src/pathops/SkOpCoincidence.cpp b/src/pathops/SkOpCoincidence.cpp
index 58ff7f3ab9..46d06e9e0b 100755
--- a/src/pathops/SkOpCoincidence.cpp
+++ b/src/pathops/SkOpCoincidence.cpp
@@ -568,6 +568,16 @@ void SkOpCoincidence::fixAligned() {
coin->fOppPtTEnd = coin->fOppPtTEnd->doppelganger();
}
} while ((coin = coin->fNext));
+ coin = fHead;
+ SkCoincidentSpans** priorPtr = &fHead;
+ do {
+ if (coin->fCoinPtTStart->collapsed(coin->fCoinPtTEnd)
+ || coin->fOppPtTStart->collapsed(coin->fOppPtTEnd)) {
+ *priorPtr = coin->fNext;
+ continue;
+ }
+ priorPtr = &coin->fNext;
+ } while ((coin = coin->fNext));
}
void SkOpCoincidence::fixUp(SkOpPtT* deleted, SkOpPtT* kept) {
diff --git a/src/pathops/SkOpContour.h b/src/pathops/SkOpContour.h
index 1225416eaa..7ef68b0377 100644
--- a/src/pathops/SkOpContour.h
+++ b/src/pathops/SkOpContour.h
@@ -192,6 +192,15 @@ public:
return fTail->pts()[SkPathOpsVerbToPoints(fTail->verb())];
}
+ bool findCollapsed() {
+ SkASSERT(fCount > 0);
+ SkOpSegment* segment = &fHead;
+ do {
+ segment->findCollapsed();
+ } while ((segment = segment->next()));
+ return true;
+ }
+
SkOpSpan* findSortableTop(SkOpContour* );
SkOpSegment* first() {
diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp
index fd8ab65acd..fc32643558 100644
--- a/src/pathops/SkOpSegment.cpp
+++ b/src/pathops/SkOpSegment.cpp
@@ -615,6 +615,15 @@ double SkOpSegment::distSq(double t, SkOpAngle* oppAngle) {
return closestDistSq;
}
+void SkOpSegment::findCollapsed() {
+ if (fHead.contains(&fTail)) {
+ markAllDone();
+ // move start and end to the same point
+ fHead.alignEnd(0, fHead.pt());
+ fTail.setAligned();
+ }
+}
+
/*
The M and S variable name parts stand for the operators.
Mi stands for Minuend (see wiki subtraction, analogous to difference)
diff --git a/src/pathops/SkOpSegment.h b/src/pathops/SkOpSegment.h
index 6873203b25..a3f5989824 100644
--- a/src/pathops/SkOpSegment.h
+++ b/src/pathops/SkOpSegment.h
@@ -182,6 +182,7 @@ public:
void dumpPts() const;
void dumpPtsInner() const;
+ void findCollapsed();
SkOpSegment* findNextOp(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** nextStart,
SkOpSpanBase** nextEnd, bool* unsortable, SkPathOp op,
int xorMiMask, int xorSuMask);
diff --git a/src/pathops/SkOpSpan.cpp b/src/pathops/SkOpSpan.cpp
index f5a52099da..5c89c736fb 100755
--- a/src/pathops/SkOpSpan.cpp
+++ b/src/pathops/SkOpSpan.cpp
@@ -13,6 +13,16 @@ bool SkOpPtT::alias() const {
return this->span()->ptT() != this;
}
+bool SkOpPtT::collapsed(const SkOpPtT* check) const {
+ if (fPt != check->fPt) {
+ return false;
+ }
+ SkASSERT(this != check);
+ const SkOpSegment* segment = this->segment();
+ SkASSERT(segment == check->segment());
+ return segment->collapsed();
+}
+
bool SkOpPtT::contains(const SkOpPtT* check) const {
SkASSERT(this != check);
const SkOpPtT* ptT = this;
diff --git a/src/pathops/SkOpSpan.h b/src/pathops/SkOpSpan.h
index ec62246c31..2a11c96dd7 100644
--- a/src/pathops/SkOpSpan.h
+++ b/src/pathops/SkOpSpan.h
@@ -48,6 +48,7 @@ public:
}
bool alias() const;
+ bool collapsed(const SkOpPtT* ) const;
bool contains(const SkOpPtT* ) const;
SkOpPtT* contains(const SkOpSegment* );
SkOpContour* contour() const;
@@ -266,6 +267,10 @@ public:
return fSegment;
}
+ void setAligned() {
+ fAligned = true;
+ }
+
void setChased(bool chased) {
fChased = chased;
}
diff --git a/src/pathops/SkPathOpsCommon.cpp b/src/pathops/SkPathOpsCommon.cpp
index 4ead297f7d..c53f458d1a 100644
--- a/src/pathops/SkPathOpsCommon.cpp
+++ b/src/pathops/SkPathOpsCommon.cpp
@@ -198,7 +198,7 @@ public:
void Assemble(const SkPathWriter& path, SkPathWriter* simple) {
SkChunkAlloc allocator(4096); // FIXME: constant-ize, tune
SkOpContourHead contour;
- SkOpGlobalState globalState(NULL, &contour);
+ SkOpGlobalState globalState(NULL, &contour SkDEBUGPARAMS(NULL));
#if DEBUG_SHOW_TEST_NAME
SkDebugf("</div>\n");
#endif
@@ -408,6 +408,13 @@ static void calcAngles(SkOpContourHead* contourList, SkChunkAlloc* allocator) {
} while ((contour = contour->next()));
}
+static void findCollapsed(SkOpContourHead* contourList) {
+ SkOpContour* contour = contourList;
+ do {
+ contour->findCollapsed();
+ } while ((contour = contour->next()));
+}
+
static bool missingCoincidence(SkOpContourHead* contourList,
SkOpCoincidence* coincidence, SkChunkAlloc* allocator) {
SkOpContour* contour = contourList;
@@ -444,6 +451,7 @@ bool HandleCoincidence(SkOpContourHead* contourList, SkOpCoincidence* coincidenc
SkOpGlobalState* globalState = contourList->globalState();
// combine t values when multiple intersections occur on some segments but not others
moveMultiples(contourList);
+ findCollapsed(contourList);
// move t values and points together to eliminate small/tiny gaps
moveNearby(contourList);
align(contourList); // give all span members common values
diff --git a/src/pathops/SkPathOpsCommon.h b/src/pathops/SkPathOpsCommon.h
index f76d57c83b..73bc0f42cc 100644
--- a/src/pathops/SkPathOpsCommon.h
+++ b/src/pathops/SkPathOpsCommon.h
@@ -25,7 +25,8 @@ SkOpSegment* FindUndone(SkOpContourHead* , SkOpSpanBase** startPtr,
void 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);
+bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result,
+ bool expectSuccess 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 9c09eaf8f3..12a9578dd3 100644
--- a/src/pathops/SkPathOpsOp.cpp
+++ b/src/pathops/SkPathOpsOp.cpp
@@ -223,12 +223,12 @@ static void dump_op(const SkPath& one, const SkPath& two, SkPathOp op) {
#endif
bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result,
- bool expectSuccess) {
+ bool expectSuccess 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);
+ SkOpGlobalState globalState(&coincidence, contourList SkDEBUGPARAMS(testName));
#if DEBUGGING_PATHOPS_FROM_HOST
dump_op(one, two, op);
#endif
@@ -304,5 +304,5 @@ bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result,
}
bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) {
- return OpDebug(one, two, op, result, true);
+ return OpDebug(one, two, op, result, true SkDEBUGPARAMS(NULL));
}
diff --git a/src/pathops/SkPathOpsSimplify.cpp b/src/pathops/SkPathOpsSimplify.cpp
index 11b6833a73..8c07653320 100644
--- a/src/pathops/SkPathOpsSimplify.cpp
+++ b/src/pathops/SkPathOpsSimplify.cpp
@@ -167,7 +167,7 @@ bool Simplify(const SkPath& path, SkPath* result) {
SkOpCoincidence coincidence;
SkOpContour contour;
SkOpContourHead* contourList = static_cast<SkOpContourHead*>(&contour);
- SkOpGlobalState globalState(&coincidence, contourList);
+ SkOpGlobalState globalState(&coincidence, contourList SkDEBUGPARAMS(NULL));
#if DEBUG_SORT
SkPathOpsDebug::gSortCount = SkPathOpsDebug::gSortCountDefault;
#endif
diff --git a/src/pathops/SkPathOpsTightBounds.cpp b/src/pathops/SkPathOpsTightBounds.cpp
index f60c291710..7eb72a9037 100644
--- a/src/pathops/SkPathOpsTightBounds.cpp
+++ b/src/pathops/SkPathOpsTightBounds.cpp
@@ -11,7 +11,7 @@ bool TightBounds(const SkPath& path, SkRect* result) {
SkChunkAlloc allocator(4096); // FIXME: constant-ize, tune
SkOpContour contour;
SkOpContourHead* contourList = static_cast<SkOpContourHead*>(&contour);
- SkOpGlobalState globalState(NULL, contourList);
+ SkOpGlobalState globalState(NULL, contourList SkDEBUGPARAMS(NULL));
// 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 dcd33c9d73..c3de93a94a 100644
--- a/src/pathops/SkPathOpsTypes.cpp
+++ b/src/pathops/SkPathOpsTypes.cpp
@@ -200,13 +200,15 @@ double SkDCubeRoot(double x) {
return result;
}
-SkOpGlobalState::SkOpGlobalState(SkOpCoincidence* coincidence, SkOpContourHead* head)
+SkOpGlobalState::SkOpGlobalState(SkOpCoincidence* coincidence, SkOpContourHead* head
+ SkDEBUGPARAMS(const char* testName))
: fCoincidence(coincidence)
, fContourHead(head)
, fNested(0)
, fWindingFailed(false)
, fAngleCoincidence(false)
, fPhase(kIntersecting)
+ SkDEBUGPARAMS(fDebugTestName(testName))
SkDEBUGPARAMS(fAngleID(0))
SkDEBUGPARAMS(fContourID(0))
SkDEBUGPARAMS(fPtTID(0))
diff --git a/src/pathops/SkPathOpsTypes.h b/src/pathops/SkPathOpsTypes.h
index 9550aa1ead..2cd45a5c4d 100644
--- a/src/pathops/SkPathOpsTypes.h
+++ b/src/pathops/SkPathOpsTypes.h
@@ -28,7 +28,8 @@ class SkOpContourHead;
class SkOpGlobalState {
public:
- SkOpGlobalState(SkOpCoincidence* coincidence, SkOpContourHead* head);
+ SkOpGlobalState(SkOpCoincidence* coincidence, SkOpContourHead* head
+ SkDEBUGPARAMS(const char* testName));
enum Phase {
kIntersecting,
@@ -67,6 +68,7 @@ public:
bool debugRunFail() const;
const class SkOpSegment* debugSegment(int id) const;
const class SkOpSpanBase* debugSpan(int id) const;
+ const char* debugTestName() const { return fDebugTestName; }
#endif
int nested() const {
@@ -128,6 +130,7 @@ private:
bool fAngleCoincidence;
Phase fPhase;
#ifdef SK_DEBUG
+ const char* fDebugTestName;
int fAngleID;
int fContourID;
int fPtTID;
diff --git a/tests/PathOpsAngleIdeas.cpp b/tests/PathOpsAngleIdeas.cpp
index 79e09b9865..88b469e21a 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(NULL, &contour);
+ SkOpGlobalState state(NULL, &contour SkDEBUGPARAMS(NULL));
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 9c707743cf..9f9c321a42 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(NULL, &contour);
+ SkOpGlobalState state(NULL, &contour SkDEBUGPARAMS(NULL));
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(NULL, &contour);
+ SkOpGlobalState state(NULL, &contour SkDEBUGPARAMS(NULL));
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 df77100b01..08fc632732 100644
--- a/tests/PathOpsBuilderTest.cpp
+++ b/tests/PathOpsBuilderTest.cpp
@@ -150,3 +150,124 @@ DEF_TEST(BuilderIssue502792_2, reporter) {
SkPath result;
builder.resolve(&result);
}
+
+DEF_TEST(Fuzz846, reporter) {
+/*
+<clipPath id="clip-circle">
+ <circle id="circle" cx="60" cy="60" r="50" />
+</clipPath>
+<clipPath id="clip-rect">
+ <clipPath id="clip-rect">
+ <clipPath id="clip-rect">
+ <clipPath id="clip-rect">
+ <rect x="10" y="30" width="0" height="60" />
+ <rect x="10" y="30" width="0" height="60" />
+ <rect x="10" y="30" width="100" height="60" />
+ <rect x="10" y="30" width="32668" />
+ <rect x="10" y="30" width="100" height="18446744073709551615" />
+ <rect x="10" y="255" width="100" height="60" />
+ <rect width="100" height="60" />
+ <rect x="10" y="30" width="100" height="60" />
+ <rect x="10" y="30" width="100" height="4294967236" />
+ <rect x="10" y="30" width="100" height="60" />
+ </clipPath>
+ <rect x="10" y="30" width="0" height="60" />
+ <rect x="10" y="30" width="0" height="0.18093252719929986369568203" />
+ <rect x="10" y="30" width="100" height="60" />
+ <rect x="10" y="30" width="32668" height="60" />
+ <rect x="10" y="30" width="100" height="18446744073709551615" />
+ <rect x="10" y="255" width="100" height="60" />
+ <rect x="2147483649" y="30" width="100" height="60" />
+ <rect x="10" y="30" width="100" height="60" />
+ <rect x="10" y="30" width="100" height="60" />
+ <rect x="10" y="30" width="100" height="60" />
+ </clipPath>
+ <rect x="10" y="30" width="0" height="60" />
+ <rect x="10" y="30" width="0" height="60" />
+ <rect x="10" y="30" width="100" height="60" />
+ <rect x="10" y="30" width="32668" height="60" />
+ <rect x="10" y="30" width="100" height="18446744073709551615" />
+ <rect x="10" y="255" width="100" height="60" />
+ <rect x="2147483649" y="30" width="100" height="60" />
+ <rect x="10" y="30" width="100" height="60" />
+ <rect x="10" y="2879753595" width="100" height="60" />
+ <rect x="10" y="30" width="100" height="60" />
+ </clipPath>
+ <rect x="10" y="30" width="100" height="60" />
+ <rect x="10" y="30" width="0" height="60" />
+ <rect x="10" y="30" width="100" height="60" />
+ <rect x="10" y="30" width="32668" height="60" />
+ <rect x="10" y="30" width="100" height="18446744073709551615" />
+ <rect x="10" y="255" width="100" height="60" />
+ <rect x="2147483649" y="30" width="100" height="60" />
+ <rect x="10" y="30" width="100" height="60" />
+ <rect x="10" y="30" width="100" height="4294967236" />
+ <rect x="10" y="30" width="100" height="4294967236" />
+ <rect x="10" y="30" width="100" height="4294967236" />
+ <rect x="10" y="30" width="100" height="4294967236" />
+ <rect x="10" y="30" width="100" height="60" />
+ <rect x="757798030" y="30" width="100" height="60" />
+*/
+ SkPath clipCircle, clipRect;
+ SkPath inner;
+ clipCircle.addCircle(60, 60, 50); // <circle id="circle" cx="60" cy="60" r="50" />
+
+ inner.addRect(10, 30, 10+0, 30+60); // <rect x="10" y="30" width="0" height="60" />
+ inner.addRect(10, 30, 10+0, 30+60); // <rect x="10" y="30" width="0" height="60" />
+ inner.addRect(10, 30, 10+100, 30+60); // <rect x="10" y="30" width="100" height="60" />
+ inner.addRect(10, 30, 10+32668, 30+0); // <rect x="10" y="30" width="32668" />
+ inner.addRect(10, 30, 10+100, 30+18446744073709551615.f); // <rect x="10" y="30" width="100" height="18446744073709551615" />
+ inner.addRect(10, 255, 10+100, 255+60); // <rect x="10" y="255" width="100" height="60" />
+ inner.addRect(0, 0, 0+100, 0+60); // <rect width="100" height="60" />
+ inner.addRect(10, 30, 10+100, 30+60); // <rect x="10" y="30" width="100" height="60" />
+ inner.addRect(10, 30, 10+100, 30+4294967236.f); // <rect x="10" y="30" width="100" height="4294967236" />
+ inner.addRect(10, 30, 10+100, 30+60); // <rect x="10" y="30" width="100" height="60" />
+ clipRect.addPath(inner);
+ inner.reset();
+ inner.addRect(10, 30, 10+0, 30+60); // <rect x="10" y="30" width="0" height="60" />
+ inner.addRect(10, 30, 10+0, 30+0.18093252719929986369568203f); // <rect x="10" y="30" width="0" height="0.18093252719929986369568203" />
+ inner.addRect(10, 30, 10+100, 30+60); // <rect x="10" y="30" width="100" height="60" />
+ inner.addRect(10, 30, 10+32668, 30+60); // <rect x="10" y="30" width="32668" height="60" />
+ inner.addRect(10, 30, 10+100, 30+18446744073709551615.f); // <rect x="10" y="30" width="100" height="18446744073709551615" />
+ inner.addRect(10, 255, 10+100, 255+60); // <rect x="10" y="255" width="100" height="60" />
+ inner.addRect(2147483649.f, 30, 2147483649.f+100, 30+60); // <rect x="2147483649" y="30" width="100" height="60" />
+ inner.addRect(10, 30, 10+100, 30+60); // <rect x="10" y="30" width="100" height="60" />
+ inner.addRect(10, 30, 10+100, 30+60); // <rect x="10" y="30" width="100" height="60" />
+ inner.addRect(10, 30, 10+100, 30+60); // <rect x="10" y="30" width="100" height="60" />
+ clipRect.addPath(inner);
+ inner.reset();
+ inner.addRect(10, 30, 10+0, 30+60); // <rect x="10" y="30" width="0" height="60" />
+ inner.addRect(10, 30, 10+0, 30+60); // <rect x="10" y="30" width="0" height="60" />
+ inner.addRect(10, 30, 10+100, 30+60); // <rect x="10" y="30" width="100" height="60" />
+ inner.addRect(10, 30, 10+32668, 30+60); // <rect x="10" y="30" width="32668" height="60" />
+ inner.addRect(10, 30, 10+100, 30+18446744073709551615.f); // <rect x="10" y="30" width="100" height="18446744073709551615" />
+ inner.addRect(10, 255, 10+100, 255+60); // <rect x="10" y="255" width="100" height="60" />
+ inner.addRect(2147483649.f, 30, 2147483649.f+100, 30+60); // <rect x="2147483649" y="30" width="100" height="60" />
+ inner.addRect(10, 30, 10+100, 30+60); // <rect x="10" y="30" width="100" height="60" />
+ inner.addRect(10, 2879753595.f, 10+100, 30+2879753595.f); // <rect x="10" y="2879753595" width="100" height="60" />
+ inner.addRect(10, 30, 10+100, 30+60); // <rect x="10" y="30" width="100" height="60" />
+ clipRect.addPath(inner);
+ inner.reset();
+ inner.addRect(10, 30, 10+100, 30+60); // <rect x="10" y="30" width="100" height="60" />
+ inner.addRect(10, 30, 10+0, 30+60); // <rect x="10" y="30" width="0" height="60" />
+ inner.addRect(10, 30, 10+100, 30+60); // <rect x="10" y="30" width="100" height="60" />
+ inner.addRect(10, 30, 10+32668, 30+60); // <rect x="10" y="30" width="32668" height="60" />
+ inner.addRect(10, 30, 10+100, 30+18446744073709551615.f); // <rect x="10" y="30" width="100" height="18446744073709551615" />
+ inner.addRect(10, 255, 10+100, 255+60); // <rect x="10" y="255" width="100" height="60" />
+ inner.addRect(2147483649.f, 30, 2147483649.f+100, 30+60); // <rect x="2147483649" y="30" width="100" height="60" />
+ inner.addRect(10, 30, 10+100, 30+60); // <rect x="10" y="30" width="100" height="60" />
+ inner.addRect(10, 30, 10+100, 30+4294967236.f); // <rect x="10" y="30" width="100" height="4294967236" />
+ inner.addRect(10, 30, 10+100, 30+4294967236.f); // <rect x="10" y="30" width="100" height="4294967236" />
+ inner.addRect(10, 30, 10+100, 30+4294967236.f); // <rect x="10" y="30" width="100" height="4294967236" />
+ inner.addRect(10, 30, 10+100, 30+4294967236.f); // <rect x="10" y="30" width="100" height="4294967236" />
+ inner.addRect(10, 30, 10+100, 30+60); // <rect x="10" y="30" width="100" height="60" />
+ inner.addRect(757798030.f, 30, 757798030.f+100, 30+60); // <rect x="757798030" y="30" width="100" height="60" />
+ clipRect.addPath(inner);
+
+ SkOpBuilder builder;
+ builder.add(clipCircle, kUnion_SkPathOp);
+ builder.add(clipRect, kDifference_SkPathOp);
+ SkPath result;
+ builder.resolve(&result);
+}
+
diff --git a/tests/PathOpsExtendedTest.cpp b/tests/PathOpsExtendedTest.cpp
index 69a2d617b0..d458c41e97 100644
--- a/tests/PathOpsExtendedTest.cpp
+++ b/tests/PathOpsExtendedTest.cpp
@@ -488,7 +488,8 @@ 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);
+bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result,
+ bool expectSuccess SkDEBUGPARAMS(const char* testName));
static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
const SkPathOp shapeOp, const char* testName, bool expectSuccess) {
@@ -496,7 +497,7 @@ static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkP
showName(a, b, shapeOp);
#endif
SkPath out;
- if (!OpDebug(a, b, shapeOp, &out, expectSuccess)) {
+ if (!OpDebug(a, b, shapeOp, &out, expectSuccess SkDEBUGPARAMS(testName))) {
SkDebugf("%s did not expect failure\n", __FUNCTION__);
REPORTER_ASSERT(reporter, 0);
return false;
diff --git a/tests/PathOpsSimplifyTest.cpp b/tests/PathOpsSimplifyTest.cpp
index 5b763dee83..165ee8d11d 100644
--- a/tests/PathOpsSimplifyTest.cpp
+++ b/tests/PathOpsSimplifyTest.cpp
@@ -4810,11 +4810,76 @@ static void testQuads65(skiatest::Reporter* reporter,const char* filename) {
testSimplify(reporter, path, filename);
}
+static void fuzz864a(skiatest::Reporter* reporter,const char* filename) {
+ SkPath path;
+ path.moveTo(10, 90);
+ path.lineTo(10, 90);
+ path.lineTo(10, 30);
+ path.lineTo(10, 30);
+ path.lineTo(10, 90);
+ path.close();
+ path.moveTo(10, 90);
+ path.lineTo(10, 90);
+ path.lineTo(10, 30);
+ path.lineTo(10, 30);
+ path.lineTo(10, 90);
+ path.close();
+ path.moveTo(10, 90);
+ path.lineTo(110, 90);
+ path.lineTo(110, 30);
+ path.lineTo(10, 30);
+ path.lineTo(10, 90);
+ path.close();
+ path.moveTo(10, 30);
+ path.lineTo(32678, 30);
+ path.lineTo(32678, 30);
+ path.lineTo(10, 30);
+ path.close();
+ path.moveTo(10, 3.35545e+07f);
+ path.lineTo(110, 3.35545e+07f);
+ path.lineTo(110, 30);
+ path.lineTo(10, 30);
+ path.lineTo(10, 3.35545e+07f);
+ path.close();
+ path.moveTo(10, 315);
+ path.lineTo(110, 315);
+ path.lineTo(110, 255);
+ path.lineTo(10, 255);
+ path.lineTo(10, 315);
+ path.close();
+ path.moveTo(0, 60);
+ path.lineTo(100, 60);
+ path.lineTo(100, 0);
+ path.lineTo(0, 0);
+ path.lineTo(0, 60);
+ path.close();
+ path.moveTo(10, 90);
+ path.lineTo(110, 90);
+ path.lineTo(110, 30);
+ path.lineTo(10, 30);
+ path.lineTo(10, 90);
+ path.close();
+ path.moveTo(10, 3.35545e+07f);
+ path.lineTo(110, 3.35545e+07f);
+ path.lineTo(110, 30);
+ path.lineTo(10, 30);
+ path.lineTo(10, 3.35545e+07f);
+ path.close();
+ path.moveTo(10, 90);
+ path.lineTo(110, 90);
+ path.lineTo(110, 30);
+ path.lineTo(10, 30);
+ path.lineTo(10, 90);
+ path.close();
+ testSimplify(reporter, path, filename);
+}
+
static void (*skipTest)(skiatest::Reporter* , const char* filename) = 0;
static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0;
static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
static TestDesc tests[] = {
+ TEST(fuzz864a),
TEST(testQuads65),
TEST(testIssue3838_3),
TEST(testIssue3838),