| Index: src/pathops/SkPathOpsDebug.cpp
|
| diff --git a/src/pathops/SkPathOpsDebug.cpp b/src/pathops/SkPathOpsDebug.cpp
|
| index 212e2bcc79637246eb754a68c8e8218e09931e91..d099c4a985093952fd4af10f00993264f43b88cc 100644
|
| --- a/src/pathops/SkPathOpsDebug.cpp
|
| +++ b/src/pathops/SkPathOpsDebug.cpp
|
| @@ -12,6 +12,18 @@
|
| #include "SkPathOpsDebug.h"
|
| #include "SkString.h"
|
|
|
| +#undef FAIL_IF
|
| +#define FAIL_IF(cond, coin) \
|
| + do { if (cond) log->record(kAddExpandedFail_Glitch, id, coin); } while (false)
|
| +
|
| +#undef FAIL_WITH_NULL_IF
|
| +#define FAIL_WITH_NULL_IF(cond, span) \
|
| + do { if (cond) log->record(kAddExpandedFail_Glitch, id, span); } while (false)
|
| +
|
| +#undef RETURN_FALSE_IF
|
| +#define RETURN_FALSE_IF(cond, span) \
|
| + do { if (cond) log->record(kAddExpandedFail_Glitch, id, span); } while (false)
|
| +
|
| class SkCoincidentSpans;
|
|
|
| #if DEBUG_VALIDATE
|
| @@ -67,6 +79,7 @@ enum GlitchType {
|
| kMarkCoinMissing_Glitch,
|
| kMarkCoinStart_Glitch,
|
| kMergeContained_Glitch,
|
| + kMergeMatches_Glitch,
|
| kMissingCoin_Glitch,
|
| kMissingDone_Glitch,
|
| kMissingIntersection_Glitch,
|
| @@ -331,6 +344,7 @@ void SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList, const char* id) {
|
| case kMarkCoinMissing_Glitch: SkDebugf(" MarkCoinMissing"); break;
|
| case kMarkCoinStart_Glitch: SkDebugf(" MarkCoinStart"); break;
|
| case kMergeContained_Glitch: SkDebugf(" MergeContained"); break;
|
| + case kMergeMatches_Glitch: SkDebugf(" MergeMatches"); break;
|
| case kMissingCoin_Glitch: SkDebugf(" MissingCoin"); break;
|
| case kMissingDone_Glitch: SkDebugf(" MissingDone"); break;
|
| case kMissingIntersection_Glitch: SkDebugf(" MissingIntersection"); break;
|
| @@ -580,9 +594,9 @@ void SkDRect::debugInit() {
|
| #include "SkOpAngle.h"
|
| #include "SkOpSegment.h"
|
|
|
| -#if DEBUG_COINCIDENCE
|
| +#if DEBUG_COINCIDENCE_VERBOSE
|
| // commented-out lines keep this in sync with addT()
|
| - const SkOpPtT* SkOpSegment::debugAddT(double t) const {
|
| + const SkOpPtT* SkOpSegment::debugAddT(double t, const char* id, SkPathOpsDebug::GlitchLog* log) const {
|
| debugValidate();
|
| SkPoint pt = this->ptAtT(t);
|
| const SkOpSpanBase* span = &fHead;
|
| @@ -594,7 +608,7 @@ void SkDRect::debugInit() {
|
| }
|
| if (t < result->fT) {
|
| const SkOpSpan* prev = result->span()->prev();
|
| - FAIL_WITH_NULL_IF(!prev);
|
| + FAIL_WITH_NULL_IF(!prev, span);
|
| // marks in global state that new op span has been allocated
|
| this->globalState()->setAllocatedOpSpan();
|
| // span->init(this, prev, t, pt);
|
| @@ -606,7 +620,7 @@ void SkDRect::debugInit() {
|
| // span->bumpSpanAdds();
|
| return nullptr;
|
| }
|
| - FAIL_WITH_NULL_IF(span != &fTail);
|
| + FAIL_WITH_NULL_IF(span != &fTail, span);
|
| } while ((span = span->upCast()->next()));
|
| SkASSERT(0);
|
| return nullptr; // we never get here, but need this to satisfy compiler
|
| @@ -776,7 +790,7 @@ void SkOpSegment::debugMissingCoincidence(const char* id, SkPathOpsDebug::Glitch
|
| }
|
| if (testForCoincidence(rootPriorPtT, rootPtT, prior, spanBase, opp)) {
|
| // mark coincidence
|
| -#if DEBUG_COINCIDENCE
|
| +#if DEBUG_COINCIDENCE_VERBOSE
|
| // SkDebugf("%s coinSpan=%d endSpan=%d oppSpan=%d oppEndSpan=%d\n", __FUNCTION__,
|
| // rootPriorPtT->debugID(), rootPtT->debugID(), rootOppStart->debugID(),
|
| // rootOppEnd->debugID());
|
| @@ -879,13 +893,8 @@ void SkOpSegment::debugMoveMultiples(const char* id, SkPathOpsDebug::GlitchLog*
|
| goto tryNextSpan;
|
| foundMatch: // merge oppTest and oppSpan
|
| oppSegment->debugValidate();
|
| - if (oppTest == &oppSegment->fTail || oppTest == &oppSegment->fHead) {
|
| - SkASSERT(oppSpan != &oppSegment->fHead); // don't expect collapse
|
| - SkASSERT(oppSpan != &oppSegment->fTail);
|
| - glitches->record(kMoveMultiple_Glitch, id, oppTest, oppSpan);
|
| - } else {
|
| - glitches->record(kMoveMultiple_Glitch, id, oppSpan, oppTest);
|
| - }
|
| + oppTest->debugMergeMatches(id, glitches, oppSpan);
|
| + oppTest->debugAddOpp(id, glitches, oppSpan);
|
| oppSegment->debugValidate();
|
| goto checkNextSpan;
|
| }
|
| @@ -1254,6 +1263,7 @@ void SkCoincidentSpans::debugStartCheck(const SkOpSpanBase* outer, const SkOpSpa
|
|
|
| #if DEBUG_COINCIDENCE_VERBOSE
|
| /* Commented-out lines keep this in sync with expand */
|
| +// expand the range by checking adjacent spans for coincidence
|
| bool SkCoincidentSpans::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* log) const {
|
| bool expanded = false;
|
| const SkOpSegment* segment = coinPtTStart()->segment();
|
| @@ -1275,6 +1285,9 @@ bool SkCoincidentSpans::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* l
|
| do {
|
| const SkOpSpanBase* end = coinPtTEnd()->span();
|
| SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next();
|
| + if (next && next->deleted()) {
|
| + break;
|
| + }
|
| const SkOpPtT* oppPtT;
|
| if (!next || !(oppPtT = next->contains(oppSegment))) {
|
| break;
|
| @@ -1289,9 +1302,6 @@ bool SkCoincidentSpans::debugExpand(const char* id, SkPathOpsDebug::GlitchLog* l
|
| return expanded;
|
| }
|
|
|
| -#undef FAIL_IF
|
| -#define FAIL_IF(cond) do { if (cond) log->record(kAddExpandedFail_Glitch, id, coin); } while (false)
|
| -
|
| /* Commented-out lines keep this in sync with addExpanded */
|
| // for each coincident pair, match the spans
|
| // if the spans don't match, add the mssing pt to the segment and loop it in the opposite span
|
| @@ -1309,7 +1319,8 @@ void SkOpCoincidence::debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog
|
| const SkOpSpanBase* oStart = oStartPtT->span();
|
| const SkOpSpanBase* end = coin->coinPtTEnd()->span();
|
| const SkOpSpanBase* oEnd = coin->oppPtTEnd()->span();
|
| - FAIL_IF(oEnd->deleted());
|
| + FAIL_IF(oEnd->deleted(), coin);
|
| + FAIL_IF(!start->upCastable(), coin);
|
| const SkOpSpanBase* test = start->upCast()->next();
|
| const SkOpSpanBase* oTest = coin->flipped() ? oStart->prev() : oStart->upCast()->next();
|
| if (!oTest) {
|
| @@ -1320,12 +1331,12 @@ void SkOpCoincidence::debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog
|
| || !oTest->ptT()->contains(start->segment())) {
|
| // use t ranges to guess which one is missing
|
| double startRange = coin->coinPtTEnd()->fT - startPtT->fT;
|
| - FAIL_IF(!startRange);
|
| + FAIL_IF(!startRange, coin);
|
| double startPart = (test->t() - startPtT->fT) / startRange;
|
| double oStartRange = coin->oppPtTEnd()->fT - oStartPtT->fT;
|
| - FAIL_IF(!oStartRange);
|
| + FAIL_IF(!oStartRange, coin);
|
| double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange;
|
| - FAIL_IF(startPart == oStartPart);
|
| + FAIL_IF(startPart == oStartPart, coin);
|
| bool startOver = false;
|
| if (startPart < oStartPart)
|
| log->record(kAddExpandedCoin_Glitch, id, // strange debug formatting lines up with original
|
| @@ -1342,6 +1353,9 @@ void SkOpCoincidence::debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog
|
| }
|
| }
|
| if (test != end) {
|
| + if (!test->upCastable()) {
|
| + return;
|
| + }
|
| test = test->upCast()->next();
|
| }
|
| if (oTest != oEnd) {
|
| @@ -1393,12 +1407,15 @@ void SkOpCoincidence::debugAddIfMissing(const SkOpPtT* over1s, const SkOpPtT* ov
|
| if (coinSeg == oppSeg) {
|
| return;
|
| }
|
| - return this->debugAddOrOverlap(coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, id, log);
|
| + return this->debugAddOrOverlap(id, log, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe);
|
| }
|
|
|
| /* Commented-out lines keep this in sync addOrOverlap() */
|
| -void SkOpCoincidence::debugAddOrOverlap(const SkOpSegment* coinSeg, const SkOpSegment* oppSeg,
|
| - double coinTs, double coinTe, double oppTs, double oppTe, const char* id, SkPathOpsDebug::GlitchLog* log) const {
|
| +// If this is called by addEndMovedSpans(), a returned false propogates out to an abort.
|
| +// If this is called by AddIfMissing(), a returned false indicates there was nothing to add
|
| +void SkOpCoincidence::debugAddOrOverlap(const char* id, SkPathOpsDebug::GlitchLog* log,
|
| + const SkOpSegment* coinSeg, const SkOpSegment* oppSeg,
|
| + double coinTs, double coinTe, double oppTs, double oppTe) const {
|
| SkTDArray<SkCoincidentSpans*> overlaps;
|
| SkASSERT(!fTop); // this is (correctly) reversed in addifMissing()
|
| if (fTop && !this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &overlaps)) {
|
| @@ -1427,77 +1444,63 @@ void SkOpCoincidence::debugAddOrOverlap(const SkOpSegment* coinSeg, const SkOpSe
|
| : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) {
|
| log->record(kAddOrOverlap_Glitch, id, overlap, test->oppPtTEnd());
|
| }
|
| - if (!fHead) {
|
| - SkAssertResult(true);
|
| + if (!fHead) { this->debugRelease(id, log, fHead, test);
|
| + this->debugRelease(id, log, fTop, test);
|
| }
|
| }
|
| const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg);
|
| const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg);
|
| - if (overlap && cs && ce && overlap->contains(cs, ce)) {
|
| - return;
|
| - }
|
| - SkASSERT(cs != ce || !cs);
|
| + RETURN_FALSE_IF(overlap && cs && ce && overlap->contains(cs, ce), coinSeg);
|
| + RETURN_FALSE_IF(cs != ce || !cs, coinSeg);
|
| const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg);
|
| const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg);
|
| - if (overlap && os && oe && overlap->contains(os, oe)) {
|
| - return;
|
| - }
|
| + RETURN_FALSE_IF(overlap && os && oe && overlap->contains(os, oe), oppSeg);
|
| SkASSERT(true || !cs || !cs->deleted());
|
| SkASSERT(true || !os || !os->deleted());
|
| SkASSERT(true || !ce || !ce->deleted());
|
| SkASSERT(true || !oe || !oe->deleted());
|
| const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullptr;
|
| const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullptr;
|
| - if (csExisting && csExisting == ceExisting) {
|
| - return;
|
| - }
|
| - if (csExisting && (csExisting == ce || csExisting->contains(ceExisting ? ceExisting : ce))) {
|
| - return;
|
| - }
|
| - if (ceExisting && (ceExisting == cs || ceExisting->contains(csExisting ? csExisting : cs))) {
|
| - return;
|
| - }
|
| + RETURN_FALSE_IF(csExisting && csExisting == ceExisting, coinSeg);
|
| + RETURN_FALSE_IF(csExisting && (csExisting == ce ||
|
| + csExisting->contains(ceExisting ? ceExisting : ce)), coinSeg);
|
| + RETURN_FALSE_IF(ceExisting && (ceExisting == cs ||
|
| + ceExisting->contains(csExisting ? csExisting : cs)), coinSeg);
|
| const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr;
|
| const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr;
|
| - if (osExisting && osExisting == oeExisting) {
|
| - return;
|
| - }
|
| - if (osExisting && (osExisting == oe || osExisting->contains(oeExisting ? oeExisting : oe))) {
|
| - return;
|
| - }
|
| - if (oeExisting && (oeExisting == os || oeExisting->contains(osExisting ? osExisting : os))) {
|
| - return;
|
| - }
|
| + RETURN_FALSE_IF(osExisting && osExisting == oeExisting, oppSeg);
|
| + RETURN_FALSE_IF(osExisting && (osExisting == oe ||
|
| + osExisting->contains(oeExisting ? oeExisting : oe)), oppSeg);
|
| + RETURN_FALSE_IF(oeExisting && (oeExisting == os ||
|
| + oeExisting->contains(osExisting ? osExisting : os)), oppSeg);
|
| bool csDeleted = false, osDeleted = false, ceDeleted = false, oeDeleted = false;
|
| this->debugValidate();
|
| if (!cs || !os) {
|
| if (!cs)
|
| - cs = coinSeg->debugAddT(coinTs);
|
| + cs = coinSeg->debugAddT(coinTs, id, log);
|
| if (!os)
|
| - os = oppSeg->debugAddT(oppTs);
|
| - if (cs && os) cs->span()->debugAddOppAndMerge(id, log, os->span(), &csDeleted, &osDeleted);
|
| + os = oppSeg->debugAddT(oppTs, id, log);
|
| +// RETURN_FALSE_IF(callerAborts, !csWritable || !osWritable);
|
| + if (cs && os) cs->span()->debugAddOpp(id, log, os->span());
|
| // cs = csWritable;
|
| -// os = osWritable;
|
| - if ((ce && ce->deleted()) || (oe && oe->deleted())) {
|
| - return;
|
| - }
|
| +// os = osWritable->active();
|
| + RETURN_FALSE_IF((ce && ce->deleted()) || (oe && oe->deleted()), coinSeg);
|
| }
|
| if (!ce || !oe) {
|
| if (!ce)
|
| - ce = coinSeg->debugAddT(coinTe);
|
| + ce = coinSeg->debugAddT(coinTe, id, log);
|
| if (!oe)
|
| - oe = oppSeg->debugAddT(oppTe);
|
| - if (ce && oe) ce->span()->debugAddOppAndMerge(id, log, oe->span(), &ceDeleted, &oeDeleted);
|
| + oe = oppSeg->debugAddT(oppTe, id, log);
|
| + if (ce && oe) ce->span()->debugAddOpp(id, log, oe->span());
|
| // ce = ceWritable;
|
| // oe = oeWritable;
|
| }
|
| this->debugValidate();
|
| - if (csDeleted || osDeleted || ceDeleted || oeDeleted) {
|
| - return;
|
| - }
|
| - if (!cs || !ce || cs->contains(ce) || !os || !oe || os->contains(oe)) {
|
| - return;
|
| - }
|
| + RETURN_FALSE_IF(csDeleted, coinSeg);
|
| + RETURN_FALSE_IF(osDeleted, oppSeg);
|
| + RETURN_FALSE_IF(ceDeleted, coinSeg);
|
| + RETURN_FALSE_IF(oeDeleted, oppSeg);
|
| + RETURN_FALSE_IF(!cs || !ce || cs->contains(ce) || !os || !oe || os->contains(oe), coinSeg);
|
| // bool result = true;
|
| if (overlap) {
|
| if (overlap->coinPtTStart()->segment() == coinSeg) {
|
| @@ -1599,6 +1602,27 @@ void SkOpCoincidence::debugAddMissing(const char* id, SkPathOpsDebug::GlitchLog*
|
| }
|
|
|
| // Commented-out lines keep this in sync with release()
|
| +void SkOpCoincidence::debugRelease(const char* id, SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkCoincidentSpans* remove) const {
|
| + const SkCoincidentSpans* head = coin;
|
| + const SkCoincidentSpans* prev = nullptr;
|
| + const SkCoincidentSpans* next;
|
| + do {
|
| + next = coin->next();
|
| + if (coin == remove) {
|
| + if (prev) {
|
| +// prev->setNext(next);
|
| + } else if (head == fHead) {
|
| +// fHead = next;
|
| + } else {
|
| +// fTop = next;
|
| + }
|
| + log->record(kReleasedSpan_Glitch, id, coin);
|
| + }
|
| + prev = coin;
|
| + } while ((coin = next));
|
| + return;
|
| +}
|
| +
|
| void SkOpCoincidence::debugRelease(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSegment* deleted) const {
|
| const SkCoincidentSpans* coin = fHead;
|
| if (!coin) {
|
| @@ -1614,6 +1638,7 @@ void SkOpCoincidence::debugRelease(const char* id, SkPathOpsDebug::GlitchLog* lo
|
| } while ((coin = coin->next()));
|
| }
|
|
|
| +
|
| // Commented-out lines keep this in sync with reorder()
|
| // iterate through all coincident pairs, looking for ranges greater than 1
|
| // if found, see if the opposite pair can match it -- which may require
|
| @@ -1626,7 +1651,10 @@ void SkOpCoincidence::debugReorder(const char* id, SkPathOpsDebug::GlitchLog* lo
|
| do {
|
| // most commonly, concidence are one span long; check for that first
|
| int intervals = coin->spanCount();
|
| - if (intervals = 1) {
|
| + if (intervals <= 0) {
|
| + return;
|
| + }
|
| + if (1 == intervals) {
|
| #if DEBUG_COINCIDENCE_VERBOSE
|
| // SkASSERT(!coin->debugExpand(nullptr, nullptr));
|
| #endif
|
| @@ -1709,6 +1737,9 @@ void SkOpCoincidence::debugMark(const char* id, SkPathOpsDebug::GlitchLog* log)
|
| return;
|
| }
|
| do {
|
| + if (!coin->coinPtTStartWritable()->span()->upCastable()) {
|
| + return;
|
| + }
|
| const SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast();
|
| // SkASSERT(start->deleted());
|
| const SkOpSpanBase* end = coin->coinPtTEndWritable()->span();
|
| @@ -1730,11 +1761,17 @@ void SkOpCoincidence::debugMark(const char* id, SkPathOpsDebug::GlitchLog* log)
|
| const SkOpSpanBase* next = start;
|
| const SkOpSpanBase* oNext = oStart;
|
| while ((next = next->upCast()->next()) != end) {
|
| + if (!next->upCastable()) {
|
| + return;
|
| + }
|
| if (next->upCast()->debugInsertCoincidence(id, log, oSegment, flipped), false) {
|
| return;
|
| }
|
| }
|
| while ((oNext = oNext->upCast()->next()) != oEnd) {
|
| + if (!oNext->upCastable()) {
|
| + return;
|
| + }
|
| if (oNext->upCast()->debugInsertCoincidence(id, log, segment, flipped), false) {
|
| return;
|
| }
|
| @@ -1747,6 +1784,7 @@ void SkOpCoincidence::debugMark(const char* id, SkPathOpsDebug::GlitchLog* log)
|
| #if DEBUG_COINCIDENCE_VERBOSE
|
| // Commented-out lines keep this in sync with markCollapsed()
|
| void SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* coin, const SkOpPtT* test) const {
|
| + const SkCoincidentSpans* head = coin;
|
| while (coin) {
|
| if (coin->collapsed(test)) {
|
| if (zero_or_one(coin->coinPtTStart()->fT) && zero_or_one(coin->coinPtTEnd()->fT)) {
|
| @@ -1755,6 +1793,7 @@ void SkOpCoincidence::debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchL
|
| if (zero_or_one(coin->oppPtTStart()->fT) && zero_or_one(coin->oppPtTEnd()->fT)) {
|
| log->record(kCollapsedCoin_Glitch, id, coin);
|
| }
|
| + this->debugRelease(id, log, head, coin);
|
| }
|
| coin = coin->next();
|
| }
|
| @@ -2035,27 +2074,16 @@ void SkOpSegment::debugValidate() const {
|
| }
|
|
|
| #if DEBUG_COINCIDENCE_VERBOSE
|
| -// Commented-out lines keep this in sync with addOppAndMerge()
|
| -// If the added points envelop adjacent spans, merge them in.
|
| -void SkOpSpanBase::debugAddOppAndMerge(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp, bool* spanDeleted, bool* oppDeleted) const {
|
| - const SkOpPtT* oppPrev = this->ptT()->debugOppPrev(opp->ptT());
|
| - if (oppPrev) {
|
| - this->ptT()->debugAddOpp(opp->ptT(), oppPrev);
|
| - this->debugCheckForCollapsedCoincidence(id, log);
|
| - }
|
| - // compute bounds of points in span
|
| - SkPathOpsBounds bounds;
|
| - bounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin);
|
| - const SkOpPtT* head = this->ptT();
|
| - const SkOpPtT* nextPt = head;
|
| - do {
|
| - bounds.add(nextPt->fPt);
|
| - } while ((nextPt = nextPt->next()) != head);
|
| - if (!bounds.width() && !bounds.height()) {
|
| +
|
| +// Commented-out lines keep this in sync with addOpp()
|
| +void SkOpSpanBase::debugAddOpp(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp) const {
|
| + const SkOpPtT* oppPrev = this->ptT()->oppPrev(opp->ptT());
|
| + if (!oppPrev) {
|
| return;
|
| }
|
| - this->debugMergeContained(id, log, bounds, spanDeleted);
|
| - opp->debugMergeContained(id, log, bounds, oppDeleted);
|
| + this->debugMergeMatches(id, log, opp);
|
| + this->ptT()->debugAddOpp(opp->ptT(), oppPrev);
|
| + this->debugCheckForCollapsedCoincidence(id, log);
|
| }
|
|
|
| // Commented-out lines keep this in sync with checkForCollapsedCoincidence()
|
| @@ -2151,6 +2179,76 @@ void SkOpSpanBase::debugMergeContained(const char* id, SkPathOpsDebug::GlitchLog
|
| // this->globalState()->coincidence()->debugValidate();
|
| #endif
|
| }
|
| +
|
| +// Commented-out lines keep this in sync with mergeMatches()
|
| +// Look to see if pt-t linked list contains same segment more than once
|
| +// if so, and if each pt-t is directly pointed to by spans in that segment,
|
| +// merge them
|
| +// keep the points, but remove spans so that the segment doesn't have 2 or more
|
| +// spans pointing to the same pt-t loop at different loop elements
|
| +void SkOpSpanBase::debugMergeMatches(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpSpanBase* opp) const {
|
| + const SkOpPtT* test = &fPtT;
|
| + const SkOpPtT* testNext;
|
| + const SkOpPtT* stop = test;
|
| + do {
|
| + testNext = test->next();
|
| + if (test->deleted()) {
|
| + continue;
|
| + }
|
| + const SkOpSpanBase* testBase = test->span();
|
| + SkASSERT(testBase->ptT() == test);
|
| + const SkOpSegment* segment = test->segment();
|
| + if (segment->done()) {
|
| + continue;
|
| + }
|
| + const SkOpPtT* inner = opp->ptT();
|
| + const SkOpPtT* innerStop = inner;
|
| + do {
|
| + if (inner->segment() != segment) {
|
| + continue;
|
| + }
|
| + if (inner->deleted()) {
|
| + continue;
|
| + }
|
| + const SkOpSpanBase* innerBase = inner->span();
|
| + SkASSERT(innerBase->ptT() == inner);
|
| + // when the intersection is first detected, the span base is marked if there are
|
| + // more than one point in the intersection.
|
| +// if (!innerBase->hasMultipleHint() && !testBase->hasMultipleHint()) {
|
| + if (!zero_or_one(inner->fT)) {
|
| + log->record(kMergeMatches_Glitch, id, innerBase, test);
|
| + } else {
|
| + SkASSERT(inner->fT != test->fT);
|
| + if (!zero_or_one(test->fT)) {
|
| + log->record(kMergeMatches_Glitch, id, testBase, inner);
|
| + } else {
|
| + log->record(kMergeMatches_Glitch, id, segment);
|
| +// SkDEBUGCODE(testBase->debugSetDeleted());
|
| +// test->setDeleted();
|
| +// SkDEBUGCODE(innerBase->debugSetDeleted());
|
| +// inner->setDeleted();
|
| + }
|
| + }
|
| +#ifdef SK_DEBUG // assert if another undeleted entry points to segment
|
| + const SkOpPtT* debugInner = inner;
|
| + while ((debugInner = debugInner->next()) != innerStop) {
|
| + if (debugInner->segment() != segment) {
|
| + continue;
|
| + }
|
| + if (debugInner->deleted()) {
|
| + continue;
|
| + }
|
| + SkOPASSERT(0);
|
| + }
|
| +#endif
|
| + break;
|
| +// }
|
| + break;
|
| + } while ((inner = inner->next()) != innerStop);
|
| + } while ((test = testNext) != stop);
|
| + this->debugCheckForCollapsedCoincidence(id, log);
|
| +}
|
| +
|
| #endif
|
|
|
| void SkOpSpanBase::debugResetCoinT() const {
|
|
|