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 |
} |