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

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

Issue 2128633003: pathops coincidence and security rewrite (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: require resulting t to be between 0 and 1 Created 4 years, 5 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
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 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 "SkOpContour.h" 8 #include "SkOpContour.h"
9 #include "SkOpSegment.h" 9 #include "SkOpSegment.h"
10 #include "SkPathWriter.h" 10 #include "SkPathWriter.h"
(...skipping 17 matching lines...) Expand all
28 const SkOpPtT* ptT = this; 28 const SkOpPtT* ptT = this;
29 const SkOpPtT* stopPtT = ptT; 29 const SkOpPtT* stopPtT = ptT;
30 while ((ptT = ptT->next()) != stopPtT) { 30 while ((ptT = ptT->next()) != stopPtT) {
31 if (ptT == check) { 31 if (ptT == check) {
32 return true; 32 return true;
33 } 33 }
34 } 34 }
35 return false; 35 return false;
36 } 36 }
37 37
38 SkOpPtT* SkOpPtT::contains(const SkOpSegment* check) { 38 bool SkOpPtT::contains(const SkOpSegment* segment, const SkPoint& pt) const {
39 SkASSERT(this->segment() != check); 39 SkASSERT(this->segment() != segment);
40 SkOpPtT* ptT = this; 40 const SkOpPtT* ptT = this;
41 const SkOpPtT* stopPtT = ptT; 41 const SkOpPtT* stopPtT = ptT;
42 while ((ptT = ptT->next()) != stopPtT) { 42 while ((ptT = ptT->next()) != stopPtT) {
43 if (ptT->segment() == check) { 43 if (ptT->fPt == pt && ptT->segment() == segment) {
44 return true;
45 }
46 }
47 return false;
48 }
49
50 bool SkOpPtT::contains(const SkOpSegment* segment, double t) const {
51 const SkOpPtT* ptT = this;
52 const SkOpPtT* stopPtT = ptT;
53 while ((ptT = ptT->next()) != stopPtT) {
54 if (ptT->fT == t && ptT->segment() == segment) {
55 return true;
56 }
57 }
58 return false;
59 }
60
61 const SkOpPtT* SkOpPtT::contains(const SkOpSegment* check) const {
62 SkASSERT(this->segment() != check);
63 const SkOpPtT* ptT = this;
64 const SkOpPtT* stopPtT = ptT;
65 while ((ptT = ptT->next()) != stopPtT) {
66 if (ptT->segment() == check && !ptT->deleted()) {
44 return ptT; 67 return ptT;
45 } 68 }
46 } 69 }
47 return nullptr; 70 return nullptr;
48 } 71 }
49 72
50 SkOpContour* SkOpPtT::contour() const { 73 SkOpContour* SkOpPtT::contour() const {
51 return segment()->contour(); 74 return segment()->contour();
52 } 75 }
53 76
54 SkOpPtT* SkOpPtT::doppelganger() { 77 const SkOpPtT* SkOpPtT::find(const SkOpSegment* segment) const {
55 SkASSERT(fDeleted); 78 const SkOpPtT* ptT = this;
56 SkOpPtT* ptT = fNext;
57 while (ptT->fDeleted) {
58 ptT = ptT->fNext;
59 }
60 const SkOpPtT* stopPtT = ptT; 79 const SkOpPtT* stopPtT = ptT;
61 do { 80 do {
62 if (ptT->fSpan == fSpan) { 81 if (ptT->segment() == segment && !ptT->deleted()) {
63 return ptT; 82 return ptT;
64 } 83 }
65 ptT = ptT->fNext; 84 ptT = ptT->fNext;
66 } while (stopPtT != ptT); 85 } while (stopPtT != ptT);
67 SkASSERT(0); 86 // SkASSERT(0);
68 return nullptr;
69 }
70
71 SkOpPtT* SkOpPtT::find(SkOpSegment* segment) {
72 SkOpPtT* ptT = this;
73 const SkOpPtT* stopPtT = ptT;
74 do {
75 if (ptT->segment() == segment) {
76 return ptT;
77 }
78 ptT = ptT->fNext;
79 } while (stopPtT != ptT);
80 SkASSERT(0);
81 return nullptr; 87 return nullptr;
82 } 88 }
83 89
84 SkOpGlobalState* SkOpPtT::globalState() const { 90 SkOpGlobalState* SkOpPtT::globalState() const {
85 return contour()->globalState(); 91 return contour()->globalState();
86 } 92 }
87 93
88 void SkOpPtT::init(SkOpSpanBase* span, double t, const SkPoint& pt, bool duplica te) { 94 void SkOpPtT::init(SkOpSpanBase* span, double t, const SkPoint& pt, bool duplica te) {
89 fT = t; 95 fT = t;
90 fPt = pt; 96 fPt = pt;
91 fSpan = span; 97 fSpan = span;
92 fNext = this; 98 fNext = this;
93 fDuplicatePt = duplicate; 99 fDuplicatePt = duplicate;
94 fDeleted = false; 100 fDeleted = false;
101 fCoincident = false;
95 SkDEBUGCODE(fID = span->globalState()->nextPtTID()); 102 SkDEBUGCODE(fID = span->globalState()->nextPtTID());
96 } 103 }
97 104
98 bool SkOpPtT::onEnd() const { 105 bool SkOpPtT::onEnd() const {
99 const SkOpSpanBase* span = this->span(); 106 const SkOpSpanBase* span = this->span();
100 if (span->ptT() != this) { 107 if (span->ptT() != this) {
101 return false; 108 return false;
102 } 109 }
103 const SkOpSegment* segment = this->segment(); 110 const SkOpSegment* segment = this->segment();
104 return span == segment->head() || span == segment->tail(); 111 return span == segment->head() || span == segment->tail();
105 } 112 }
106 113
114 bool SkOpPtT::ptAlreadySeen(const SkOpPtT* check) const {
115 while (this != check) {
116 if (this->fPt == check->fPt) {
117 return true;
118 }
119 check = check->fNext;
120 }
121 return false;
122 }
123
107 SkOpPtT* SkOpPtT::prev() { 124 SkOpPtT* SkOpPtT::prev() {
108 SkOpPtT* result = this; 125 SkOpPtT* result = this;
109 SkOpPtT* next = this; 126 SkOpPtT* next = this;
110 while ((next = next->fNext) != this) { 127 while ((next = next->fNext) != this) {
111 result = next; 128 result = next;
112 } 129 }
113 SkASSERT(result->fNext == this); 130 SkASSERT(result->fNext == this);
114 return result; 131 return result;
115 } 132 }
116 133
117 SkOpPtT* SkOpPtT::remove() { 134 SkOpPtT* SkOpPtT::remove(const SkOpPtT* kept) {
118 SkOpPtT* prev = this; 135 SkOpPtT* prev = this;
119 do { 136 do {
120 SkOpPtT* next = prev->fNext; 137 SkOpPtT* next = prev->fNext;
121 if (next == this) { 138 if (next == this) {
122 prev->removeNext(this); 139 prev->removeNext(kept);
123 SkASSERT(prev->fNext != prev); 140 SkASSERT(prev->fNext != prev);
124 fDeleted = true; 141 fDeleted = true;
125 return prev; 142 return prev;
126 } 143 }
127 prev = next; 144 prev = next;
128 } while (prev != this); 145 } while (prev != this);
129 SkASSERT(0); 146 SkASSERT(0);
130 return nullptr; 147 return nullptr;
131 } 148 }
132 149
133 void SkOpPtT::removeNext(SkOpPtT* kept) { 150 void SkOpPtT::removeNext(const SkOpPtT* kept) {
134 SkASSERT(this->fNext); 151 SkASSERT(this->fNext);
135 SkOpPtT* next = this->fNext; 152 SkOpPtT* next = this->fNext;
136 SkASSERT(this != next->fNext); 153 SkASSERT(this != next->fNext);
137 this->fNext = next->fNext; 154 this->fNext = next->fNext;
138 SkOpSpanBase* span = next->span(); 155 SkOpSpanBase* span = next->span();
156 SkOpCoincidence* coincidence = span->globalState()->coincidence();
157 if (coincidence) {
158 coincidence->fixUp(next, kept);
159 }
139 next->setDeleted(); 160 next->setDeleted();
140 if (span->ptT() == next) { 161 if (span->ptT() == next) {
141 span->upCast()->release(kept); 162 span->upCast()->release(kept);
142 } 163 }
143 } 164 }
144 165
145 const SkOpSegment* SkOpPtT::segment() const { 166 const SkOpSegment* SkOpPtT::segment() const {
146 return span()->segment(); 167 return span()->segment();
147 } 168 }
148 169
149 SkOpSegment* SkOpPtT::segment() { 170 SkOpSegment* SkOpPtT::segment() {
150 return span()->segment(); 171 return span()->segment();
151 } 172 }
152 173
153 void SkOpSpanBase::align() { 174 void SkOpPtT::setDeleted() {
154 if (this->fAligned) { 175 SkASSERT(this->span()->debugDeleted() || this->span()->ptT() != this);
176 SkASSERT(this->globalState()->debugSkipAssert() || !fDeleted);
177 fDeleted = true;
178 }
179
180 // please keep this in sync with debugAddOppAndMerge
181 // If the added points envelop adjacent spans, merge them in.
182 void SkOpSpanBase::addOppAndMerge(SkOpSpanBase* opp) {
183 if (this->ptT()->addOpp(opp->ptT())) {
184 this->checkForCollapsedCoincidence();
185 }
186 // compute bounds of points in span
187 SkPathOpsBounds bounds;
188 bounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin);
189 const SkOpPtT* head = this->ptT();
190 const SkOpPtT* nextPt = head;
191 do {
192 bounds.add(nextPt->fPt);
193 } while ((nextPt = nextPt->next()) != head);
194 if (!bounds.width() && !bounds.height()) {
155 return; 195 return;
156 } 196 }
157 SkASSERT(!zero_or_one(this->fPtT.fT)); 197 this->mergeContained(bounds);
158 SkASSERT(this->fPtT.next()); 198 opp->mergeContained(bounds);
159 // if a linked pt/t pair has a t of zero or one, use it as the base for alig nment 199 }
160 SkOpPtT* ptT = &this->fPtT, * stopPtT = ptT; 200
161 while ((ptT = ptT->next()) != stopPtT) { 201 // Please keep this in sync with debugMergeContained()
162 if (zero_or_one(ptT->fT)) { 202 void SkOpSpanBase::mergeContained(const SkPathOpsBounds& bounds) {
163 SkOpSegment* segment = ptT->segment(); 203 // while adjacent spans' points are contained by the bounds, merge them
164 SkASSERT(this->segment() != segment); 204 SkOpSpanBase* prev = this;
165 SkASSERT(segment->head()->ptT() == ptT || segment->tail()->ptT() == ptT); 205 SkOpSegment* seg = this->segment();
166 if (ptT->fT) { 206 while ((prev = prev->prev()) && bounds.contains(prev->pt()) && !seg->ptsDisj oint(prev, this)) {
167 segment->tail()->alignEnd(1, segment->lastPt()); 207 if (prev->prev()) {
168 } else { 208 this->merge(prev->upCast());
169 segment->head()->alignEnd(0, segment->pts()[0]); 209 prev = this;
170 } 210 } else if (this->final()) {
211 seg->clearAll();
212 return;
213 } else {
214 prev->merge(this->upCast());
215 }
216 }
217 SkOpSpanBase* current = this;
218 SkOpSpanBase* next = this;
219 while (next->upCastable() && (next = next->upCast()->next())
220 && bounds.contains(next->pt()) && !seg->ptsDisjoint(this, next)) {
221 if (!current->prev() && next->final()) {
222 seg->clearAll();
171 return; 223 return;
172 } 224 }
225 if (current->prev()) {
226 next->merge(current->upCast());
227 current = next;
228 } else {
229 current->merge(next->upCast());
230 // extra line in debug version
231 }
173 } 232 }
174 alignInner(); 233 #if DEBUG_COINCIDENCE
175 this->fAligned = true; 234 this->globalState()->coincidence()->debugValidate();
176 } 235 #endif
177
178
179 // FIXME: delete spans that collapse
180 // delete segments that collapse
181 // delete contours that collapse
182 void SkOpSpanBase::alignEnd(double t, const SkPoint& pt) {
183 SkASSERT(zero_or_one(t));
184 SkOpSegment* segment = this->segment();
185 SkASSERT(t ? segment->lastPt() == pt : segment->pts()[0] == pt);
186 alignInner();
187 *segment->writablePt(!!t) = pt;
188 SkOpPtT* ptT = &this->fPtT;
189 SkASSERT(t == ptT->fT);
190 SkASSERT(pt == ptT->fPt);
191 SkOpPtT* test = ptT, * stopPtT = ptT;
192 while ((test = test->next()) != stopPtT) {
193 SkOpSegment* other = test->segment();
194 if (other == this->segment()) {
195 continue;
196 }
197 if (!zero_or_one(test->fT)) {
198 continue;
199 }
200 *other->writablePt(!!test->fT) = pt;
201 }
202 this->fAligned = true;
203 }
204
205 void SkOpSpanBase::alignInner() {
206 // force the spans to share points and t values
207 SkOpPtT* ptT = &this->fPtT, * stopPtT = ptT;
208 const SkPoint& pt = ptT->fPt;
209 do {
210 ptT->fPt = pt;
211 const SkOpSpanBase* span = ptT->span();
212 SkOpPtT* test = ptT;
213 do {
214 SkOpPtT* prev = test;
215 if ((test = test->next()) == stopPtT) {
216 break;
217 }
218 if (span == test->span() && !span->segment()->ptsDisjoint(*ptT, *tes t)) {
219 // omit aliases that alignment makes redundant
220 if ((!ptT->alias() || test->alias()) && (ptT->onEnd() || !test-> onEnd())) {
221 SkASSERT(test->alias());
222 prev->removeNext(ptT);
223 test = prev;
224 } else {
225 SkASSERT(ptT->alias());
226 stopPtT = ptT = ptT->remove();
227 break;
228 }
229 }
230 } while (true);
231 } while ((ptT = ptT->next()) != stopPtT);
232 } 236 }
233 237
234 bool SkOpSpanBase::contains(const SkOpSpanBase* span) const { 238 bool SkOpSpanBase::contains(const SkOpSpanBase* span) const {
235 const SkOpPtT* start = &fPtT; 239 const SkOpPtT* start = &fPtT;
236 const SkOpPtT* check = &span->fPtT; 240 const SkOpPtT* check = &span->fPtT;
237 SkASSERT(start != check); 241 SkASSERT(start != check);
238 const SkOpPtT* walk = start; 242 const SkOpPtT* walk = start;
239 while ((walk = walk->next()) != start) { 243 while ((walk = walk->next()) != start) {
240 if (walk == check) { 244 if (walk == check) {
241 return true; 245 return true;
242 } 246 }
243 } 247 }
244 return false; 248 return false;
245 } 249 }
246 250
247 SkOpPtT* SkOpSpanBase::contains(const SkOpSegment* segment) { 251 const SkOpPtT* SkOpSpanBase::contains(const SkOpSegment* segment) const {
248 SkOpPtT* start = &fPtT; 252 const SkOpPtT* start = &fPtT;
249 SkOpPtT* walk = start; 253 const SkOpPtT* walk = start;
250 while ((walk = walk->next()) != start) { 254 while ((walk = walk->next()) != start) {
251 if (walk->segment() == segment) { 255 if (walk->deleted()) {
256 continue;
257 }
258 if (walk->segment() == segment && walk->span()->ptT() == walk) {
252 return walk; 259 return walk;
253 } 260 }
254 } 261 }
255 return nullptr; 262 return nullptr;
256 } 263 }
257 264
258 bool SkOpSpanBase::containsCoinEnd(const SkOpSegment* segment) const { 265 bool SkOpSpanBase::containsCoinEnd(const SkOpSegment* segment) const {
259 SkASSERT(this->segment() != segment); 266 SkASSERT(this->segment() != segment);
260 const SkOpSpanBase* next = this; 267 const SkOpSpanBase* next = this;
261 while ((next = next->fCoinEnd) != this) { 268 while ((next = next->fCoinEnd) != this) {
262 if (next->segment() == segment) { 269 if (next->segment() == segment) {
263 return true; 270 return true;
264 } 271 }
265 } 272 }
266 return false; 273 return false;
267 } 274 }
268 275
269 SkOpContour* SkOpSpanBase::contour() const { 276 SkOpContour* SkOpSpanBase::contour() const {
270 return segment()->contour(); 277 return segment()->contour();
271 } 278 }
272 279
273 SkOpGlobalState* SkOpSpanBase::globalState() const { 280 SkOpGlobalState* SkOpSpanBase::globalState() const {
274 return contour()->globalState(); 281 return contour()->globalState();
275 } 282 }
276 283
277 void SkOpSpanBase::initBase(SkOpSegment* segment, SkOpSpan* prev, double t, cons t SkPoint& pt) { 284 void SkOpSpanBase::initBase(SkOpSegment* segment, SkOpSpan* prev, double t, cons t SkPoint& pt) {
278 fSegment = segment; 285 fSegment = segment;
279 fPtT.init(this, t, pt, false); 286 fPtT.init(this, t, pt, false);
280 fCoinEnd = this; 287 fCoinEnd = this;
281 fFromAngle = nullptr; 288 fFromAngle = nullptr;
282 fPrev = prev; 289 fPrev = prev;
283 fSpanAdds = 0; 290 fSpanAdds = 0;
284 fAligned = true; 291 fAligned = true;
285 fChased = false; 292 fChased = false;
286 SkDEBUGCODE(fCount = 1); 293 SkDEBUGCODE(fCount = 1);
287 SkDEBUGCODE(fID = globalState()->nextSpanID()); 294 SkDEBUGCODE(fID = globalState()->nextSpanID());
295 SkDEBUGCODE(fDeleted = false);
288 } 296 }
289 297
290 // this pair of spans share a common t value or point; merge them and eliminate duplicates 298 // this pair of spans share a common t value or point; merge them and eliminate duplicates
291 // this does not compute the best t or pt value; this merely moves all data into a single list 299 // this does not compute the best t or pt value; this merely moves all data into a single list
292 void SkOpSpanBase::merge(SkOpSpan* span) { 300 void SkOpSpanBase::merge(SkOpSpan* span) {
293 SkOpPtT* spanPtT = span->ptT(); 301 SkOpPtT* spanPtT = span->ptT();
294 SkASSERT(this->t() != spanPtT->fT); 302 SkASSERT(this->t() != spanPtT->fT);
295 SkASSERT(!zero_or_one(spanPtT->fT)); 303 SkASSERT(!zero_or_one(spanPtT->fT));
296 span->release(this->ptT()); 304 span->release(this->ptT());
305 if (this->contains(span)) {
306 return; // merge is already in the ptT loop
307 }
297 SkOpPtT* remainder = spanPtT->next(); 308 SkOpPtT* remainder = spanPtT->next();
298 ptT()->insert(spanPtT); 309 this->ptT()->insert(spanPtT);
299 while (remainder != spanPtT) { 310 while (remainder != spanPtT) {
300 SkOpPtT* next = remainder->next(); 311 SkOpPtT* next = remainder->next();
301 SkOpPtT* compare = spanPtT->next(); 312 SkOpPtT* compare = spanPtT->next();
302 while (compare != spanPtT) { 313 while (compare != spanPtT) {
303 SkOpPtT* nextC = compare->next(); 314 SkOpPtT* nextC = compare->next();
304 if (nextC->span() == remainder->span() && nextC->fT == remainder->fT ) { 315 if (nextC->span() == remainder->span() && nextC->fT == remainder->fT ) {
305 goto tryNextRemainder; 316 goto tryNextRemainder;
306 } 317 }
307 compare = nextC; 318 compare = nextC;
308 } 319 }
309 spanPtT->insert(remainder); 320 spanPtT->insert(remainder);
310 tryNextRemainder: 321 tryNextRemainder:
311 remainder = next; 322 remainder = next;
312 } 323 }
313 fSpanAdds += span->fSpanAdds; 324 fSpanAdds += span->fSpanAdds;
325 this->checkForCollapsedCoincidence();
326 }
327
328 // please keep in sync with debugCheckForCollapsedCoincidence()
329 void SkOpSpanBase::checkForCollapsedCoincidence() {
330 SkOpCoincidence* coins = this->globalState()->coincidence();
331 if (coins->isEmpty()) {
332 return;
333 }
334 // the insert above may have put both ends of a coincident run in the same span
335 // for each coincident ptT in loop; see if its opposite in is also in the loop
336 // this implementation is the motivation for marking that a ptT is referenced by a coincident span
337 SkOpPtT* head = this->ptT();
338 SkOpPtT* test = head;
339 do {
340 if (!test->coincident()) {
341 continue;
342 }
343 coins->markCollapsed(test);
344 } while ((test = test->next()) != head);
314 } 345 }
315 346
316 int SkOpSpan::computeWindSum() { 347 int SkOpSpan::computeWindSum() {
317 SkOpGlobalState* globals = this->globalState(); 348 SkOpGlobalState* globals = this->globalState();
318 SkOpContour* contourHead = globals->contourHead(); 349 SkOpContour* contourHead = globals->contourHead();
319 int windTry = 0; 350 int windTry = 0;
320 while (!this->sortableTop(contourHead) && ++windTry < SkOpGlobalState::kMaxW indingTries) { 351 while (!this->sortableTop(contourHead) && ++windTry < SkOpGlobalState::kMaxW indingTries) {
321 ; 352 ;
322 } 353 }
323 return this->windSum(); 354 return this->windSum();
324 } 355 }
325 356
326 bool SkOpSpan::containsCoincidence(const SkOpSegment* segment) const { 357 bool SkOpSpan::containsCoincidence(const SkOpSegment* segment) const {
327 SkASSERT(this->segment() != segment); 358 SkASSERT(this->segment() != segment);
328 const SkOpSpan* next = fCoincident; 359 const SkOpSpan* next = fCoincident;
329 do { 360 do {
330 if (next->segment() == segment) { 361 if (next->segment() == segment) {
331 return true; 362 return true;
332 } 363 }
333 } while ((next = next->fCoincident) != this); 364 } while ((next = next->fCoincident) != this);
334 return false; 365 return false;
335 } 366 }
336 367
337 void SkOpSpan::release(SkOpPtT* kept) { 368 void SkOpSpan::init(SkOpSegment* segment, SkOpSpan* prev, double t, const SkPoin t& pt) {
369 SkASSERT(t != 1);
370 initBase(segment, prev, t, pt);
371 fCoincident = this;
372 fToAngle = nullptr;
373 fWindSum = fOppSum = SK_MinS32;
374 fWindValue = 1;
375 fOppValue = 0;
376 fTopTTry = 0;
377 fChased = fDone = false;
378 segment->bumpCount();
379 fAlreadyAdded = false;
380 }
381
382 // Please keep this in sync with debugInsertCoincidence()
383 bool SkOpSpan::insertCoincidence(const SkOpSegment* segment, bool flipped) {
384 if (this->containsCoincidence(segment)) {
385 return true;
386 }
387 SkOpPtT* next = &fPtT;
388 while ((next = next->next()) != &fPtT) {
389 if (next->segment() == segment) {
390 SkOpSpan* span = flipped ? next->span()->prev() : next->span()->upCa st();
391 if (!span) {
392 return false;
393 }
394 this->insertCoincidence(span);
395 return true;
396 }
397 }
398 #if DEBUG_COINCIDENCE
399 SkASSERT(0); // FIXME? if we get here, the span is missing its opposite segm ent...
400 #endif
401 return true;
402 }
403
404 void SkOpSpan::release(const SkOpPtT* kept) {
405 SkDEBUGCODE(fDeleted = true);
406 SkASSERT(kept->span() != this);
338 SkASSERT(!final()); 407 SkASSERT(!final());
339 SkOpSpan* prev = this->prev(); 408 SkOpSpan* prev = this->prev();
340 SkASSERT(prev); 409 SkASSERT(prev);
341 SkOpSpanBase* next = this->next(); 410 SkOpSpanBase* next = this->next();
342 SkASSERT(next); 411 SkASSERT(next);
343 prev->setNext(next); 412 prev->setNext(next);
344 next->setPrev(prev); 413 next->setPrev(prev);
345 this->segment()->release(this); 414 this->segment()->release(this);
346 SkOpCoincidence* coincidence = this->globalState()->coincidence(); 415 SkOpCoincidence* coincidence = this->globalState()->coincidence();
347 if (coincidence) { 416 if (coincidence) {
348 coincidence->fixUp(this->ptT(), kept); 417 coincidence->fixUp(this->ptT(), kept);
349 } 418 }
350 this->ptT()->setDeleted(); 419 this->ptT()->setDeleted();
351 } 420 SkOpPtT* stopPtT = this->ptT();
352 421 SkOpPtT* testPtT = stopPtT;
353 void SkOpSpan::init(SkOpSegment* segment, SkOpSpan* prev, double t, const SkPoin t& pt) { 422 const SkOpSpanBase* keptSpan = kept->span();
354 SkASSERT(t != 1); 423 do {
355 initBase(segment, prev, t, pt); 424 if (this == testPtT->span()) {
356 fCoincident = this; 425 testPtT->setSpan(keptSpan);
357 fToAngle = nullptr; 426 }
358 fWindSum = fOppSum = SK_MinS32; 427 } while ((testPtT = testPtT->next()) != stopPtT);
359 fWindValue = 1;
360 fOppValue = 0;
361 fTopTTry = 0;
362 fChased = fDone = false;
363 segment->bumpCount();
364 fAlreadyAdded = false;
365 } 428 }
366 429
367 void SkOpSpan::setOppSum(int oppSum) { 430 void SkOpSpan::setOppSum(int oppSum) {
368 SkASSERT(!final()); 431 SkASSERT(!final());
369 if (fOppSum != SK_MinS32 && fOppSum != oppSum) { 432 if (fOppSum != SK_MinS32 && fOppSum != oppSum) {
370 this->globalState()->setWindingFailed(); 433 this->globalState()->setWindingFailed();
371 return; 434 return;
372 } 435 }
373 SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(oppSum) <= DEBUG_LIMIT_WIND_SUM); 436 SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(oppSum) <= DEBUG_LIMIT_WIND_SUM);
374 fOppSum = oppSum; 437 fOppSum = oppSum;
375 } 438 }
376 439
377 void SkOpSpan::setWindSum(int windSum) { 440 void SkOpSpan::setWindSum(int windSum) {
378 SkASSERT(!final()); 441 SkASSERT(!final());
379 if (fWindSum != SK_MinS32 && fWindSum != windSum) { 442 if (fWindSum != SK_MinS32 && fWindSum != windSum) {
380 this->globalState()->setWindingFailed(); 443 this->globalState()->setWindingFailed();
381 return; 444 return;
382 } 445 }
383 SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(windSum) <= DEBUG_LIMIT_WIND_SUM); 446 SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(windSum) <= DEBUG_LIMIT_WIND_SUM);
384 fWindSum = windSum; 447 fWindSum = windSum;
385 } 448 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698