aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar caryclark <caryclark@google.com>2015-07-23 12:40:22 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-07-23 12:40:22 -0700
commitd4349723fac9c0fd4dcf8c275fb7c756bdfdff7b (patch)
tree20a850a4c02da163ac18a888494813fccc6f1862
parenta0170f10aadca337fc412953f3409eb368c6964b (diff)
fix path ops fuzz buster
Mark collapsed segments as done and remove collapsed segment references from the coincidence array. Also add test names to global debugging. R=fmalita@chromium.org BUG=512592 Review URL: https://codereview.chromium.org/1250293002
-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),