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 |