| Index: src/pathops/SkPathOpsDebug.cpp
|
| diff --git a/src/pathops/SkPathOpsDebug.cpp b/src/pathops/SkPathOpsDebug.cpp
|
| index d099c4a985093952fd4af10f00993264f43b88cc..b5b42c40e7d90301df8fed284b4cd2fdbcb94a58 100644
|
| --- a/src/pathops/SkPathOpsDebug.cpp
|
| +++ b/src/pathops/SkPathOpsDebug.cpp
|
| @@ -63,6 +63,7 @@ enum GlitchType {
|
| kAddCorruptCoin_Glitch,
|
| kAddExpandedCoin_Glitch,
|
| kAddExpandedFail_Glitch,
|
| + kAddIfCollapsed_Glitch,
|
| kAddIfMissingCoin_Glitch,
|
| kAddMissingCoin_Glitch,
|
| kAddMissingExtend_Glitch,
|
| @@ -286,22 +287,26 @@ void SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList, const char* id) {
|
| const SpanGlitch& glitch = glitches.fGlitches[index];
|
| SkDebugf("%02d: ", index);
|
| if (glitch.fBase) {
|
| - SkDebugf(" base=%d", glitch.fBase->debugID());
|
| + SkDebugf(" seg/base=%d/%d", glitch.fBase->segment()->debugID(),
|
| + glitch.fBase->debugID());
|
| }
|
| if (glitch.fSuspect) {
|
| - SkDebugf(" base=%d", glitch.fSuspect->debugID());
|
| + SkDebugf(" seg/base=%d/%d", glitch.fSuspect->segment()->debugID(),
|
| + glitch.fSuspect->debugID());
|
| }
|
| if (glitch.fSegment) {
|
| SkDebugf(" segment=%d", glitch.fSegment->debugID());
|
| }
|
| if (glitch.fCoinSpan) {
|
| - SkDebugf(" coinSpan=%d", glitch.fCoinSpan->debugID());
|
| + SkDebugf(" coinSeg/Span/PtT=%d/%d/%d", glitch.fCoinSpan->segment()->debugID(),
|
| + glitch.fCoinSpan->span()->debugID(), glitch.fCoinSpan->debugID());
|
| }
|
| if (glitch.fEndSpan) {
|
| SkDebugf(" endSpan=%d", glitch.fEndSpan->debugID());
|
| }
|
| if (glitch.fOppSpan) {
|
| - SkDebugf(" oppSpan=%d", glitch.fOppSpan->debugID());
|
| + SkDebugf(" oppSeg/Span/PtT=%d/%d/%d", glitch.fOppSpan->segment()->debugID(),
|
| + glitch.fOppSpan->span()->debugID(), glitch.fOppSpan->debugID());
|
| }
|
| if (glitch.fOppEndSpan) {
|
| SkDebugf(" oppEndSpan=%d", glitch.fOppEndSpan->debugID());
|
| @@ -328,6 +333,7 @@ void SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList, const char* id) {
|
| case kAddCorruptCoin_Glitch: SkDebugf(" AddCorruptCoin"); break;
|
| case kAddExpandedCoin_Glitch: SkDebugf(" AddExpandedCoin"); break;
|
| case kAddExpandedFail_Glitch: SkDebugf(" AddExpandedFail"); break;
|
| + case kAddIfCollapsed_Glitch: SkDebugf(" AddIfCollapsed"); break;; break;
|
| case kAddIfMissingCoin_Glitch: SkDebugf(" AddIfMissingCoin"); break;
|
| case kAddMissingCoin_Glitch: SkDebugf(" AddMissingCoin"); break;
|
| case kAddMissingExtend_Glitch: SkDebugf(" AddMissingExtend"); break;
|
| @@ -364,7 +370,7 @@ void SkPathOpsDebug::CheckHealth(SkOpContourHead* contourList, const char* id) {
|
| SkDebugf("\n");
|
| }
|
| contourList->globalState()->debugSetCheckHealth(false);
|
| -#if DEBUG_ACTIVE_SPANS
|
| +#if 0 && DEBUG_ACTIVE_SPANS
|
| SkDebugf("active after %s:\n", id);
|
| ShowActiveSpans(contourList);
|
| #endif
|
| @@ -1370,8 +1376,8 @@ void SkOpCoincidence::debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog
|
| }
|
|
|
| /* Commented-out lines keep this in sync with addIfMissing() */
|
| -void SkOpCoincidence::debugAddIfMissing(const SkCoincidentSpans* outer, const SkOpPtT* over1s,
|
| - const SkOpPtT* over1e, const char* id, SkPathOpsDebug::GlitchLog* log) const {
|
| +void SkOpCoincidence::debugAddIfMissing(const char* id, SkPathOpsDebug::GlitchLog* log, const SkCoincidentSpans* outer, const SkOpPtT* over1s,
|
| + const SkOpPtT* over1e) const {
|
| // SkASSERT(fTop);
|
| if (fTop && alreadyAdded(fTop, outer, over1s, over1e)) { // in debug, fTop may be null
|
| return;
|
| @@ -1385,29 +1391,40 @@ void SkOpCoincidence::debugAddIfMissing(const SkCoincidentSpans* outer, const Sk
|
| }
|
|
|
| /* Commented-out lines keep this in sync addIfMissing() */
|
| -void SkOpCoincidence::debugAddIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e,
|
| - const SkOpPtT* over2s, const SkOpPtT* over2e, double tStart, double tEnd,
|
| - const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd,
|
| - const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, const char* id, SkPathOpsDebug::GlitchLog* log) const {
|
| +// note that over1s, over1e, over2s, over2e are ordered
|
| +void SkOpCoincidence::debugAddIfMissing(const char* id, SkPathOpsDebug::GlitchLog* log, const SkOpPtT* over1s, const SkOpPtT* over2s,
|
| + double tStart, double tEnd, const SkOpSegment* coinSeg, const SkOpSegment* oppSeg,
|
| + const SkOpPtT* over1e, const SkOpPtT* over2e) const {
|
| + SkASSERT(tStart < tEnd);
|
| + SkASSERT(over1s->fT < over1e->fT);
|
| + SkASSERT(between(over1s->fT, tStart, over1e->fT));
|
| + SkASSERT(between(over1s->fT, tEnd, over1e->fT));
|
| + SkASSERT(over2s->fT < over2e->fT);
|
| + SkASSERT(between(over2s->fT, tStart, over2e->fT));
|
| + SkASSERT(between(over2s->fT, tEnd, over2e->fT));
|
| + SkASSERT(over1s->segment() == over1e->segment());
|
| + SkASSERT(over2s->segment() == over2e->segment());
|
| + SkASSERT(over1s->segment() == over2s->segment());
|
| + SkASSERT(over1s->segment() != coinSeg);
|
| + SkASSERT(over1s->segment() != oppSeg);
|
| + SkASSERT(coinSeg != oppSeg);
|
| double coinTs, coinTe, oppTs, oppTe;
|
| - TRange(over1s, over1e, tStart, tEnd, coinPtTStart, coinPtTEnd, &coinTs, &coinTe);
|
| - TRange(over2s, over2e, tStart, tEnd, oppPtTStart, oppPtTEnd, &oppTs, &oppTe);
|
| - bool swap = coinTs > coinTe;
|
| - if (swap) {
|
| - SkTSwap(coinTs, coinTe);
|
| + coinTs = TRange(over1s, tStart, coinSeg SkDEBUGPARAMS(over1e));
|
| + coinTe = TRange(over1s, tEnd, coinSeg SkDEBUGPARAMS(over1e));
|
| + if (coinSeg->collapsed(coinTs, coinTe)) {
|
| + return log->record(kAddIfCollapsed_Glitch, id, coinSeg);
|
| }
|
| - if ((over1s->fT < over1e->fT) != (over2s->fT < over2e->fT)) {
|
| - SkTSwap(oppTs, oppTe);
|
| + oppTs = TRange(over2s, tStart, oppSeg SkDEBUGPARAMS(over2e));
|
| + oppTe = TRange(over2s, tEnd, oppSeg SkDEBUGPARAMS(over2e));
|
| + if (oppSeg->collapsed(oppTs, oppTe)) {
|
| + return log->record(kAddIfCollapsed_Glitch, id, oppSeg);
|
| }
|
| - if (swap) {
|
| + if (coinTs > coinTe) {
|
| + SkTSwap(coinTs, coinTe);
|
| SkTSwap(oppTs, oppTe);
|
| }
|
| - const SkOpSegment* coinSeg = coinPtTStart->segment();
|
| - const SkOpSegment* oppSeg = oppPtTStart->segment();
|
| - if (coinSeg == oppSeg) {
|
| - return;
|
| - }
|
| - return this->debugAddOrOverlap(id, log, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe);
|
| + return this->debugAddOrOverlap(id, log, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe
|
| + );
|
| }
|
|
|
| /* Commented-out lines keep this in sync addOrOverlap() */
|
| @@ -1500,8 +1517,8 @@ void SkOpCoincidence::debugAddOrOverlap(const char* id, SkPathOpsDebug::GlitchLo
|
| 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;
|
| + RETURN_FALSE_IF(!cs || !ce || cs == ce || cs->contains(ce) || !os || !oe || os == oe || os->contains(oe), coinSeg);
|
| + bool result = true;
|
| if (overlap) {
|
| if (overlap->coinPtTStart()->segment() == coinSeg) {
|
| log->record(kAddMissingExtend_Glitch, id, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe);
|
| @@ -1512,19 +1529,19 @@ void SkOpCoincidence::debugAddOrOverlap(const char* id, SkPathOpsDebug::GlitchLo
|
| }
|
| log->record(kAddMissingExtend_Glitch, id, oppSeg, oppTs, oppTe, coinSeg, coinTs, coinTe);
|
| }
|
| -#if DEBUG_COINCIDENCE_VERBOSE
|
| -// if (result) {
|
| -// overlap->debugShow();
|
| -// }
|
| +#if 0 && DEBUG_COINCIDENCE_VERBOSE
|
| + if (result) {
|
| + overlap->debugShow();
|
| + }
|
| #endif
|
| } else {
|
| log->record(kAddMissingCoin_Glitch, id, coinSeg, coinTs, coinTe, oppSeg, oppTs, oppTe);
|
| -#if DEBUG_COINCIDENCE_VERBOSE
|
| -// fHead->debugShow();
|
| +#if 0 && DEBUG_COINCIDENCE_VERBOSE
|
| + fHead->debugShow();
|
| #endif
|
| }
|
| this->debugValidate();
|
| - return;
|
| + return (void) result;
|
| }
|
|
|
| // Extra commented-out lines keep this in sync with addMissing()
|
| @@ -1543,55 +1560,75 @@ void SkOpCoincidence::debugAddMissing(const char* id, SkPathOpsDebug::GlitchLog*
|
| // addifmissing can modify the list that this is walking
|
| // save head so that walker can iterate over old data unperturbed
|
| // addifmissing adds to head freely then add saved head in the end
|
| - const SkOpSegment* outerCoin = outer->coinPtTStart()->segment();
|
| - const SkOpSegment* outerOpp = outer->oppPtTStart()->segment();
|
| - if (outerCoin->done() || outerOpp->done()) {
|
| - continue;
|
| - }
|
| + const SkOpPtT* ocs = outer->coinPtTStart();
|
| + SkASSERT(!ocs->deleted());
|
| + const SkOpSegment* outerCoin = ocs->segment();
|
| + SkASSERT(!outerCoin->done()); // if it's done, should have already been removed from list
|
| + const SkOpPtT* oos = outer->oppPtTStart();
|
| + SkASSERT(!oos->deleted());
|
| + const SkOpSegment* outerOpp = oos->segment();
|
| + SkASSERT(!outerOpp->done());
|
| +// SkOpSegment* outerCoinWritable = const_cast<SkOpSegment*>(outerCoin);
|
| +// SkOpSegment* outerOppWritable = const_cast<SkOpSegment*>(outerOpp);
|
| const SkCoincidentSpans* inner = outer;
|
| while ((inner = inner->next())) {
|
| this->debugValidate();
|
| double overS, overE;
|
| - const SkOpSegment* innerCoin = inner->coinPtTStart()->segment();
|
| - const SkOpSegment* innerOpp = inner->oppPtTStart()->segment();
|
| - if (innerCoin->done() || innerOpp->done()) {
|
| - continue;
|
| - }
|
| + const SkOpPtT* ics = inner->coinPtTStart();
|
| + SkASSERT(!ics->deleted());
|
| + const SkOpSegment* innerCoin = ics->segment();
|
| + SkASSERT(!innerCoin->done());
|
| + const SkOpPtT* ios = inner->oppPtTStart();
|
| + SkASSERT(!ios->deleted());
|
| + const SkOpSegment* innerOpp = ios->segment();
|
| + SkASSERT(!innerOpp->done());
|
| +// SkOpSegment* innerCoinWritable = const_cast<SkOpSegment*>(innerCoin);
|
| +// SkOpSegment* innerOppWritable = const_cast<SkOpSegment*>(innerOpp);
|
| if (outerCoin == innerCoin) {
|
| - if (outerOpp != innerOpp
|
| - && this->overlap(outer->coinPtTStart(), outer->coinPtTEnd(),
|
| - inner->coinPtTStart(), inner->coinPtTEnd(), &overS, &overE)) {
|
| - this->debugAddIfMissing(outer->coinPtTStart(), outer->coinPtTEnd(),
|
| - inner->coinPtTStart(), inner->coinPtTEnd(), overS, overE,
|
| - outer->oppPtTStart(), outer->oppPtTEnd(),
|
| - inner->oppPtTStart(), inner->oppPtTEnd(), id, log);
|
| + const SkOpPtT* oce = outer->coinPtTEnd();
|
| + SkASSERT(!oce->deleted());
|
| + const SkOpPtT* ice = inner->coinPtTEnd();
|
| + SkASSERT(!ice->deleted());
|
| + if (outerOpp != innerOpp && this->overlap(ocs, oce, ics, ice, &overS, &overE)) {
|
| + this->debugAddIfMissing(id, log, ocs->starter(oce), ics->starter(ice),
|
| + overS, overE, outerOpp, innerOpp,
|
| + ocs->debugEnder(oce),
|
| + ics->debugEnder(ice));
|
| }
|
| } else if (outerCoin == innerOpp) {
|
| - if (outerOpp != innerCoin
|
| - && this->overlap(outer->coinPtTStart(), outer->coinPtTEnd(),
|
| - inner->oppPtTStart(), inner->oppPtTEnd(), &overS, &overE)) {
|
| - this->debugAddIfMissing(outer->coinPtTStart(), outer->coinPtTEnd(),
|
| - inner->oppPtTStart(), inner->oppPtTEnd(), overS, overE,
|
| - outer->oppPtTStart(), outer->oppPtTEnd(),
|
| - inner->coinPtTStart(), inner->coinPtTEnd(), id, log);
|
| + const SkOpPtT* oce = outer->coinPtTEnd();
|
| + SkASSERT(!oce->deleted());
|
| + const SkOpPtT* ioe = inner->oppPtTEnd();
|
| + SkASSERT(!ioe->deleted());
|
| + if (outerOpp != innerCoin && this->overlap(ocs, oce, ios, ioe, &overS, &overE)) {
|
| + this->debugAddIfMissing(id, log, ocs->starter(oce), ios->starter(ioe),
|
| + overS, overE, outerOpp, innerCoin,
|
| + ocs->debugEnder(oce),
|
| + ios->debugEnder(ioe));
|
| }
|
| } else if (outerOpp == innerCoin) {
|
| + const SkOpPtT* ooe = outer->oppPtTEnd();
|
| + SkASSERT(!ooe->deleted());
|
| + const SkOpPtT* ice = inner->coinPtTEnd();
|
| + SkASSERT(!ice->deleted());
|
| SkASSERT(outerCoin != innerOpp);
|
| - if (this->overlap(outer->oppPtTStart(), outer->oppPtTEnd(),
|
| - inner->coinPtTStart(), inner->coinPtTEnd(), &overS, &overE)) {
|
| - this->debugAddIfMissing(outer->oppPtTStart(), outer->oppPtTEnd(),
|
| - inner->coinPtTStart(), inner->coinPtTEnd(), overS, overE,
|
| - outer->coinPtTStart(), outer->coinPtTEnd(),
|
| - inner->oppPtTStart(), inner->oppPtTEnd(), id, log);
|
| + if (this->overlap(oos, ooe, ics, ice, &overS, &overE)) {
|
| + this->debugAddIfMissing(id, log, oos->starter(ooe), ics->starter(ice),
|
| + overS, overE, outerCoin, innerOpp,
|
| + oos->debugEnder(ooe),
|
| + ics->debugEnder(ice));
|
| }
|
| } else if (outerOpp == innerOpp) {
|
| + const SkOpPtT* ooe = outer->oppPtTEnd();
|
| + SkASSERT(!ooe->deleted());
|
| + const SkOpPtT* ioe = inner->oppPtTEnd();
|
| + SkASSERT(!ioe->deleted());
|
| SkASSERT(outerCoin != innerCoin);
|
| - if (this->overlap(outer->oppPtTStart(), outer->oppPtTEnd(),
|
| - inner->oppPtTStart(), inner->oppPtTEnd(), &overS, &overE)) {
|
| - this->debugAddIfMissing(outer->oppPtTStart(), outer->oppPtTEnd(),
|
| - inner->oppPtTStart(), inner->oppPtTEnd(), overS, overE,
|
| - outer->coinPtTStart(), outer->coinPtTEnd(),
|
| - inner->coinPtTStart(), inner->coinPtTEnd(), id, log);
|
| + if (this->overlap(oos, ooe, ios, ioe, &overS, &overE)) {
|
| + this->debugAddIfMissing(id, log, oos->starter(ooe), ios->starter(ioe),
|
| + overS, overE, outerCoin, innerCoin,
|
| + oos->debugEnder(ooe),
|
| + ios->debugEnder(ioe));
|
| }
|
| }
|
| this->debugValidate();
|
| @@ -2442,6 +2479,10 @@ const SkOpPtT* SkOpPtT::debugContains(const SkOpSegment* check) const {
|
| } while (true);
|
| }
|
|
|
| +const SkOpPtT* SkOpPtT::debugEnder(const SkOpPtT* end) const {
|
| + return fT < end->fT ? end : this;
|
| +}
|
| +
|
| int SkOpPtT::debugLoopLimit(bool report) const {
|
| int loop = 0;
|
| const SkOpPtT* next = this;
|
|
|