| Index: src/pathops/SkOpCoincidence.cpp
|
| diff --git a/src/pathops/SkOpCoincidence.cpp b/src/pathops/SkOpCoincidence.cpp
|
| index fb2de5ac60029e8df2f5e7e3488029add621b714..a22cfc6deb23307857316cf15a3a9189bbd13b79 100755
|
| --- a/src/pathops/SkOpCoincidence.cpp
|
| +++ b/src/pathops/SkOpCoincidence.cpp
|
| @@ -51,6 +51,8 @@ void SkOpCoincidence::add(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* o
|
| coinRec->fOppPtTStart = oppPtTStart;
|
| coinRec->fOppPtTEnd = oppPtTEnd;
|
| coinRec->fFlipped = flipped;
|
| + SkDEBUGCODE(coinRec->fID = fDebugState->nextCoinID());
|
| +
|
| this->fHead = coinRec;
|
| }
|
|
|
| @@ -65,7 +67,7 @@ static void t_range(const SkOpPtT* overS, const SkOpPtT* overE, double tStart, d
|
| *coinTe = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * eRatio;
|
| }
|
|
|
| -void SkOpCoincidence::addExpanded(SkChunkAlloc* allocator
|
| +bool SkOpCoincidence::addExpanded(SkChunkAlloc* allocator
|
| PATH_OPS_DEBUG_VALIDATE_PARAMS(SkOpGlobalState* globalState)) {
|
| #if DEBUG_VALIDATE
|
| globalState->setPhase(SkOpGlobalState::kIntersecting);
|
| @@ -92,7 +94,9 @@ void SkOpCoincidence::addExpanded(SkChunkAlloc* allocator
|
| double startPart = (test->t() - startPtT->fT) / startRange;
|
| double oStartRange = coin->fOppPtTEnd->fT - oStartPtT->fT;
|
| double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange;
|
| - SkASSERT(startPart != oStartPart);
|
| + if (startPart == oStartPart) {
|
| + return false;
|
| + }
|
| SkOpPtT* newPt;
|
| if (startPart < oStartPart) {
|
| double newT = oStartPtT->fT + oStartRange * startPart;
|
| @@ -112,7 +116,7 @@ void SkOpCoincidence::addExpanded(SkChunkAlloc* allocator
|
| if (test != end) {
|
| test = test->upCast()->next();
|
| }
|
| - if (oStart != oEnd) {
|
| + if (oTest != oEnd) {
|
| oTest = coin->fFlipped ? oTest->prev() : oTest->upCast()->next();
|
| }
|
| }
|
| @@ -120,9 +124,10 @@ void SkOpCoincidence::addExpanded(SkChunkAlloc* allocator
|
| #if DEBUG_VALIDATE
|
| globalState->setPhase(SkOpGlobalState::kWalking);
|
| #endif
|
| + return true;
|
| }
|
|
|
| -void SkOpCoincidence::addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over1s,
|
| +bool SkOpCoincidence::addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over1s,
|
| SkOpPtT* over1e, SkChunkAlloc* allocator) {
|
| SkCoincidentSpans* check = this->fTop;
|
| do {
|
| @@ -132,7 +137,7 @@ void SkOpCoincidence::addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over
|
| || !fDebugState->debugRunFail());
|
| SkASSERT(check->fOppPtTEnd->span() == outer->fOppPtTEnd->span()
|
| || !fDebugState->debugRunFail());
|
| - return;
|
| + return false;
|
| }
|
| if (check->fCoinPtTStart->span() == outer->fCoinPtTStart->span()
|
| && check->fOppPtTStart->span() == over1s->span()) {
|
| @@ -140,13 +145,14 @@ void SkOpCoincidence::addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over
|
| || !fDebugState->debugRunFail());
|
| SkASSERT(check->fOppPtTEnd->span() == over1e->span()
|
| || !fDebugState->debugRunFail());
|
| - return;
|
| + return false;
|
| }
|
| } while ((check = check->fNext));
|
| this->add(outer->fCoinPtTStart, outer->fCoinPtTEnd, over1s, over1e, allocator);
|
| #if 0
|
| // FIXME: up to four flavors could be added -- do we need only one?
|
| #endif
|
| + return true;
|
| }
|
|
|
| bool SkOpCoincidence::addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e,
|
| @@ -184,7 +190,7 @@ bool SkOpCoincidence::addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e,
|
| + (int) between(check->fOppPtTStart->fT, oTe, check->fOppPtTEnd->fT);
|
| // SkASSERT(tweenCount == 0 || tweenCount == 4);
|
| if (tweenCount) {
|
| - return true;
|
| + return false;
|
| }
|
| } while ((check = check->fNext));
|
| if ((over1s->fT < over1e->fT) != (over2s->fT < over2e->fT)) {
|
| @@ -196,9 +202,7 @@ bool SkOpCoincidence::addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e,
|
| }
|
| SkOpPtT* cs = coinSeg->addMissing(coinTs, oppSeg, allocator);
|
| SkOpPtT* ce = coinSeg->addMissing(coinTe, oppSeg, allocator);
|
| - if (cs == ce) {
|
| - return false;
|
| - }
|
| + SkASSERT(cs != ce);
|
| SkOpPtT* os = oppSeg->addMissing(oppTs, coinSeg, allocator);
|
| SkOpPtT* oe = oppSeg->addMissing(oppTe, coinSeg, allocator);
|
| SkASSERT(os != oe);
|
| @@ -215,13 +219,13 @@ bool SkOpCoincidence::addMissing(SkChunkAlloc* allocator) {
|
| if (!outer) {
|
| return true;
|
| }
|
| - bool result;
|
| + bool added = false;
|
| fTop = outer;
|
| fHead = nullptr;
|
| do {
|
| // addifmissing can modify the list that this is walking
|
| - // maybe save head so that walker can iterate over old data unperturbed
|
| - // and addifmissing can add to head freely then add saved head in the end
|
| + // 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->fCoinPtTStart->segment();
|
| SkASSERT(outerCoin == outer->fCoinPtTEnd->segment());
|
| const SkOpSegment* outerOpp = outer->fOppPtTStart->segment();
|
| @@ -236,43 +240,31 @@ bool SkOpCoincidence::addMissing(SkChunkAlloc* allocator) {
|
| if (outerCoin == innerCoin
|
| && this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd,
|
| inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) {
|
| - if (!this->addIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd,
|
| + added |= this->addIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd,
|
| inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE,
|
| outer->fOppPtTStart, outer->fOppPtTEnd,
|
| - inner->fOppPtTStart, inner->fOppPtTEnd, allocator)) {
|
| - result = false;
|
| - goto returnResult;
|
| - }
|
| + inner->fOppPtTStart, inner->fOppPtTEnd, allocator);
|
| } else if (outerCoin == innerOpp
|
| && this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd,
|
| inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) {
|
| - if (!this->addIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd,
|
| + added |= this->addIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd,
|
| inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE,
|
| outer->fOppPtTStart, outer->fOppPtTEnd,
|
| - inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator)) {
|
| - result = false;
|
| - goto returnResult;
|
| - }
|
| + inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator);
|
| } else if (outerOpp == innerCoin
|
| && this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd,
|
| inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) {
|
| - if (!this->addIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd,
|
| + added |= this->addIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd,
|
| inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE,
|
| outer->fCoinPtTStart, outer->fCoinPtTEnd,
|
| - inner->fOppPtTStart, inner->fOppPtTEnd, allocator)) {
|
| - result = false;
|
| - goto returnResult;
|
| - }
|
| + inner->fOppPtTStart, inner->fOppPtTEnd, allocator);
|
| } else if (outerOpp == innerOpp
|
| && this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd,
|
| inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) {
|
| - if (!this->addIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd,
|
| + added |= this->addIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd,
|
| inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE,
|
| outer->fCoinPtTStart, outer->fCoinPtTEnd,
|
| - inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator)) {
|
| - result = false;
|
| - goto returnResult;
|
| - }
|
| + inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator);
|
| } else if (outerCoin != innerCoin) {
|
| // check to see if outer span overlaps the inner span
|
| // look for inner segment in pt-t list
|
| @@ -283,21 +275,24 @@ bool SkOpCoincidence::addMissing(SkChunkAlloc* allocator) {
|
| if (testS && testS->fT >= inner->fCoinPtTStart->fT
|
| && testE && testE->fT <= inner->fCoinPtTEnd->fT
|
| && this->testForCoincidence(outer, testS, testE)) {
|
| - this->addIfMissing(outer, testS, testE, allocator);
|
| + added |= this->addIfMissing(outer, testS, testE, allocator);
|
| } else {
|
| testS = inner->fCoinPtTStart->contains(outerCoin);
|
| testE = inner->fCoinPtTEnd->contains(outerCoin);
|
| if (testS && testS->fT >= outer->fCoinPtTStart->fT
|
| && testE && testE->fT <= outer->fCoinPtTEnd->fT
|
| && this->testForCoincidence(inner, testS, testE)) {
|
| - this->addIfMissing(inner, testS, testE, allocator);
|
| + added |= this->addIfMissing(inner, testS, testE, allocator);
|
| }
|
| }
|
| }
|
| +#if 0 && DEBUG_COINCIDENCE
|
| + SkString miss;
|
| + miss.printf("addMissing inner=%d outer=%d", inner->debugID(), outer->debugID());
|
| + DEBUG_COINCIDENCE_HEALTH(fDebugState->contourHead(), miss.c_str());
|
| +#endif
|
| }
|
| } while ((outer = outer->fNext));
|
| - result = true;
|
| -returnResult:
|
| SkCoincidentSpans** headPtr = &fHead;
|
| while (*headPtr) {
|
| SkCoincidentSpans** headNext = &(*headPtr)->fNext;
|
| @@ -307,7 +302,7 @@ returnResult:
|
| headPtr = headNext;
|
| }
|
| *headPtr = fTop;
|
| - return result;
|
| + return added;
|
| }
|
|
|
| void SkOpCoincidence::addOverlap(SkOpSegment* seg1, SkOpSegment* seg1o, SkOpSegment* seg2,
|
| @@ -340,9 +335,9 @@ void SkOpCoincidence::addOverlap(SkOpSegment* seg1, SkOpSegment* seg1o, SkOpSegm
|
| this->add(s1, e1, s2, e2, allocator);
|
| }
|
|
|
| -bool SkOpCoincidence::contains(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* oppPtTStart,
|
| - SkOpPtT* oppPtTEnd, bool flipped) {
|
| - SkCoincidentSpans* coin = fHead;
|
| +bool SkOpCoincidence::contains(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd,
|
| + const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, bool flipped) const {
|
| + const SkCoincidentSpans* coin = fHead;
|
| if (!coin) {
|
| return false;
|
| }
|
| @@ -454,6 +449,9 @@ bool SkOpCoincidence::apply() {
|
| if (next == end) {
|
| break;
|
| }
|
| + if (!next->upCastable()) {
|
| + return false;
|
| + }
|
| start = next->upCast();
|
| // if the opposite ran out too soon, just reuse the last span
|
| if (!oNext || !oNext->upCastable()) {
|
| @@ -662,8 +660,8 @@ bool SkOpCoincidence::overlap(const SkOpPtT* coin1s, const SkOpPtT* coin1e,
|
| return *overS < *overE;
|
| }
|
|
|
| -bool SkOpCoincidence::testForCoincidence(const SkCoincidentSpans* outer, SkOpPtT* testS,
|
| - SkOpPtT* testE) const {
|
| +bool SkOpCoincidence::testForCoincidence(const SkCoincidentSpans* outer, const SkOpPtT* testS,
|
| + const SkOpPtT* testE) const {
|
| return testS->segment()->testForCoincidence(testS, testE, testS->span(),
|
| testE->span(), outer->fCoinPtTStart->segment(), 120000); // FIXME: replace with tuned
|
| }
|
|
|