| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 #include "SkOpCoincidence.h" | 7 #include "SkOpCoincidence.h" |
| 8 #include "SkOpSegment.h" | 8 #include "SkOpSegment.h" |
| 9 #include "SkPathOpsTSect.h" | 9 #include "SkPathOpsTSect.h" |
| 10 | 10 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 SkOpPtT* oppPtTEnd, SkChunkAlloc* allocator) { | 44 SkOpPtT* oppPtTEnd, SkChunkAlloc* allocator) { |
| 45 SkASSERT(coinPtTStart->fT < coinPtTEnd->fT); | 45 SkASSERT(coinPtTStart->fT < coinPtTEnd->fT); |
| 46 bool flipped = oppPtTStart->fT > oppPtTEnd->fT; | 46 bool flipped = oppPtTStart->fT > oppPtTEnd->fT; |
| 47 SkCoincidentSpans* coinRec = SkOpTAllocator<SkCoincidentSpans>::Allocate(all
ocator); | 47 SkCoincidentSpans* coinRec = SkOpTAllocator<SkCoincidentSpans>::Allocate(all
ocator); |
| 48 coinRec->fNext = this->fHead; | 48 coinRec->fNext = this->fHead; |
| 49 coinRec->fCoinPtTStart = coinPtTStart; | 49 coinRec->fCoinPtTStart = coinPtTStart; |
| 50 coinRec->fCoinPtTEnd = coinPtTEnd; | 50 coinRec->fCoinPtTEnd = coinPtTEnd; |
| 51 coinRec->fOppPtTStart = oppPtTStart; | 51 coinRec->fOppPtTStart = oppPtTStart; |
| 52 coinRec->fOppPtTEnd = oppPtTEnd; | 52 coinRec->fOppPtTEnd = oppPtTEnd; |
| 53 coinRec->fFlipped = flipped; | 53 coinRec->fFlipped = flipped; |
| 54 SkDEBUGCODE(coinRec->fID = fDebugState->nextCoinID()); |
| 55 |
| 54 this->fHead = coinRec; | 56 this->fHead = coinRec; |
| 55 } | 57 } |
| 56 | 58 |
| 57 static void t_range(const SkOpPtT* overS, const SkOpPtT* overE, double tStart, d
ouble tEnd, | 59 static void t_range(const SkOpPtT* overS, const SkOpPtT* overE, double tStart, d
ouble tEnd, |
| 58 const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, double* coinTs,
double* coinTe) { | 60 const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, double* coinTs,
double* coinTe) { |
| 59 double denom = overE->fT - overS->fT; | 61 double denom = overE->fT - overS->fT; |
| 60 double start = 0 < denom ? tStart : tEnd; | 62 double start = 0 < denom ? tStart : tEnd; |
| 61 double end = 0 < denom ? tEnd : tStart; | 63 double end = 0 < denom ? tEnd : tStart; |
| 62 double sRatio = (start - overS->fT) / denom; | 64 double sRatio = (start - overS->fT) / denom; |
| 63 double eRatio = (end - overS->fT) / denom; | 65 double eRatio = (end - overS->fT) / denom; |
| 64 *coinTs = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * sRatio; | 66 *coinTs = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * sRatio; |
| 65 *coinTe = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * eRatio; | 67 *coinTe = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * eRatio; |
| 66 } | 68 } |
| 67 | 69 |
| 68 void SkOpCoincidence::addExpanded(SkChunkAlloc* allocator | 70 bool SkOpCoincidence::addExpanded(SkChunkAlloc* allocator |
| 69 PATH_OPS_DEBUG_VALIDATE_PARAMS(SkOpGlobalState* globalState)) { | 71 PATH_OPS_DEBUG_VALIDATE_PARAMS(SkOpGlobalState* globalState)) { |
| 70 #if DEBUG_VALIDATE | 72 #if DEBUG_VALIDATE |
| 71 globalState->setPhase(SkOpGlobalState::kIntersecting); | 73 globalState->setPhase(SkOpGlobalState::kIntersecting); |
| 72 #endif | 74 #endif |
| 73 // for each coincident pair, match the spans | 75 // for each coincident pair, match the spans |
| 74 // if the spans don't match, add the mssing pt to the segment and loop it in
the opposite span | 76 // if the spans don't match, add the mssing pt to the segment and loop it in
the opposite span |
| 75 SkCoincidentSpans* coin = this->fHead; | 77 SkCoincidentSpans* coin = this->fHead; |
| 76 SkASSERT(coin); | 78 SkASSERT(coin); |
| 77 do { | 79 do { |
| 78 SkOpPtT* startPtT = coin->fCoinPtTStart; | 80 SkOpPtT* startPtT = coin->fCoinPtTStart; |
| 79 SkOpPtT* oStartPtT = coin->fOppPtTStart; | 81 SkOpPtT* oStartPtT = coin->fOppPtTStart; |
| 80 SkASSERT(startPtT->contains(oStartPtT)); | 82 SkASSERT(startPtT->contains(oStartPtT)); |
| 81 SkASSERT(coin->fCoinPtTEnd->contains(coin->fOppPtTEnd)); | 83 SkASSERT(coin->fCoinPtTEnd->contains(coin->fOppPtTEnd)); |
| 82 SkOpSpanBase* start = startPtT->span(); | 84 SkOpSpanBase* start = startPtT->span(); |
| 83 SkOpSpanBase* oStart = oStartPtT->span(); | 85 SkOpSpanBase* oStart = oStartPtT->span(); |
| 84 const SkOpSpanBase* end = coin->fCoinPtTEnd->span(); | 86 const SkOpSpanBase* end = coin->fCoinPtTEnd->span(); |
| 85 const SkOpSpanBase* oEnd = coin->fOppPtTEnd->span(); | 87 const SkOpSpanBase* oEnd = coin->fOppPtTEnd->span(); |
| 86 SkOpSpanBase* test = start->upCast()->next(); | 88 SkOpSpanBase* test = start->upCast()->next(); |
| 87 SkOpSpanBase* oTest = coin->fFlipped ? oStart->prev() : oStart->upCast()
->next(); | 89 SkOpSpanBase* oTest = coin->fFlipped ? oStart->prev() : oStart->upCast()
->next(); |
| 88 while (test != end || oTest != oEnd) { | 90 while (test != end || oTest != oEnd) { |
| 89 if (!test->ptT()->contains(oTest->ptT())) { | 91 if (!test->ptT()->contains(oTest->ptT())) { |
| 90 // use t ranges to guess which one is missing | 92 // use t ranges to guess which one is missing |
| 91 double startRange = coin->fCoinPtTEnd->fT - startPtT->fT; | 93 double startRange = coin->fCoinPtTEnd->fT - startPtT->fT; |
| 92 double startPart = (test->t() - startPtT->fT) / startRange; | 94 double startPart = (test->t() - startPtT->fT) / startRange; |
| 93 double oStartRange = coin->fOppPtTEnd->fT - oStartPtT->fT; | 95 double oStartRange = coin->fOppPtTEnd->fT - oStartPtT->fT; |
| 94 double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange; | 96 double oStartPart = (oTest->t() - oStartPtT->fT) / oStartRange; |
| 95 SkASSERT(startPart != oStartPart); | 97 if (startPart == oStartPart) { |
| 98 return false; |
| 99 } |
| 96 SkOpPtT* newPt; | 100 SkOpPtT* newPt; |
| 97 if (startPart < oStartPart) { | 101 if (startPart < oStartPart) { |
| 98 double newT = oStartPtT->fT + oStartRange * startPart; | 102 double newT = oStartPtT->fT + oStartRange * startPart; |
| 99 newPt = oStart->segment()->addT(newT, SkOpSegment::kAllowAli
as, allocator); | 103 newPt = oStart->segment()->addT(newT, SkOpSegment::kAllowAli
as, allocator); |
| 100 newPt->fPt = test->pt(); | 104 newPt->fPt = test->pt(); |
| 101 test->ptT()->addOpp(newPt); | 105 test->ptT()->addOpp(newPt); |
| 102 } else { | 106 } else { |
| 103 double newT = startPtT->fT + startRange * oStartPart; | 107 double newT = startPtT->fT + startRange * oStartPart; |
| 104 newPt = start->segment()->addT(newT, SkOpSegment::kAllowAlia
s, allocator); | 108 newPt = start->segment()->addT(newT, SkOpSegment::kAllowAlia
s, allocator); |
| 105 newPt->fPt = oTest->pt(); | 109 newPt->fPt = oTest->pt(); |
| 106 oTest->ptT()->addOpp(newPt); | 110 oTest->ptT()->addOpp(newPt); |
| 107 } | 111 } |
| 108 // start over | 112 // start over |
| 109 test = start; | 113 test = start; |
| 110 oTest = oStart; | 114 oTest = oStart; |
| 111 } | 115 } |
| 112 if (test != end) { | 116 if (test != end) { |
| 113 test = test->upCast()->next(); | 117 test = test->upCast()->next(); |
| 114 } | 118 } |
| 115 if (oStart != oEnd) { | 119 if (oTest != oEnd) { |
| 116 oTest = coin->fFlipped ? oTest->prev() : oTest->upCast()->next()
; | 120 oTest = coin->fFlipped ? oTest->prev() : oTest->upCast()->next()
; |
| 117 } | 121 } |
| 118 } | 122 } |
| 119 } while ((coin = coin->fNext)); | 123 } while ((coin = coin->fNext)); |
| 120 #if DEBUG_VALIDATE | 124 #if DEBUG_VALIDATE |
| 121 globalState->setPhase(SkOpGlobalState::kWalking); | 125 globalState->setPhase(SkOpGlobalState::kWalking); |
| 122 #endif | 126 #endif |
| 127 return true; |
| 123 } | 128 } |
| 124 | 129 |
| 125 void SkOpCoincidence::addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over
1s, | 130 bool SkOpCoincidence::addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over
1s, |
| 126 SkOpPtT* over1e, SkChunkAlloc* allocator) { | 131 SkOpPtT* over1e, SkChunkAlloc* allocator) { |
| 127 SkCoincidentSpans* check = this->fTop; | 132 SkCoincidentSpans* check = this->fTop; |
| 128 do { | 133 do { |
| 129 if (check->fCoinPtTStart->span() == over1s->span() | 134 if (check->fCoinPtTStart->span() == over1s->span() |
| 130 && check->fOppPtTStart->span() == outer->fOppPtTStart->span()) { | 135 && check->fOppPtTStart->span() == outer->fOppPtTStart->span()) { |
| 131 SkASSERT(check->fCoinPtTEnd->span() == over1e->span() | 136 SkASSERT(check->fCoinPtTEnd->span() == over1e->span() |
| 132 || !fDebugState->debugRunFail()); | 137 || !fDebugState->debugRunFail()); |
| 133 SkASSERT(check->fOppPtTEnd->span() == outer->fOppPtTEnd->span() | 138 SkASSERT(check->fOppPtTEnd->span() == outer->fOppPtTEnd->span() |
| 134 || !fDebugState->debugRunFail()); | 139 || !fDebugState->debugRunFail()); |
| 135 return; | 140 return false; |
| 136 } | 141 } |
| 137 if (check->fCoinPtTStart->span() == outer->fCoinPtTStart->span() | 142 if (check->fCoinPtTStart->span() == outer->fCoinPtTStart->span() |
| 138 && check->fOppPtTStart->span() == over1s->span()) { | 143 && check->fOppPtTStart->span() == over1s->span()) { |
| 139 SkASSERT(check->fCoinPtTEnd->span() == outer->fCoinPtTEnd->span() | 144 SkASSERT(check->fCoinPtTEnd->span() == outer->fCoinPtTEnd->span() |
| 140 || !fDebugState->debugRunFail()); | 145 || !fDebugState->debugRunFail()); |
| 141 SkASSERT(check->fOppPtTEnd->span() == over1e->span() | 146 SkASSERT(check->fOppPtTEnd->span() == over1e->span() |
| 142 || !fDebugState->debugRunFail()); | 147 || !fDebugState->debugRunFail()); |
| 143 return; | 148 return false; |
| 144 } | 149 } |
| 145 } while ((check = check->fNext)); | 150 } while ((check = check->fNext)); |
| 146 this->add(outer->fCoinPtTStart, outer->fCoinPtTEnd, over1s, over1e, allocato
r); | 151 this->add(outer->fCoinPtTStart, outer->fCoinPtTEnd, over1s, over1e, allocato
r); |
| 147 #if 0 | 152 #if 0 |
| 148 // FIXME: up to four flavors could be added -- do we need only one? | 153 // FIXME: up to four flavors could be added -- do we need only one? |
| 149 #endif | 154 #endif |
| 155 return true; |
| 150 } | 156 } |
| 151 | 157 |
| 152 bool SkOpCoincidence::addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, | 158 bool SkOpCoincidence::addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, |
| 153 const SkOpPtT* over2s, const SkOpPtT* over2e, double tStar
t, double tEnd, | 159 const SkOpPtT* over2s, const SkOpPtT* over2e, double tStar
t, double tEnd, |
| 154 SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, | 160 SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
| 155 SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, SkChunkAlloc* allocator)
{ | 161 SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, SkChunkAlloc* allocator)
{ |
| 156 double coinTs, coinTe, oppTs, oppTe; | 162 double coinTs, coinTe, oppTs, oppTe; |
| 157 t_range(over1s, over1e, tStart, tEnd, coinPtTStart, coinPtTEnd, &coinTs, &co
inTe); | 163 t_range(over1s, over1e, tStart, tEnd, coinPtTStart, coinPtTEnd, &coinTs, &co
inTe); |
| 158 t_range(over2s, over2e, tStart, tEnd, oppPtTStart, oppPtTEnd, &oppTs, &oppTe
); | 164 t_range(over2s, over2e, tStart, tEnd, oppPtTStart, oppPtTEnd, &oppTs, &oppTe
); |
| 159 SkOpSegment* coinSeg = coinPtTStart->segment(); | 165 SkOpSegment* coinSeg = coinPtTStart->segment(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 177 SkASSERT(checkOppSeg != oppSeg); | 183 SkASSERT(checkOppSeg != oppSeg); |
| 178 SkTSwap(cTs, oTs); | 184 SkTSwap(cTs, oTs); |
| 179 SkTSwap(cTe, oTe); | 185 SkTSwap(cTe, oTe); |
| 180 } | 186 } |
| 181 int tweenCount = (int) between(check->fCoinPtTStart->fT, cTs, check->fCo
inPtTEnd->fT) | 187 int tweenCount = (int) between(check->fCoinPtTStart->fT, cTs, check->fCo
inPtTEnd->fT) |
| 182 + (int) between(check->fCoinPtTStart->fT, cTe, check->fCo
inPtTEnd->fT) | 188 + (int) between(check->fCoinPtTStart->fT, cTe, check->fCo
inPtTEnd->fT) |
| 183 + (int) between(check->fOppPtTStart->fT, oTs, check->fOpp
PtTEnd->fT) | 189 + (int) between(check->fOppPtTStart->fT, oTs, check->fOpp
PtTEnd->fT) |
| 184 + (int) between(check->fOppPtTStart->fT, oTe, check->fOpp
PtTEnd->fT); | 190 + (int) between(check->fOppPtTStart->fT, oTe, check->fOpp
PtTEnd->fT); |
| 185 // SkASSERT(tweenCount == 0 || tweenCount == 4); | 191 // SkASSERT(tweenCount == 0 || tweenCount == 4); |
| 186 if (tweenCount) { | 192 if (tweenCount) { |
| 187 return true; | 193 return false; |
| 188 } | 194 } |
| 189 } while ((check = check->fNext)); | 195 } while ((check = check->fNext)); |
| 190 if ((over1s->fT < over1e->fT) != (over2s->fT < over2e->fT)) { | 196 if ((over1s->fT < over1e->fT) != (over2s->fT < over2e->fT)) { |
| 191 SkTSwap(oppTs, oppTe); | 197 SkTSwap(oppTs, oppTe); |
| 192 } | 198 } |
| 193 if (coinTs > coinTe) { | 199 if (coinTs > coinTe) { |
| 194 SkTSwap(coinTs, coinTe); | 200 SkTSwap(coinTs, coinTe); |
| 195 SkTSwap(oppTs, oppTe); | 201 SkTSwap(oppTs, oppTe); |
| 196 } | 202 } |
| 197 SkOpPtT* cs = coinSeg->addMissing(coinTs, oppSeg, allocator); | 203 SkOpPtT* cs = coinSeg->addMissing(coinTs, oppSeg, allocator); |
| 198 SkOpPtT* ce = coinSeg->addMissing(coinTe, oppSeg, allocator); | 204 SkOpPtT* ce = coinSeg->addMissing(coinTe, oppSeg, allocator); |
| 199 if (cs == ce) { | 205 SkASSERT(cs != ce); |
| 200 return false; | |
| 201 } | |
| 202 SkOpPtT* os = oppSeg->addMissing(oppTs, coinSeg, allocator); | 206 SkOpPtT* os = oppSeg->addMissing(oppTs, coinSeg, allocator); |
| 203 SkOpPtT* oe = oppSeg->addMissing(oppTe, coinSeg, allocator); | 207 SkOpPtT* oe = oppSeg->addMissing(oppTe, coinSeg, allocator); |
| 204 SkASSERT(os != oe); | 208 SkASSERT(os != oe); |
| 205 cs->addOpp(os); | 209 cs->addOpp(os); |
| 206 ce->addOpp(oe); | 210 ce->addOpp(oe); |
| 207 this->add(cs, ce, os, oe, allocator); | 211 this->add(cs, ce, os, oe, allocator); |
| 208 return true; | 212 return true; |
| 209 } | 213 } |
| 210 | 214 |
| 211 /* detects overlaps of different coincident runs on same segment */ | 215 /* detects overlaps of different coincident runs on same segment */ |
| 212 /* does not detect overlaps for pairs without any segments in common */ | 216 /* does not detect overlaps for pairs without any segments in common */ |
| 213 bool SkOpCoincidence::addMissing(SkChunkAlloc* allocator) { | 217 bool SkOpCoincidence::addMissing(SkChunkAlloc* allocator) { |
| 214 SkCoincidentSpans* outer = fHead; | 218 SkCoincidentSpans* outer = fHead; |
| 215 if (!outer) { | 219 if (!outer) { |
| 216 return true; | 220 return true; |
| 217 } | 221 } |
| 218 bool result; | 222 bool added = false; |
| 219 fTop = outer; | 223 fTop = outer; |
| 220 fHead = nullptr; | 224 fHead = nullptr; |
| 221 do { | 225 do { |
| 222 // addifmissing can modify the list that this is walking | 226 // addifmissing can modify the list that this is walking |
| 223 // maybe save head so that walker can iterate over old data unperturbed | 227 // save head so that walker can iterate over old data unperturbed |
| 224 // and addifmissing can add to head freely then add saved head in the end | 228 // addifmissing adds to head freely then add saved head in the end |
| 225 const SkOpSegment* outerCoin = outer->fCoinPtTStart->segment(); | 229 const SkOpSegment* outerCoin = outer->fCoinPtTStart->segment(); |
| 226 SkASSERT(outerCoin == outer->fCoinPtTEnd->segment()); | 230 SkASSERT(outerCoin == outer->fCoinPtTEnd->segment()); |
| 227 const SkOpSegment* outerOpp = outer->fOppPtTStart->segment(); | 231 const SkOpSegment* outerOpp = outer->fOppPtTStart->segment(); |
| 228 SkASSERT(outerOpp == outer->fOppPtTEnd->segment()); | 232 SkASSERT(outerOpp == outer->fOppPtTEnd->segment()); |
| 229 SkCoincidentSpans* inner = outer; | 233 SkCoincidentSpans* inner = outer; |
| 230 while ((inner = inner->fNext)) { | 234 while ((inner = inner->fNext)) { |
| 231 double overS, overE; | 235 double overS, overE; |
| 232 const SkOpSegment* innerCoin = inner->fCoinPtTStart->segment(); | 236 const SkOpSegment* innerCoin = inner->fCoinPtTStart->segment(); |
| 233 SkASSERT(innerCoin == inner->fCoinPtTEnd->segment()); | 237 SkASSERT(innerCoin == inner->fCoinPtTEnd->segment()); |
| 234 const SkOpSegment* innerOpp = inner->fOppPtTStart->segment(); | 238 const SkOpSegment* innerOpp = inner->fOppPtTStart->segment(); |
| 235 SkASSERT(innerOpp == inner->fOppPtTEnd->segment()); | 239 SkASSERT(innerOpp == inner->fOppPtTEnd->segment()); |
| 236 if (outerCoin == innerCoin | 240 if (outerCoin == innerCoin |
| 237 && this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd, | 241 && this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd, |
| 238 inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) { | 242 inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) { |
| 239 if (!this->addIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd
, | 243 added |= this->addIfMissing(outer->fCoinPtTStart, outer->fCoinPt
TEnd, |
| 240 inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE, | 244 inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE, |
| 241 outer->fOppPtTStart, outer->fOppPtTEnd, | 245 outer->fOppPtTStart, outer->fOppPtTEnd, |
| 242 inner->fOppPtTStart, inner->fOppPtTEnd, allocator)) { | 246 inner->fOppPtTStart, inner->fOppPtTEnd, allocator); |
| 243 result = false; | |
| 244 goto returnResult; | |
| 245 } | |
| 246 } else if (outerCoin == innerOpp | 247 } else if (outerCoin == innerOpp |
| 247 && this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd, | 248 && this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd, |
| 248 inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) { | 249 inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) { |
| 249 if (!this->addIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd
, | 250 added |= this->addIfMissing(outer->fCoinPtTStart, outer->fCoinPt
TEnd, |
| 250 inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE, | 251 inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE, |
| 251 outer->fOppPtTStart, outer->fOppPtTEnd, | 252 outer->fOppPtTStart, outer->fOppPtTEnd, |
| 252 inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator)) { | 253 inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator); |
| 253 result = false; | |
| 254 goto returnResult; | |
| 255 } | |
| 256 } else if (outerOpp == innerCoin | 254 } else if (outerOpp == innerCoin |
| 257 && this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd, | 255 && this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd, |
| 258 inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) { | 256 inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) { |
| 259 if (!this->addIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd, | 257 added |= this->addIfMissing(outer->fOppPtTStart, outer->fOppPtTE
nd, |
| 260 inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE, | 258 inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE, |
| 261 outer->fCoinPtTStart, outer->fCoinPtTEnd, | 259 outer->fCoinPtTStart, outer->fCoinPtTEnd, |
| 262 inner->fOppPtTStart, inner->fOppPtTEnd, allocator)) { | 260 inner->fOppPtTStart, inner->fOppPtTEnd, allocator); |
| 263 result = false; | |
| 264 goto returnResult; | |
| 265 } | |
| 266 } else if (outerOpp == innerOpp | 261 } else if (outerOpp == innerOpp |
| 267 && this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd, | 262 && this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd, |
| 268 inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) { | 263 inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) { |
| 269 if (!this->addIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd, | 264 added |= this->addIfMissing(outer->fOppPtTStart, outer->fOppPtTE
nd, |
| 270 inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE, | 265 inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE, |
| 271 outer->fCoinPtTStart, outer->fCoinPtTEnd, | 266 outer->fCoinPtTStart, outer->fCoinPtTEnd, |
| 272 inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator)) { | 267 inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator); |
| 273 result = false; | |
| 274 goto returnResult; | |
| 275 } | |
| 276 } else if (outerCoin != innerCoin) { | 268 } else if (outerCoin != innerCoin) { |
| 277 // check to see if outer span overlaps the inner span | 269 // check to see if outer span overlaps the inner span |
| 278 // look for inner segment in pt-t list | 270 // look for inner segment in pt-t list |
| 279 // if present, and if t values are in coincident range | 271 // if present, and if t values are in coincident range |
| 280 // add two pairs of new coincidence | 272 // add two pairs of new coincidence |
| 281 SkOpPtT* testS = outer->fCoinPtTStart->contains(innerCoin); | 273 SkOpPtT* testS = outer->fCoinPtTStart->contains(innerCoin); |
| 282 SkOpPtT* testE = outer->fCoinPtTEnd->contains(innerCoin); | 274 SkOpPtT* testE = outer->fCoinPtTEnd->contains(innerCoin); |
| 283 if (testS && testS->fT >= inner->fCoinPtTStart->fT | 275 if (testS && testS->fT >= inner->fCoinPtTStart->fT |
| 284 && testE && testE->fT <= inner->fCoinPtTEnd->fT | 276 && testE && testE->fT <= inner->fCoinPtTEnd->fT |
| 285 && this->testForCoincidence(outer, testS, testE)) { | 277 && this->testForCoincidence(outer, testS, testE)) { |
| 286 this->addIfMissing(outer, testS, testE, allocator); | 278 added |= this->addIfMissing(outer, testS, testE, allocator); |
| 287 } else { | 279 } else { |
| 288 testS = inner->fCoinPtTStart->contains(outerCoin); | 280 testS = inner->fCoinPtTStart->contains(outerCoin); |
| 289 testE = inner->fCoinPtTEnd->contains(outerCoin); | 281 testE = inner->fCoinPtTEnd->contains(outerCoin); |
| 290 if (testS && testS->fT >= outer->fCoinPtTStart->fT | 282 if (testS && testS->fT >= outer->fCoinPtTStart->fT |
| 291 && testE && testE->fT <= outer->fCoinPtTEnd->fT | 283 && testE && testE->fT <= outer->fCoinPtTEnd->fT |
| 292 && this->testForCoincidence(inner, testS, testE)) { | 284 && this->testForCoincidence(inner, testS, testE)) { |
| 293 this->addIfMissing(inner, testS, testE, allocator); | 285 added |= this->addIfMissing(inner, testS, testE, allocat
or); |
| 294 } | 286 } |
| 295 } | 287 } |
| 296 } | 288 } |
| 289 #if 0 && DEBUG_COINCIDENCE |
| 290 SkString miss; |
| 291 miss.printf("addMissing inner=%d outer=%d", inner->debugID(), outer-
>debugID()); |
| 292 DEBUG_COINCIDENCE_HEALTH(fDebugState->contourHead(), miss.c_str()); |
| 293 #endif |
| 297 } | 294 } |
| 298 } while ((outer = outer->fNext)); | 295 } while ((outer = outer->fNext)); |
| 299 result = true; | |
| 300 returnResult: | |
| 301 SkCoincidentSpans** headPtr = &fHead; | 296 SkCoincidentSpans** headPtr = &fHead; |
| 302 while (*headPtr) { | 297 while (*headPtr) { |
| 303 SkCoincidentSpans** headNext = &(*headPtr)->fNext; | 298 SkCoincidentSpans** headNext = &(*headPtr)->fNext; |
| 304 if (*headNext) { | 299 if (*headNext) { |
| 305 break; | 300 break; |
| 306 } | 301 } |
| 307 headPtr = headNext; | 302 headPtr = headNext; |
| 308 } | 303 } |
| 309 *headPtr = fTop; | 304 *headPtr = fTop; |
| 310 return result; | 305 return added; |
| 311 } | 306 } |
| 312 | 307 |
| 313 void SkOpCoincidence::addOverlap(SkOpSegment* seg1, SkOpSegment* seg1o, SkOpSegm
ent* seg2, | 308 void SkOpCoincidence::addOverlap(SkOpSegment* seg1, SkOpSegment* seg1o, SkOpSegm
ent* seg2, |
| 314 SkOpSegment* seg2o, SkOpPtT* overS, SkOpPtT* overE, SkChunkAlloc* alloca
tor) { | 309 SkOpSegment* seg2o, SkOpPtT* overS, SkOpPtT* overE, SkChunkAlloc* alloca
tor) { |
| 315 SkOpPtT* s1 = overS->find(seg1); | 310 SkOpPtT* s1 = overS->find(seg1); |
| 316 SkOpPtT* e1 = overE->find(seg1); | 311 SkOpPtT* e1 = overE->find(seg1); |
| 317 if (!s1->starter(e1)->span()->upCast()->windValue()) { | 312 if (!s1->starter(e1)->span()->upCast()->windValue()) { |
| 318 s1 = overS->find(seg1o); | 313 s1 = overS->find(seg1o); |
| 319 e1 = overE->find(seg1o); | 314 e1 = overE->find(seg1o); |
| 320 if (!s1->starter(e1)->span()->upCast()->windValue()) { | 315 if (!s1->starter(e1)->span()->upCast()->windValue()) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 333 if (s1->segment() == s2->segment()) { | 328 if (s1->segment() == s2->segment()) { |
| 334 return; | 329 return; |
| 335 } | 330 } |
| 336 if (s1->fT > e1->fT) { | 331 if (s1->fT > e1->fT) { |
| 337 SkTSwap(s1, e1); | 332 SkTSwap(s1, e1); |
| 338 SkTSwap(s2, e2); | 333 SkTSwap(s2, e2); |
| 339 } | 334 } |
| 340 this->add(s1, e1, s2, e2, allocator); | 335 this->add(s1, e1, s2, e2, allocator); |
| 341 } | 336 } |
| 342 | 337 |
| 343 bool SkOpCoincidence::contains(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpP
tT* oppPtTStart, | 338 bool SkOpCoincidence::contains(const SkOpPtT* coinPtTStart, const SkOpPtT* coinP
tTEnd, |
| 344 SkOpPtT* oppPtTEnd, bool flipped) { | 339 const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, bool flipped) cons
t { |
| 345 SkCoincidentSpans* coin = fHead; | 340 const SkCoincidentSpans* coin = fHead; |
| 346 if (!coin) { | 341 if (!coin) { |
| 347 return false; | 342 return false; |
| 348 } | 343 } |
| 349 do { | 344 do { |
| 350 if (coin->fCoinPtTStart == coinPtTStart && coin->fCoinPtTEnd == coinPtT
End | 345 if (coin->fCoinPtTStart == coinPtTStart && coin->fCoinPtTEnd == coinPtT
End |
| 351 && coin->fOppPtTStart == oppPtTStart && coin->fOppPtTEnd == oppP
tTEnd | 346 && coin->fOppPtTStart == oppPtTStart && coin->fOppPtTEnd == oppP
tTEnd |
| 352 && coin->fFlipped == flipped) { | 347 && coin->fFlipped == flipped) { |
| 353 return true; | 348 return true; |
| 354 } | 349 } |
| 355 } while ((coin = coin->fNext)); | 350 } while ((coin = coin->fNext)); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 segment->markDone(start); | 442 segment->markDone(start); |
| 448 } | 443 } |
| 449 if (!oWindValue && !oOppValue) { | 444 if (!oWindValue && !oOppValue) { |
| 450 oSegment->markDone(oStart); | 445 oSegment->markDone(oStart); |
| 451 } | 446 } |
| 452 SkOpSpanBase* next = start->next(); | 447 SkOpSpanBase* next = start->next(); |
| 453 SkOpSpanBase* oNext = flipped ? oStart->prev() : oStart->next(); | 448 SkOpSpanBase* oNext = flipped ? oStart->prev() : oStart->next(); |
| 454 if (next == end) { | 449 if (next == end) { |
| 455 break; | 450 break; |
| 456 } | 451 } |
| 452 if (!next->upCastable()) { |
| 453 return false; |
| 454 } |
| 457 start = next->upCast(); | 455 start = next->upCast(); |
| 458 // if the opposite ran out too soon, just reuse the last span | 456 // if the opposite ran out too soon, just reuse the last span |
| 459 if (!oNext || !oNext->upCastable()) { | 457 if (!oNext || !oNext->upCastable()) { |
| 460 oNext = oStart; | 458 oNext = oStart; |
| 461 } | 459 } |
| 462 oStart = oNext->upCast(); | 460 oStart = oNext->upCast(); |
| 463 } while (true); | 461 } while (true); |
| 464 } while ((coin = coin->fNext)); | 462 } while ((coin = coin->fNext)); |
| 465 return true; | 463 return true; |
| 466 } | 464 } |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 } | 653 } |
| 656 | 654 |
| 657 bool SkOpCoincidence::overlap(const SkOpPtT* coin1s, const SkOpPtT* coin1e, | 655 bool SkOpCoincidence::overlap(const SkOpPtT* coin1s, const SkOpPtT* coin1e, |
| 658 const SkOpPtT* coin2s, const SkOpPtT* coin2e, double* overS, double* ove
rE) const { | 656 const SkOpPtT* coin2s, const SkOpPtT* coin2e, double* overS, double* ove
rE) const { |
| 659 SkASSERT(coin1s->segment() == coin2s->segment()); | 657 SkASSERT(coin1s->segment() == coin2s->segment()); |
| 660 *overS = SkTMax(SkTMin(coin1s->fT, coin1e->fT), SkTMin(coin2s->fT, coin2e->f
T)); | 658 *overS = SkTMax(SkTMin(coin1s->fT, coin1e->fT), SkTMin(coin2s->fT, coin2e->f
T)); |
| 661 *overE = SkTMin(SkTMax(coin1s->fT, coin1e->fT), SkTMax(coin2s->fT, coin2e->f
T)); | 659 *overE = SkTMin(SkTMax(coin1s->fT, coin1e->fT), SkTMax(coin2s->fT, coin2e->f
T)); |
| 662 return *overS < *overE; | 660 return *overS < *overE; |
| 663 } | 661 } |
| 664 | 662 |
| 665 bool SkOpCoincidence::testForCoincidence(const SkCoincidentSpans* outer, SkOpPtT
* testS, | 663 bool SkOpCoincidence::testForCoincidence(const SkCoincidentSpans* outer, const S
kOpPtT* testS, |
| 666 SkOpPtT* testE) const { | 664 const SkOpPtT* testE) const { |
| 667 return testS->segment()->testForCoincidence(testS, testE, testS->span(), | 665 return testS->segment()->testForCoincidence(testS, testE, testS->span(), |
| 668 testE->span(), outer->fCoinPtTStart->segment(), 120000); // FIXME:
replace with tuned | 666 testE->span(), outer->fCoinPtTStart->segment(), 120000); // FIXME:
replace with tuned |
| 669 } | 667 } |
| OLD | NEW |