diff --git a/src/pathops/SkOpAngle.h b/src/pathops/SkOpAngle.h index 63d378d73c..098c470128 100644 --- a/src/pathops/SkOpAngle.h +++ b/src/pathops/SkOpAngle.h @@ -160,10 +160,10 @@ public: void reset(); private: void dump() const; // utility to be called by user from debugger + SkChunkAlloc* fAngles; #if DEBUG_ANGLE int fCount; #endif - SkChunkAlloc* fAngles; }; #endif diff --git a/src/pathops/SkOpContour.cpp b/src/pathops/SkOpContour.cpp index 5ef702d4c1..e4dd62a653 100644 --- a/src/pathops/SkOpContour.cpp +++ b/src/pathops/SkOpContour.cpp @@ -452,8 +452,14 @@ void SkOpContour::checkCoincidentPair(const SkCoincidence& oneCoin, int oneIdx, } if (cancelers) { if (missingT1 >= 0) { + if (addTo1->reversePoints(missingPt1, missingPt2)) { + SkTSwap(missingPt1, missingPt2); + } addTo1->addTCancel(missingPt1, missingPt2, addOther1); } else { + if (addTo2->reversePoints(missingPt1, missingPt2)) { + SkTSwap(missingPt1, missingPt2); + } addTo2->addTCancel(missingPt1, missingPt2, addOther2); } } else if (missingT1 >= 0) { diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp index f6d989b18a..747cd9d497 100644 --- a/src/pathops/SkOpSegment.cpp +++ b/src/pathops/SkOpSegment.cpp @@ -2294,9 +2294,10 @@ void SkOpSegment::checkSmall() { } const SkOpSpan& firstSpan = this->firstSpan(*thisSpan); const SkOpSpan& lastSpan = this->lastSpan(*thisSpan); + const SkOpSpan* nextSpan = &firstSpan + 1; ptrdiff_t smallCount = &lastSpan - &firstSpan + 1; SkASSERT(1 <= smallCount && smallCount < count()); - if (smallCount <= 1) { + if (smallCount <= 1 && !nextSpan->fSmall) { SkASSERT(1 == smallCount); checkSmallCoincidence(firstSpan, NULL); continue; @@ -3067,6 +3068,13 @@ int SkOpSegment::findOtherT(double t, const SkOpSegment* match) const { int SkOpSegment::findT(double t, const SkPoint& pt, const SkOpSegment* match) const { int count = this->count(); + // prefer exact matches over approximate matches + for (int index = 0; index < count; ++index) { + const SkOpSpan& span = fTs[index]; + if (span.fT == t && span.fOther == match) { + return index; + } + } for (int index = 0; index < count; ++index) { const SkOpSpan& span = fTs[index]; if (approximately_equal_orderable(span.fT, t) && span.fOther == match) { @@ -3986,6 +3994,24 @@ void SkOpSegment::pinT(const SkPoint& pt, double* t) { } } +bool SkOpSegment::reversePoints(const SkPoint& p1, const SkPoint& p2) const { + SkASSERT(p1 != p2); + int spanCount = count(); + int p1IndexMin = -1; + int p2IndexMax = spanCount; + for (int index = 0; index < spanCount; ++index) { + const SkOpSpan& span = fTs[index]; + if (span.fPt == p1) { + if (p1IndexMin < 0) { + p1IndexMin = index; + } + } else if (span.fPt == p2) { + p2IndexMax = index; + } + } + return p1IndexMin > p2IndexMax; +} + void SkOpSegment::setCoincidentRange(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other) { int count = this->count(); diff --git a/src/pathops/SkOpSegment.h b/src/pathops/SkOpSegment.h index d191e88af2..df87d058b6 100644 --- a/src/pathops/SkOpSegment.h +++ b/src/pathops/SkOpSegment.h @@ -177,6 +177,8 @@ public: fTs.reset(); } + bool reversePoints(const SkPoint& p1, const SkPoint& p2) const; + void setOppXor(bool isOppXor) { fOppXor = isOppXor; } diff --git a/tests/PathOpsSkpClipTest.cpp b/tests/PathOpsSkpClipTest.cpp index 0e3cee9f4e..a94412e989 100755 --- a/tests/PathOpsSkpClipTest.cpp +++ b/tests/PathOpsSkpClipTest.cpp @@ -38,7 +38,7 @@ const struct SkipOverTest { { 7, "http___www_foxsports_nl_.skp", true}, // (no repro on mac) addT SkASSERT(this != other || fVerb == SkPath::kCubic_Verb) {13, "http___www_modernqigong_com_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y)); {14, "http___www_devbridge_com_.skp", true}, // checkSmallCoincidence SkASSERT(!next->fSmall || checkMultiple); - {16, "http___www_1023world_net_.skp", true}, // bitmap decode assert (corrupt skp?) + {16, "http___www_1023world_net_.skp", false}, // bitmap decode assert (corrupt skp?) {19, "http___www_alamdi_com_.skp", true}, // cubic/quad intersection {26, "http___www_liveencounters_net_.skp", true}, // (no repro on mac) checkSmall addT:549 (line, expects cubic) {28, "http___www_encros_fr_.skp", false}, // SkAAClip::Builder::addRun SkASSERT(fBounds.contains(x, y)); diff --git a/tests/PathOpsSkpTest.cpp b/tests/PathOpsSkpTest.cpp index 2da38f4166..32ddf61f43 100755 --- a/tests/PathOpsSkpTest.cpp +++ b/tests/PathOpsSkpTest.cpp @@ -3571,8 +3571,6 @@ static void skpwww_9to5mac_com_64(skiatest::Reporter* reporter, const char* file testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); } -#if TEST_NEW_FAILURES -// addTCoincident SkASSERT(test->fT < 1); static void skpwww_googleventures_com_32(skiatest::Reporter* reporter, const char* filename) { SkPath path; path.setFillType(SkPath::kEvenOdd_FillType); @@ -3592,7 +3590,7 @@ static void skpwww_googleventures_com_32(skiatest::Reporter* reporter, const cha testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); } -// checkSmallCoincidence failed assertion "!next->fSmall || checkMultiple" +#if TEST_NEW_FAILURES static void skpwww_devbridge_com_22(skiatest::Reporter* reporter, const char* filename) { SkPath path; path.setFillType(SkPath::kEvenOdd_FillType); @@ -3672,8 +3670,8 @@ static void skpwww_familysurvivalprotocol_wordpress_com_61(skiatest::Reporter* r pathB.lineTo(165, 14557); testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); } +#endif -// addTCancel: failed assertion "oIndex > 0" static void skpwww_firstunitedbank_com_19(skiatest::Reporter* reporter, const char* filename) { SkPath path; path.setFillType(SkPath::kEvenOdd_FillType); @@ -3709,7 +3707,6 @@ static void skpwww_firstunitedbank_com_19(skiatest::Reporter* reporter, const ch pathB.lineTo(1047, 11703); testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); } -#endif // addSimpleAngle: failed assertion "index == count() - 2" static void skpwww_shinydemos_com_5(skiatest::Reporter* reporter, const char* filename) { @@ -3764,17 +3761,77 @@ static void skpwww_lptemp_com_3(skiatest::Reporter* reporter, const char* filena testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); } +#if TEST_NEW_FAILURES +// SkOpSegment.cpp:3915: failed assertion "otherEnd >= 0" +static void skpwww_shinydemos_com_15(skiatest::Reporter* reporter, const char* filename) { + SkPath path; + path.setFillType(SkPath::kEvenOdd_FillType); + path.moveTo(1000, 310.947968f); + path.lineTo(771.570374f, 82.5183716f); + path.lineTo(205.884888f, 648.203857f); + path.lineTo(448.68103f, 891); + path.lineTo(641.911255f, 891); + path.lineTo(1000, 532.911316f); + path.lineTo(1000, 310.947968f); + path.close(); + SkPath pathB; + pathB.setFillType(SkPath::kWinding_FillType); + pathB.moveTo(771.570374f, 82.5183716f); + pathB.lineTo(1110.98169f, 421.929626f); + pathB.lineTo(545.296204f, 987.615051f); + pathB.lineTo(205.884949f, 648.203796f); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); +} + +// SkOpSegment.cpp:4398: failed assertion "!span->fDone" +static void skpwww_lptemp_com_5(skiatest::Reporter* reporter, const char* filename) { + SkPath path; + path.setFillType(SkPath::kEvenOdd_FillType); + path.moveTo(78.6429825f, 3150.97632f); + path.quadTo(79.6192932f, 3150, 81.0000076f, 3150); + path.lineTo(341, 3150); + path.quadTo(342.380707f, 3150, 343.357025f, 3150.97632f); + path.quadTo(344.333344f, 3151.95264f, 344.333344f, 3153.33325f); + path.lineTo(344.333344f, 5205.3335f); + path.quadTo(344.333344f, 5206.71436f, 343.357025f, 5207.69092f); + path.quadTo(342.380707f, 5208.66699f, 341, 5208.66699f); + path.lineTo(81.0000076f, 5208.66699f); + path.quadTo(79.6192932f, 5208.66699f, 78.6429825f, 5207.69092f); + path.quadTo(77.6666718f, 5206.71436f, 77.6666718f, 5205.3335f); + path.lineTo(77.6666718f, 3153.33325f); + path.quadTo(77.6666718f, 3151.95264f, 78.6429825f, 3150.97632f); + path.close(); + SkPath pathB; + pathB.setFillType(SkPath::kEvenOdd_FillType); + pathB.moveTo(81, 3150); + pathB.lineTo(341, 3150); + pathB.cubicTo(342.840942f, 3150, 344.333344f, 3151.49268f, 344.333344f, 3153.3335f); + pathB.lineTo(344.333344f, 5205.3335f); + pathB.cubicTo(344.333344f, 5206.99023f, 342.840942f, 5208.3335f, 341, 5208.3335f); + pathB.lineTo(81, 5208.3335f); + pathB.cubicTo(79.15905f, 5208.3335f, 77.6666718f, 5206.99023f, 77.6666718f, 5205.3335f); + pathB.lineTo(77.6666718f, 3153.3335f); + pathB.cubicTo(77.6666718f, 3151.49268f, 79.15905f, 3150, 81, 3150); + pathB.close(); + testPathOp(reporter, path, pathB, kIntersect_PathOp, filename); +} +#endif + static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0; static struct TestDesc tests[] = { TEST(skpwww_lptemp_com_3), TEST(skpwww_shinydemos_com_5), #if TEST_NEW_FAILURES + TEST(skpwww_lptemp_com_5), + TEST(skpwww_shinydemos_com_15), TEST(skpwww_familysurvivalprotocol_wordpress_com_61), TEST(skpwww_alamdi_com_3), TEST(skpwww_devbridge_com_22), - TEST(skpwww_googleventures_com_32), #endif + TEST(skpwww_firstunitedbank_com_19), + TEST(skpwww_googleventures_com_32), TEST(skpwww_9to5mac_com_64), TEST(skpwww_wartepop_blogspot_com_br_6), TEST(skpwww_wartepop_blogspot_com_br_6a),