From 6c3b9cdcb047afe963c7bcf34834ba2ecccacc33 Mon Sep 17 00:00:00 2001 From: caryclark Date: Mon, 26 Sep 2016 05:36:58 -0700 Subject: [PATCH] fix tiger b The tiger tests have uncovered numerous bugs. This CL fixes the last of them. If a pair of curves do not intersect, but have one or both ends very close to the opposite curve, consider that an intersection. TBR=reed@google.com BUG=skia:5131 GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2356363003 Review-Url: https://codereview.chromium.org/2356363003 --- gyp/pathops_unittest.gypi | 1 + src/pathops/SkOpAngle.cpp | 8 +- src/pathops/SkOpCoincidence.cpp | 2 +- src/pathops/SkOpCoincidence.h | 2 + src/pathops/SkPathOpsDebug.cpp | 47 +- src/pathops/SkPathOpsDebug.h | 2 +- src/pathops/SkPathOpsTSect.h | 91 +- tests/PathOpsConicQuadIntersectionTest.cpp | 69 + tests/PathOpsCubicIntersectionTest.cpp | 4 +- tests/PathOpsSimplifyTest.cpp | 4 +- tests/PathOpsTSectDebug.h | 6 +- tools/pathops_sorter.htm | 33 +- tools/pathops_visualizer.htm | 1523 ++++++++++++++++++-- 13 files changed, 1568 insertions(+), 224 deletions(-) create mode 100644 tests/PathOpsConicQuadIntersectionTest.cpp diff --git a/gyp/pathops_unittest.gypi b/gyp/pathops_unittest.gypi index 750a65a38a..15cdb9c4ae 100644 --- a/gyp/pathops_unittest.gypi +++ b/gyp/pathops_unittest.gypi @@ -29,6 +29,7 @@ '../tests/PathOpsBuildUseTest.cpp', '../tests/PathOpsConicIntersectionTest.cpp', '../tests/PathOpsConicLineIntersectionTest.cpp', + '../tests/PathOpsConicQuadIntersectionTest.cpp', '../tests/PathOpsCubicConicIntersectionTest.cpp', '../tests/PathOpsCubicIntersectionTest.cpp', '../tests/PathOpsCubicIntersectionTestData.cpp', diff --git a/src/pathops/SkOpAngle.cpp b/src/pathops/SkOpAngle.cpp index db86077769..09f015c287 100644 --- a/src/pathops/SkOpAngle.cpp +++ b/src/pathops/SkOpAngle.cpp @@ -841,11 +841,11 @@ void SkOpAngle::setSpans() { } const SkOpSegment* segment = fStart->segment(); const SkPoint* pts = segment->pts(); - SkDEBUGCODE(fPart.fCurve.fVerb = SkPath::kCubic_Verb); + SkDEBUGCODE(fPart.fCurve.fVerb = SkPath::kCubic_Verb); // required for SkDCurve debug check SkDEBUGCODE(fPart.fCurve[2].fX = fPart.fCurve[2].fY = fPart.fCurve[3].fX = fPart.fCurve[3].fY - = SK_ScalarNaN); - SkDEBUGCODE(fPart.fCurve.fVerb = segment->verb()); - segment->subDivide(fStart, fEnd, &fPart.fCurve); + = SK_ScalarNaN); // make the non-line part uninitialized + SkDEBUGCODE(fPart.fCurve.fVerb = segment->verb()); // set the curve type for real + segment->subDivide(fStart, fEnd, &fPart.fCurve); // set at least the line part if not more fOriginalCurvePart = fPart.fCurve; const SkPath::Verb verb = segment->verb(); fPart.setCurveHullSweep(verb); diff --git a/src/pathops/SkOpCoincidence.cpp b/src/pathops/SkOpCoincidence.cpp index d2874c3c5e..964fdc502a 100755 --- a/src/pathops/SkOpCoincidence.cpp +++ b/src/pathops/SkOpCoincidence.cpp @@ -1216,7 +1216,7 @@ bool SkOpCoincidence::apply() { } windValue = oppValue = 0; } -#if DEBUG_COINCIDENCE +#if 0 && DEBUG_COINCIDENCE SkDebugf("seg=%d span=%d windValue=%d oppValue=%d\n", segment->debugID(), start->debugID(), windValue, oppValue); SkDebugf("seg=%d span=%d windValue=%d oppValue=%d\n", oSegment->debugID(), diff --git a/src/pathops/SkOpCoincidence.h b/src/pathops/SkOpCoincidence.h index 320d9aedc4..5815196b2c 100644 --- a/src/pathops/SkOpCoincidence.h +++ b/src/pathops/SkOpCoincidence.h @@ -168,6 +168,8 @@ public: return SkDEBUGRELEASE(fGlobalState->debugAngle(id), nullptr); } + void debugCheckBetween() const; + #if DEBUG_COINCIDENCE_VERBOSE void debugCheckValid(const char* id, SkPathOpsDebug::GlitchLog* log) const; #endif diff --git a/src/pathops/SkPathOpsDebug.cpp b/src/pathops/SkPathOpsDebug.cpp index 5326addf8d..18db448f59 100644 --- a/src/pathops/SkPathOpsDebug.cpp +++ b/src/pathops/SkPathOpsDebug.cpp @@ -371,7 +371,7 @@ void SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList, const char* id) { SkDebugf("\n"); } contourList->globalState()->debugSetCheckHealth(false); -#if 0 && DEBUG_ACTIVE_SPANS +#if 01 && DEBUG_ACTIVE_SPANS SkDebugf("active after %s:\n", id); ShowActiveSpans(contourList); #endif @@ -1846,11 +1846,9 @@ void SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchL #endif void SkCoincidentSpans::debugShow() const { - SkDebugf("%s - id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__, - coinPtTStart()->segment()->debugID(), + SkDebugf("coinSpan - id=%d t=%1.9g tEnd=%1.9g\n", coinPtTStart()->segment()->debugID(), coinPtTStart()->fT, coinPtTEnd()->fT); - SkDebugf("%s + id=%d t=%1.9g tEnd=%1.9g\n", __FUNCTION__, - oppPtTStart()->segment()->debugID(), + SkDebugf("coinSpan + id=%d t=%1.9g tEnd=%1.9g\n", oppPtTStart()->segment()->debugID(), oppPtTStart()->fT, oppPtTEnd()->fT); } @@ -1865,7 +1863,7 @@ void SkOpCoincidence::debugShowCoincidence() const { } #if DEBUG_COINCIDENCE -static void DebugValidate(const SkOpSpanBase* next, const SkOpSpanBase* end, +static void DebugCheckBetween(const SkOpSpanBase* next, const SkOpSpanBase* end, double oStart, double oEnd, const SkOpSegment* oSegment, const char* id, SkPathOpsDebug::GlitchLog* log) { SkASSERT(next != end); @@ -1986,12 +1984,6 @@ static void DebugValidate(const SkCoincidentSpans* head, const SkCoincidentSpans SkASSERT(coin->coinPtTEnd()->span()->ptT() == coin->coinPtTEnd()); SkASSERT(coin->oppPtTStart()->span()->ptT() == coin->oppPtTStart()); SkASSERT(coin->oppPtTEnd()->span()->ptT() == coin->oppPtTEnd()); - DebugValidate(coin->coinPtTStart()->span(), coin->coinPtTEnd()->span(), - coin->oppPtTStart()->fT, coin->oppPtTEnd()->fT, coin->oppPtTStart()->segment(), - id, log); - DebugValidate(coin->oppPtTStart()->span(), coin->oppPtTEnd()->span(), - coin->coinPtTStart()->fT, coin->coinPtTEnd()->fT, coin->coinPtTStart()->segment(), - id, log); coin = coin->next(); } DebugCheckOverlapTop(head, opt, id, log); @@ -2000,14 +1992,39 @@ static void DebugValidate(const SkCoincidentSpans* head, const SkCoincidentSpans void SkOpCoincidence::debugValidate() const { #if DEBUG_COINCIDENCE - // if (fGlobalState->debugCheckHealth()) { -// return; -// } DebugValidate(fHead, fTop, nullptr, nullptr); DebugValidate(fTop, nullptr, nullptr, nullptr); #endif } +#if DEBUG_COINCIDENCE +static void DebugCheckBetween(const SkCoincidentSpans* head, const SkCoincidentSpans* opt, + const char* id, SkPathOpsDebug::GlitchLog* log) { + // look for pts inside coincident spans that are not inside the opposite spans + const SkCoincidentSpans* coin = head; + while (coin) { + DebugCheckBetween(coin->coinPtTStart()->span(), coin->coinPtTEnd()->span(), + coin->oppPtTStart()->fT, coin->oppPtTEnd()->fT, coin->oppPtTStart()->segment(), + id, log); + DebugCheckBetween(coin->oppPtTStart()->span(), coin->oppPtTEnd()->span(), + coin->coinPtTStart()->fT, coin->coinPtTEnd()->fT, coin->coinPtTStart()->segment(), + id, log); + coin = coin->next(); + } + DebugCheckOverlapTop(head, opt, id, log); +} +#endif + +void SkOpCoincidence::debugCheckBetween() const { +#if DEBUG_COINCIDENCE + if (fGlobalState->debugCheckHealth()) { + return; + } + DebugCheckBetween(fHead, fTop, nullptr, nullptr); + DebugCheckBetween(fTop, nullptr, nullptr, nullptr); +#endif +} + #if DEBUG_COINCIDENCE_VERBOSE void SkOpCoincidence::debugCheckValid(const char* id, SkPathOpsDebug::GlitchLog* log) const { DebugValidate(fHead, fTop, id, log); diff --git a/src/pathops/SkPathOpsDebug.h b/src/pathops/SkPathOpsDebug.h index f0e384a7e3..0525c41a59 100644 --- a/src/pathops/SkPathOpsDebug.h +++ b/src/pathops/SkPathOpsDebug.h @@ -77,7 +77,7 @@ #define DEBUG_ALIGNMENT 0 #define DEBUG_ANGLE 1 #define DEBUG_ASSEMBLE 1 -#define DEBUG_COINCIDENCE 1 +#define DEBUG_COINCIDENCE 01 #define DEBUG_COINCIDENCE_ORDER 0 // tight arc quads may generate out-of-order coincdence spans #define DEBUG_COINCIDENCE_VERBOSE 0 #define DEBUG_CUBIC_BINARY_SEARCH 0 diff --git a/src/pathops/SkPathOpsTSect.h b/src/pathops/SkPathOpsTSect.h index f84aaaa6b7..a04a4e442f 100644 --- a/src/pathops/SkPathOpsTSect.h +++ b/src/pathops/SkPathOpsTSect.h @@ -31,29 +31,29 @@ public: #ifdef SK_DEBUG this->fPerpPt.fX = this->fPerpPt.fY = SK_ScalarNaN; this->fPerpT = SK_ScalarNaN; - this->fCoincident = 0xFF; + this->fMatch = 0xFF; #endif } char dumpIsCoincidentStr() const; void dump() const; - bool isCoincident() const { - SkASSERT(!!fCoincident == fCoincident); - return SkToBool(fCoincident); + bool isMatch() const { + SkASSERT(!!fMatch == fMatch); + return SkToBool(fMatch); } void init() { fPerpT = -1; - fCoincident = false; + fMatch = false; fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN; } void markCoincident() { - if (!fCoincident) { + if (!fMatch) { fPerpT = -1; } - fCoincident = true; + fMatch = true; } const SkDPoint& perpPt() const { @@ -69,7 +69,7 @@ public: private: SkDPoint fPerpPt; double fPerpT; // perpendicular intersection on opposite curve - SkOpDebugBool fCoincident; + SkOpDebugBool fMatch; }; template class SkTSect; @@ -330,6 +330,8 @@ private: SkTSpan* fCoincident; SkTSpan* fDeleted; int fActiveCount; + bool fRemovedStartT; + bool fRemovedEndT; SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState); SkDEBUGCODE(SkTSect* fOppSect); PATH_OPS_DEBUG_T_SECT_CODE(int fID); @@ -372,9 +374,9 @@ void SkTCoincident::setPerp(const TCurve& c1, double t, t, cPt.fX, cPt.fY, cPt.approximatelyEqual(fPerpPt) ? "==" : "!=", fPerpT, fPerpPt.fX, fPerpPt.fY); #endif - fCoincident = cPt.approximatelyEqual(fPerpPt); + fMatch = cPt.approximatelyEqual(fPerpPt); #if DEBUG_T_SECT - if (fCoincident) { + if (fMatch) { SkDebugf(""); // allow setting breakpoint } #endif @@ -801,11 +803,11 @@ void SkTSpan::validate() const { SkASSERT(fStartT <= fEndT); SkASSERT(fBounded || fCollapsed == 0xFF); if (fHasPerp) { - if (fCoinStart.isCoincident()) { + if (fCoinStart.isMatch()) { validatePerpT(fCoinStart.perpT()); validatePerpPt(fCoinStart.perpT(), fCoinStart.perpPt()); } - if (fCoinEnd.isCoincident()) { + if (fCoinEnd.isMatch()) { validatePerpT(fCoinEnd.perpT()); validatePerpPt(fCoinEnd.perpT(), fCoinEnd.perpPt()); } @@ -926,7 +928,7 @@ bool SkTSect::binarySearchCoin(SkTSect* sect } last = work.fPart[0]; work.fCoinStart.setPerp(fCurve, work.fStartT, last, opp); - if (work.fCoinStart.isCoincident()) { + if (work.fCoinStart.isMatch()) { #if DEBUG_T_SECT work.validatePerpPt(work.fCoinStart.perpT(), work.fCoinStart.perpPt()); #endif @@ -1083,7 +1085,7 @@ void SkTSect::computePerpendiculars(SkTSect* } else { work->fCoinStart.setPerp(fCurve, work->fStartT, work->fPart[0], opp); } - if (work->fCoinStart.isCoincident()) { + if (work->fCoinStart.isMatch()) { double perpT = work->fCoinStart.perpT(); if (sect2->coincidentHasT(perpT)) { work->fCoinStart.init(); @@ -1092,7 +1094,7 @@ void SkTSect::computePerpendiculars(SkTSect* } } work->fCoinEnd.setPerp(fCurve, work->fEndT, work->fPart[TCurve::kPointLast], opp); - if (work->fCoinEnd.isCoincident()) { + if (work->fCoinEnd.isMatch()) { double perpT = work->fCoinEnd.perpT(); if (sect2->coincidentHasT(perpT)) { work->fCoinEnd.init(); @@ -1175,9 +1177,9 @@ bool SkTSect::extractCoincident( double oppStartT SK_INIT_TO_AVOID_WARNING; double oppEndT SK_INIT_TO_AVOID_WARNING; SkTSpan* prev = first->fPrev; - SkASSERT(first->fCoinStart.isCoincident()); + SkASSERT(first->fCoinStart.isMatch()); SkTSpan* oppFirst = first->findOppT(first->fCoinStart.perpT()); - SkOPASSERT(last->fCoinEnd.isCoincident()); + SkOPASSERT(last->fCoinEnd.isMatch()); bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT(); double coinStart; SkDEBUGCODE(double coinEnd); @@ -1208,7 +1210,7 @@ bool SkTSect::extractCoincident( } // FIXME: incomplete : if we're not at the end, find end of coin SkTSpan* oppLast; - SkOPASSERT(last->fCoinEnd.isCoincident()); + SkOPASSERT(last->fCoinEnd.isMatch()); oppLast = last->findOppT(last->fCoinEnd.perpT()); SkDEBUGCODE(coinEnd = last->fEndT); #ifdef SK_DEBUG @@ -1279,13 +1281,13 @@ SkTSpan* SkTSect::findCoincidentRun( first = nullptr; // find the first fully coincident span do { - if (work->fCoinStart.isCoincident()) { + if (work->fCoinStart.isMatch()) { #if DEBUG_T_SECT work->validatePerpT(work->fCoinStart.perpT()); work->validatePerpPt(work->fCoinStart.perpT(), work->fCoinStart.perpPt()); #endif SkASSERT(work->hasOppT(work->fCoinStart.perpT())); - if (!work->fCoinEnd.isCoincident()) { + if (!work->fCoinEnd.isMatch()) { break; } lastCandidate = work; @@ -1532,7 +1534,7 @@ int SkTSect::linesIntersect(SkTSpan* span, workPt = fCurve.ptAtT(workT); coinW.setPerp(fCurve, workT, workPt, opp->fCurve); double perpT = coinW.perpT(); - if (coinW.isCoincident() ? !between(oppSpan->fStartT, perpT, oppSpan->fEndT) : perpT < 0) { + if (coinW.isMatch() ? !between(oppSpan->fStartT, perpT, oppSpan->fEndT) : perpT < 0) { continue; } SkDVector perpW = workPt - coinW.perpPt(); @@ -1628,7 +1630,7 @@ void SkTSect::mergeCoincidence(SkTSect* sect SkDPoint midPt = fCurve.ptAtT(midT); SkTCoincident coin; coin.setPerp(fCurve, midT, midPt, sect2->fCurve); - if (coin.isCoincident()) { + if (coin.isMatch()) { smaller->fEndT = larger->fEndT; smaller->fCoinEnd = larger->fCoinEnd; if (largerPrior) { @@ -1728,6 +1730,12 @@ void SkTSect::removeCoincident(SkTSpan* span template bool SkTSect::removeSpan(SkTSpan* span) { + if (!span->fStartT) { + fRemovedStartT = true; + } + if (1 == span->fEndT) { + fRemovedEndT = true; + } this->unlinkSpan(span); return this->markSpanGone(span); } @@ -2126,6 +2134,8 @@ void SkTSect::BinarySearch(SkTSect* sect1, break; } SkTSpan* largest2 = sect2->boundsMax(); + sect1->fRemovedStartT = sect1->fRemovedEndT = false; + sect2->fRemovedStartT = sect2->fRemovedEndT = false; // split it if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsMax || (!largest1->fCollapsed && largest2->fCollapsed)))) { @@ -2214,10 +2224,10 @@ void SkTSect::BinarySearch(SkTSect* sect1, } SkASSERT(sect2->fCoincident); // courtesy check : coincidence only looks at sect 1 do { - if (!coincident->fCoinStart.isCoincident()) { + if (!coincident->fCoinStart.isMatch()) { continue; } - if (!coincident->fCoinEnd.isCoincident()) { + if (!coincident->fCoinEnd.isMatch()) { continue; } int index = intersections->insertCoincident(coincident->fStartT, @@ -2231,6 +2241,35 @@ void SkTSect::BinarySearch(SkTSect* sect1, } int zeroOneSet = EndsEqual(sect1, sect2, intersections); if (!sect1->fHead || !sect2->fHead) { + // if the final iteration contains an end (0 or 1), + if (sect1->fRemovedStartT && !(zeroOneSet & kZeroS1Set)) { + SkTCoincident perp; // intersect perpendicular with opposite curve + perp.setPerp(sect1->fCurve, 0, sect1->fCurve.fPts[0], sect2->fCurve); + if (perp.isMatch()) { + intersections->insert(0, perp.perpT(), perp.perpPt()); + } + } + if (sect1->fRemovedEndT && !(zeroOneSet & kOneS1Set)) { + SkTCoincident perp; + perp.setPerp(sect1->fCurve, 1, sect1->fCurve.fPts[TCurve::kPointLast], sect2->fCurve); + if (perp.isMatch()) { + intersections->insert(1, perp.perpT(), perp.perpPt()); + } + } + if (sect2->fRemovedStartT && !(zeroOneSet & kZeroS2Set)) { + SkTCoincident perp; + perp.setPerp(sect2->fCurve, 0, sect2->fCurve.fPts[0], sect1->fCurve); + if (perp.isMatch()) { + intersections->insert(perp.perpT(), 0, perp.perpPt()); + } + } + if (sect2->fRemovedEndT && !(zeroOneSet & kOneS2Set)) { + SkTCoincident perp; + perp.setPerp(sect2->fCurve, 1, sect2->fCurve.fPts[OppCurve::kPointLast], sect1->fCurve); + if (perp.isMatch()) { + intersections->insert(perp.perpT(), 1, perp.perpPt()); + } + } return; } sect1->recoverCollapsed(); @@ -2279,7 +2318,7 @@ void SkTSect::BinarySearch(SkTSect* sect1, } SkClosestSect closest; do { - while (result1 && result1->fCoinStart.isCoincident() && result1->fCoinEnd.isCoincident()) { + while (result1 && result1->fCoinStart.isMatch() && result1->fCoinEnd.isMatch()) { result1 = result1->fNext; } if (!result1) { @@ -2305,7 +2344,7 @@ void SkTSect::BinarySearch(SkTSect* sect1, // intersect perpendicular with opposite curve SkTCoincident perp; perp.setPerp(sect1->fCurve, midT, midPt, sect2->fCurve); - if (!perp.isCoincident()) { + if (!perp.isMatch()) { ++index; continue; } diff --git a/tests/PathOpsConicQuadIntersectionTest.cpp b/tests/PathOpsConicQuadIntersectionTest.cpp new file mode 100644 index 0000000000..5996cf804c --- /dev/null +++ b/tests/PathOpsConicQuadIntersectionTest.cpp @@ -0,0 +1,69 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "PathOpsTestCommon.h" +#include "SkIntersections.h" +#include "SkPathOpsConic.h" +#include "SkPathOpsQuad.h" +#include "SkReduceOrder.h" +#include "Test.h" + +static struct conicQuad { + SkDConic conic; + SkDQuad quad; +} conicQuadTests[] = { + {{{{{494.348663,224.583771}, {494.365143,224.633194}, {494.376404,224.684067}}}, 0.998645842f}, + {{{494.30481,224.474213}, {494.334961,224.538284}, {494.355774,224.605927}}}}, + + {{{{{494.348663,224.583771}, {494.365143,224.633194}, {494.376404,224.684067}}}, 0.998645842f}, + {{{494.355774f, 224.605927f}, {494.363708f, 224.631714f}, {494.370148f, 224.657471f}}}}, +}; + +static const int conicQuadTests_count = (int) SK_ARRAY_COUNT(conicQuadTests); + +static void conicQuadIntersection(skiatest::Reporter* reporter, int index) { + const SkDConic& conic = conicQuadTests[index].conic; + SkASSERT(ValidConic(conic)); + const SkDQuad& quad = conicQuadTests[index].quad; + SkASSERT(ValidQuad(quad)); + SkReduceOrder reduce1; + SkReduceOrder reduce2; + int order1 = reduce2.reduce(conic.fPts); + int order2 = reduce1.reduce(quad); + if (order2 != 3) { + SkDebugf("[%d] conic order=%d\n", index, order1); + REPORTER_ASSERT(reporter, 0); + } + if (order1 != 3) { + SkDebugf("[%d] quad order=%d\n", index, order2); + REPORTER_ASSERT(reporter, 0); + } + SkIntersections i; + int roots = i.intersect(conic, quad); + for (int pt = 0; pt < roots; ++pt) { + double tt1 = i[0][pt]; + SkDPoint xy1 = conic.ptAtT(tt1); + double tt2 = i[1][pt]; + SkDPoint xy2 = quad.ptAtT(tt2); + if (!xy1.approximatelyEqual(xy2)) { + SkDebugf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n", + __FUNCTION__, index, pt, tt1, xy1.fX, xy1.fY, tt2, xy2.fX, xy2.fY); + } + REPORTER_ASSERT(reporter, xy1.approximatelyEqual(xy2)); + } + reporter->bumpTestCount(); +} + +DEF_TEST(PathOpsConicQuadIntersection, reporter) { + for (int index = 0; index < conicQuadTests_count; ++index) { + conicQuadIntersection(reporter, index); + reporter->bumpTestCount(); + } +} + +DEF_TEST(PathOpsConicQuadIntersectionOneOff, reporter) { + conicQuadIntersection(reporter, 1); +} diff --git a/tests/PathOpsCubicIntersectionTest.cpp b/tests/PathOpsCubicIntersectionTest.cpp index 9bf60b7e39..07852bca9a 100644 --- a/tests/PathOpsCubicIntersectionTest.cpp +++ b/tests/PathOpsCubicIntersectionTest.cpp @@ -404,10 +404,10 @@ static void oneOff(skiatest::Reporter* reporter, const SkDCubic& cubic1, const S SkDebugf("sect%d,\n", index); } #endif - if (coin && intersections.used() != 2) { + if (coin && intersections.used() < 2) { SkDebugf(""); } - REPORTER_ASSERT(reporter, !coin || intersections.used() == 2); + REPORTER_ASSERT(reporter, !coin || intersections.used() >= 2); double tt1, tt2; SkDPoint xy1, xy2; for (int pt3 = 0; pt3 < intersections.used(); ++pt3) { diff --git a/tests/PathOpsSimplifyTest.cpp b/tests/PathOpsSimplifyTest.cpp index 55f0447bae..2e469854fa 100644 --- a/tests/PathOpsSimplifyTest.cpp +++ b/tests/PathOpsSimplifyTest.cpp @@ -5331,7 +5331,7 @@ static void tiger8b_h_1(skiatest::Reporter* reporter, const char* filename) { #if DEBUG_UNDER_DEVELOPMENT // tiger return; #endif - uint64_t testlines = 0x000000201304b4a3; // best so far: 0x000000201304b4a3 + uint64_t testlines = 0x000000000f27b9e3; // best so far: 0x000000201304b4a3 tiger8b_x(reporter, filename, testlines); } @@ -5870,7 +5870,7 @@ static void testQuads73(skiatest::Reporter* reporter, const char* filename) { } static void (*skipTest)(skiatest::Reporter* , const char* filename) = 0; -static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0; +static void (*firstTest)(skiatest::Reporter* , const char* filename) = tiger8b_h_1; static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0; static TestDesc tests[] = { diff --git a/tests/PathOpsTSectDebug.h b/tests/PathOpsTSectDebug.h index 4e04db794b..e18e0f89e6 100644 --- a/tests/PathOpsTSectDebug.h +++ b/tests/PathOpsTSectDebug.h @@ -9,16 +9,16 @@ template char SkTCoincident::dumpIsCoincidentStr() const { - if (!!fCoincident != fCoincident) { + if (!!fMatch != fMatch) { return '?'; } - return fCoincident ? '*' : 0; + return fMatch ? '*' : 0; } template void SkTCoincident::dump() const { SkDebugf("t=%1.9g pt=(%1.9g,%1.9g)%s\n", fPerpT, fPerpPt.fX, fPerpPt.fY, - fCoincident ? " coincident" : ""); + fMatch ? " match" : ""); } template diff --git a/tools/pathops_sorter.htm b/tools/pathops_sorter.htm index 0983b704dc..d2d90da8bc 100644 --- a/tools/pathops_sorter.htm +++ b/tools/pathops_sorter.htm @@ -6,42 +6,17 @@
-
-{{{130.0427549999999997, 11417.41309999999976}, {130.2331240000000037, 11418.3192999999992}, {131.0370790000000056, 11419}, {132, 11419}}}, -{{{132, 11419}, {130.8954319999999996, 11419}, {130, 11418.10449999999946}, {130, 11417}}}, +
+{{{317, 711}, {322.522857666015625, 711}, {327, 715.4771728515625}, {327, 721}}}, +{{{324.071075439453125, 713.928955078125}, {324.4051513671875, 714.26300048828125}, {324.715667724609375, 714.62060546875}, {325, 714.9990234375}}},
-
-{{{-0.001019871095195412636, -0.008523519150912761688}, {-0.005396408028900623322, -0.005396373569965362549}, {-0.02855382487177848816, -0.02855364233255386353}}}, -{{{-0.004567248281091451645, -0.01482933573424816132}, {-0.01142475008964538574, -0.01140109263360500336}, {-0.02852955088019371033, -0.02847047336399555206}}}, -
- -
-{{fX=0.000000000 fY=0.000000000 }, {fX=494.350159 fY=228.773712 }, {fX=493.191650 fY=226.887451 }} -{{fX=0.000000000 fY=0.000000000 } {fX=492.680206 fY=228.000900 } {fX=493.193817 fY=226.897568 } -{{fX=493.193817 fY=226.897568 } {fX=493.195557 fY=226.893829 } {fX=493.191650 fY=226.887451 } -
- -
-{{fX=0.000000000 fY=0.000000000 }, {fX=494.350159 fY=228.773712 }, {fX=493.191650 fY=226.887451 }} -{{fX=0.000000000 fY=0.000000000 }, {fX=494.350159 fY=228.773712 }, {fX=493.191650 fY=226.887451 }} -
- -
-{{fX=0.000000000 fY=0.000000000 } {fX=492.680206 fY=228.000900 } {fX=493.193817 fY=226.897568 } -{{fX=493.193817 fY=226.897568 } {fX=493.195557 fY=226.893829 } {fX=493.191650 fY=226.887451 } -
-