Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(648)

Side by Side Diff: src/pathops/SkOpCoincidence.cpp

Issue 1394503003: fix some pathops bugs found in 1M skps (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: init to avoid warning Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pathops/SkOpCoincidence.h ('k') | src/pathops/SkOpContour.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/pathops/SkOpCoincidence.h ('k') | src/pathops/SkOpContour.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698