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 |
11 void SkOpCoincidence::add(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* o
ppPtTStart, | 11 void SkOpCoincidence::add(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* o
ppPtTStart, |
12 SkOpPtT* oppPtTEnd, SkChunkAlloc* allocator) { | 12 SkOpPtT* oppPtTEnd, SkChunkAlloc* allocator) { |
13 SkASSERT(coinPtTStart->fT < coinPtTEnd->fT); | 13 SkASSERT(coinPtTStart->fT < coinPtTEnd->fT); |
14 bool flipped = oppPtTStart->fT > oppPtTEnd->fT; | 14 bool flipped = oppPtTStart->fT > oppPtTEnd->fT; |
15 SkCoincidentSpans* coinRec = SkOpTAllocator<SkCoincidentSpans>::Allocate(all
ocator); | 15 SkCoincidentSpans* coinRec = SkOpTAllocator<SkCoincidentSpans>::Allocate(all
ocator); |
16 coinRec->fNext = this->fHead; | 16 coinRec->fNext = this->fHead; |
17 coinRec->fCoinPtTStart = coinPtTStart; | 17 coinRec->fCoinPtTStart = coinPtTStart; |
18 coinRec->fCoinPtTEnd = coinPtTEnd; | 18 coinRec->fCoinPtTEnd = coinPtTEnd; |
19 coinRec->fOppPtTStart = oppPtTStart; | 19 coinRec->fOppPtTStart = oppPtTStart; |
20 coinRec->fOppPtTEnd = oppPtTEnd; | 20 coinRec->fOppPtTEnd = oppPtTEnd; |
21 coinRec->fFlipped = flipped; | 21 coinRec->fFlipped = flipped; |
22 this->fHead = coinRec; | 22 this->fHead = coinRec; |
23 } | 23 } |
24 | 24 |
25 static void tRange(const SkOpPtT* overS, const SkOpPtT* overE, double tStart, do
uble tEnd, | 25 static void t_range(const SkOpPtT* overS, const SkOpPtT* overE, double tStart, d
ouble tEnd, |
26 const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, double* coinTs,
double* coinTe) { | 26 const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, double* coinTs,
double* coinTe) { |
27 double denom = overE->fT - overS->fT; | 27 double denom = overE->fT - overS->fT; |
28 double start = 0 < denom ? tStart : tEnd; | 28 double start = 0 < denom ? tStart : tEnd; |
29 double end = 0 < denom ? tEnd : tStart; | 29 double end = 0 < denom ? tEnd : tStart; |
30 double sRatio = (start - overS->fT) / denom; | 30 double sRatio = (start - overS->fT) / denom; |
31 double eRatio = (end - overS->fT) / denom; | 31 double eRatio = (end - overS->fT) / denom; |
32 *coinTs = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * sRatio; | 32 *coinTs = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * sRatio; |
33 *coinTe = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * eRatio; | 33 *coinTe = coinPtTStart->fT + (coinPtTEnd->fT - coinPtTStart->fT) * eRatio; |
34 } | 34 } |
35 | 35 |
36 bool SkOpCoincidence::addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, | 36 bool SkOpCoincidence::addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, |
37 const SkOpPtT* over2s, const SkOpPtT* over2e, double tStar
t, double tEnd, | 37 const SkOpPtT* over2s, const SkOpPtT* over2e, double tStar
t, double tEnd, |
38 SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, | 38 SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
39 SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, SkChunkAlloc* allocator)
{ | 39 SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, SkChunkAlloc* allocator)
{ |
40 double coinTs, coinTe, oppTs, oppTe; | 40 double coinTs, coinTe, oppTs, oppTe; |
41 tRange(over1s, over1e, tStart, tEnd, coinPtTStart, coinPtTEnd, &coinTs, &coi
nTe); | 41 t_range(over1s, over1e, tStart, tEnd, coinPtTStart, coinPtTEnd, &coinTs, &co
inTe); |
42 tRange(over2s, over2e, tStart, tEnd, oppPtTStart, oppPtTEnd, &oppTs, &oppTe)
; | 42 t_range(over2s, over2e, tStart, tEnd, oppPtTStart, oppPtTEnd, &oppTs, &oppTe
); |
43 SkOpSegment* coinSeg = coinPtTStart->segment(); | 43 SkOpSegment* coinSeg = coinPtTStart->segment(); |
44 SkOpSegment* oppSeg = oppPtTStart->segment(); | 44 SkOpSegment* oppSeg = oppPtTStart->segment(); |
45 SkASSERT(coinSeg != oppSeg); | 45 SkASSERT(coinSeg != oppSeg); |
46 SkCoincidentSpans* check = this->fHead; | 46 SkCoincidentSpans* check = this->fHead; |
47 do { | 47 do { |
48 const SkOpSegment* checkCoinSeg = check->fCoinPtTStart->segment(); | 48 const SkOpSegment* checkCoinSeg = check->fCoinPtTStart->segment(); |
49 if (checkCoinSeg != coinSeg && checkCoinSeg != oppSeg) { | 49 if (checkCoinSeg != coinSeg && checkCoinSeg != oppSeg) { |
50 continue; | 50 continue; |
51 } | 51 } |
52 const SkOpSegment* checkOppSeg = check->fOppPtTStart->segment(); | 52 const SkOpSegment* checkOppSeg = check->fOppPtTStart->segment(); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 SkCoincidentSpans* outer = this->fHead; | 96 SkCoincidentSpans* outer = this->fHead; |
97 if (!outer) { | 97 if (!outer) { |
98 return true; | 98 return true; |
99 } | 99 } |
100 do { | 100 do { |
101 SkCoincidentSpans* inner = outer; | 101 SkCoincidentSpans* inner = outer; |
102 while ((inner = inner->fNext)) { | 102 while ((inner = inner->fNext)) { |
103 double overS, overE; | 103 double overS, overE; |
104 if (this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd, | 104 if (this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd, |
105 inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) { | 105 inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) { |
106 if (!addIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd, | 106 if (!this->addIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd
, |
107 inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE, | 107 inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE, |
108 outer->fOppPtTStart, outer->fOppPtTEnd, | 108 outer->fOppPtTStart, outer->fOppPtTEnd, |
109 inner->fOppPtTStart, inner->fOppPtTEnd, allocator)) { | 109 inner->fOppPtTStart, inner->fOppPtTEnd, allocator)) { |
110 return false; | 110 return false; |
111 } | 111 } |
112 } else if (this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd, | 112 } else if (this->overlap(outer->fCoinPtTStart, outer->fCoinPtTEnd, |
113 inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) { | 113 inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) { |
114 if (!addIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd, | 114 if (!this->addIfMissing(outer->fCoinPtTStart, outer->fCoinPtTEnd
, |
115 inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE, | 115 inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE, |
116 outer->fOppPtTStart, outer->fOppPtTEnd, | 116 outer->fOppPtTStart, outer->fOppPtTEnd, |
117 inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator)) { | 117 inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator)) { |
118 return false; | 118 return false; |
119 } | 119 } |
120 } else if (this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd, | 120 } else if (this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd, |
121 inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) { | 121 inner->fCoinPtTStart, inner->fCoinPtTEnd, &overS, &overE)) { |
122 if (!addIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd, | 122 if (!this->addIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd, |
123 inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE, | 123 inner->fCoinPtTStart, inner->fCoinPtTEnd, overS, overE, |
124 outer->fCoinPtTStart, outer->fCoinPtTEnd, | 124 outer->fCoinPtTStart, outer->fCoinPtTEnd, |
125 inner->fOppPtTStart, inner->fOppPtTEnd, allocator)) { | 125 inner->fOppPtTStart, inner->fOppPtTEnd, allocator)) { |
126 return false; | 126 return false; |
127 } | 127 } |
128 } else if (this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd, | 128 } else if (this->overlap(outer->fOppPtTStart, outer->fOppPtTEnd, |
129 inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) { | 129 inner->fOppPtTStart, inner->fOppPtTEnd, &overS, &overE)) { |
130 if (!addIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd, | 130 if (!this->addIfMissing(outer->fOppPtTStart, outer->fOppPtTEnd, |
131 inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE, | 131 inner->fOppPtTStart, inner->fOppPtTEnd, overS, overE, |
132 outer->fCoinPtTStart, outer->fCoinPtTEnd, | 132 outer->fCoinPtTStart, outer->fCoinPtTEnd, |
133 inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator)) { | 133 inner->fCoinPtTStart, inner->fCoinPtTEnd, allocator)) { |
134 return false; | 134 return false; |
135 } | 135 } |
136 } | 136 } |
137 } | 137 } |
138 | 138 |
139 } while ((outer = outer->fNext)); | 139 } while ((outer = outer->fNext)); |
140 return true; | 140 return true; |
141 } | 141 } |
142 | 142 |
143 | |
144 bool SkOpCoincidence::contains(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpP
tT* oppPtTStart, | 143 bool SkOpCoincidence::contains(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpP
tT* oppPtTStart, |
145 SkOpPtT* oppPtTEnd, bool flipped) { | 144 SkOpPtT* oppPtTEnd, bool flipped) { |
146 SkCoincidentSpans* coin = fHead; | 145 SkCoincidentSpans* coin = fHead; |
147 if (!coin) { | 146 if (!coin) { |
148 return false; | 147 return false; |
149 } | 148 } |
150 do { | 149 do { |
151 if (coin->fCoinPtTStart == coinPtTStart && coin->fCoinPtTEnd == coinPtT
End | 150 if (coin->fCoinPtTStart == coinPtTStart && coin->fCoinPtTEnd == coinPtT
End |
152 && coin->fOppPtTStart == oppPtTStart && coin->fOppPtTEnd == oppP
tTEnd | 151 && coin->fOppPtTStart == oppPtTStart && coin->fOppPtTEnd == oppP
tTEnd |
153 && coin->fFlipped == flipped) { | 152 && coin->fFlipped == flipped) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 } | 237 } |
239 if (!oWindValue && !oOppValue) { | 238 if (!oWindValue && !oOppValue) { |
240 oSegment->markDone(oStart); | 239 oSegment->markDone(oStart); |
241 } | 240 } |
242 SkOpSpanBase* next = start->next(); | 241 SkOpSpanBase* next = start->next(); |
243 SkOpSpanBase* oNext = flipped ? oStart->prev() : oStart->next(); | 242 SkOpSpanBase* oNext = flipped ? oStart->prev() : oStart->next(); |
244 if (next == end) { | 243 if (next == end) { |
245 break; | 244 break; |
246 } | 245 } |
247 start = next->upCast(); | 246 start = next->upCast(); |
248 if (!oNext) { | 247 // if the opposite ran out too soon, just reuse the last span |
249 return false; | 248 if (!oNext || !oNext->upCastable()) { |
250 } | 249 oNext = oStart; |
251 if (!oNext->upCastable()) { | |
252 return false; | |
253 } | 250 } |
254 oStart = oNext->upCast(); | 251 oStart = oNext->upCast(); |
255 } while (true); | 252 } while (true); |
256 } while ((coin = coin->fNext)); | 253 } while ((coin = coin->fNext)); |
257 return true; | 254 return true; |
258 } | 255 } |
259 | 256 |
260 void SkOpCoincidence::detach(SkCoincidentSpans* remove) { | 257 void SkOpCoincidence::detach(SkCoincidentSpans* remove) { |
261 SkCoincidentSpans* coin = fHead; | 258 SkCoincidentSpans* coin = fHead; |
262 SkCoincidentSpans* prev = NULL; | 259 SkCoincidentSpans* prev = NULL; |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 | 376 |
380 bool SkOpCoincidence::overlap(const SkOpPtT* coin1s, const SkOpPtT* coin1e, | 377 bool SkOpCoincidence::overlap(const SkOpPtT* coin1s, const SkOpPtT* coin1e, |
381 const SkOpPtT* coin2s, const SkOpPtT* coin2e, double* overS, double* ove
rE) const { | 378 const SkOpPtT* coin2s, const SkOpPtT* coin2e, double* overS, double* ove
rE) const { |
382 if (coin1s->segment() != coin2s->segment()) { | 379 if (coin1s->segment() != coin2s->segment()) { |
383 return false; | 380 return false; |
384 } | 381 } |
385 *overS = SkTMax(SkTMin(coin1s->fT, coin1e->fT), SkTMin(coin2s->fT, coin2e->f
T)); | 382 *overS = SkTMax(SkTMin(coin1s->fT, coin1e->fT), SkTMin(coin2s->fT, coin2e->f
T)); |
386 *overE = SkTMin(SkTMax(coin1s->fT, coin1e->fT), SkTMax(coin2s->fT, coin2e->f
T)); | 383 *overE = SkTMin(SkTMax(coin1s->fT, coin1e->fT), SkTMax(coin2s->fT, coin2e->f
T)); |
387 return *overS < *overE; | 384 return *overS < *overE; |
388 } | 385 } |
OLD | NEW |