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

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

Issue 2237223002: pathops coincident work (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: remove unused code Created 4 years, 3 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/SkOpSpan.h ('k') | src/pathops/SkPathOpsCommon.cpp » ('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 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"
11 11
12 bool SkOpPtT::alias() const { 12 bool SkOpPtT::alias() const {
13 return this->span()->ptT() != this; 13 return this->span()->ptT() != this;
14 } 14 }
15 15
16 const SkOpPtT* SkOpPtT::active() const {
17 if (!fDeleted) {
18 return this;
19 }
20 const SkOpPtT* ptT = this;
21 const SkOpPtT* stopPtT = ptT;
22 while ((ptT = ptT->next()) != stopPtT) {
23 if (ptT->fSpan == fSpan && !ptT->fDeleted) {
24 return ptT;
25 }
26 }
27 SkASSERT(0); // should never return deleted
28 return this;
29 }
30
16 bool SkOpPtT::collapsed(const SkOpPtT* check) const { 31 bool SkOpPtT::collapsed(const SkOpPtT* check) const {
17 if (fPt != check->fPt) { 32 if (fPt != check->fPt) {
18 return false; 33 return false;
19 } 34 }
20 SkASSERT(this != check); 35 SkASSERT(this != check);
21 const SkOpSegment* segment = this->segment(); 36 const SkOpSegment* segment = this->segment();
22 SkASSERT(segment == check->segment()); 37 SkASSERT(segment == check->segment());
23 return segment->collapsed(); 38 return segment->collapsed();
24 } 39 }
25 40
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 SkOpSegment* SkOpPtT::segment() { 185 SkOpSegment* SkOpPtT::segment() {
171 return span()->segment(); 186 return span()->segment();
172 } 187 }
173 188
174 void SkOpPtT::setDeleted() { 189 void SkOpPtT::setDeleted() {
175 SkASSERT(this->span()->debugDeleted() || this->span()->ptT() != this); 190 SkASSERT(this->span()->debugDeleted() || this->span()->ptT() != this);
176 SkOPASSERT(!fDeleted); 191 SkOPASSERT(!fDeleted);
177 fDeleted = true; 192 fDeleted = true;
178 } 193 }
179 194
180 // please keep this in sync with debugAddOppAndMerge 195 void SkOpSpanBase::addOpp(SkOpSpanBase* opp) {
181 // If the added points envelop adjacent spans, merge them in.
182 void SkOpSpanBase::addOppAndMerge(SkOpSpanBase* opp) {
183 SkOpPtT* oppPrev = this->ptT()->oppPrev(opp->ptT()); 196 SkOpPtT* oppPrev = this->ptT()->oppPrev(opp->ptT());
184 if (oppPrev) { 197 if (!oppPrev) {
185 this->ptT()->addOpp(opp->ptT(), oppPrev);
186 this->checkForCollapsedCoincidence();
187 }
188 // compute bounds of points in span
189 SkPathOpsBounds bounds;
190 bounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_ScalarMin);
191 const SkOpPtT* head = this->ptT();
192 const SkOpPtT* nextPt = head;
193 do {
194 bounds.add(nextPt->fPt);
195 } while ((nextPt = nextPt->next()) != head);
196 if (!bounds.width() && !bounds.height()) {
197 return; 198 return;
198 } 199 }
199 this->mergeContained(bounds); 200 this->mergeMatches(opp);
200 opp->mergeContained(bounds); 201 this->ptT()->addOpp(opp->ptT(), oppPrev);
202 this->checkForCollapsedCoincidence();
201 } 203 }
202 204
203 // Please keep this in sync with debugMergeContained() 205 // Please keep this in sync with debugMergeContained()
204 void SkOpSpanBase::mergeContained(const SkPathOpsBounds& bounds) { 206 void SkOpSpanBase::mergeContained(const SkPathOpsBounds& bounds) {
205 // while adjacent spans' points are contained by the bounds, merge them 207 // while adjacent spans' points are contained by the bounds, merge them
206 SkOpSpanBase* prev = this; 208 SkOpSpanBase* prev = this;
207 SkOpSegment* seg = this->segment(); 209 SkOpSegment* seg = this->segment();
208 while ((prev = prev->prev()) && bounds.contains(prev->pt()) && !seg->ptsDisj oint(prev, this)) { 210 while ((prev = prev->prev()) && bounds.contains(prev->pt()) && !seg->ptsDisj oint(prev, this)) {
209 if (prev->prev()) { 211 this->mergeMatches(prev);
210 this->merge(prev->upCast()); 212 this->addOpp(prev);
211 prev = this;
212 } else if (this->final()) {
213 seg->clearAll();
214 return;
215 } else {
216 prev->merge(this->upCast());
217 }
218 } 213 }
219 SkOpSpanBase* current = this;
220 SkOpSpanBase* next = this; 214 SkOpSpanBase* next = this;
221 while (next->upCastable() && (next = next->upCast()->next()) 215 while (next->upCastable() && (next = next->upCast()->next())
222 && bounds.contains(next->pt()) && !seg->ptsDisjoint(this, next)) { 216 && bounds.contains(next->pt()) && !seg->ptsDisjoint(this, next)) {
223 if (!current->prev() && next->final()) { 217 this->mergeMatches(next);
224 seg->clearAll(); 218 this->addOpp(next);
225 return;
226 }
227 if (current->prev()) {
228 next->merge(current->upCast());
229 current = next;
230 } else {
231 current->merge(next->upCast());
232 // extra line in debug version
233 }
234 } 219 }
235 #if DEBUG_COINCIDENCE 220 #if DEBUG_COINCIDENCE
236 this->globalState()->coincidence()->debugValidate(); 221 this->globalState()->coincidence()->debugValidate();
237 #endif 222 #endif
238 } 223 }
239 224
225 bool SkOpSpanBase::collapsed(double s, double e) const {
226 const SkOpPtT* start = &fPtT;
227 const SkOpPtT* walk = start;
228 double min = walk->fT;
229 double max = min;
230 const SkOpSegment* segment = this->segment();
231 while ((walk = walk->next()) != start) {
232 if (walk->segment() != segment) {
233 continue;
234 }
235 min = SkTMin(min, walk->fT);
236 max = SkTMax(max, walk->fT);
237 if (between(min, s, max) && between(min, e, max)) {
238 return true;
239 }
240 }
241 return false;
242 }
243
240 bool SkOpSpanBase::contains(const SkOpSpanBase* span) const { 244 bool SkOpSpanBase::contains(const SkOpSpanBase* span) const {
241 const SkOpPtT* start = &fPtT; 245 const SkOpPtT* start = &fPtT;
242 const SkOpPtT* check = &span->fPtT; 246 const SkOpPtT* check = &span->fPtT;
243 SkOPASSERT(start != check); 247 SkOPASSERT(start != check);
244 const SkOpPtT* walk = start; 248 const SkOpPtT* walk = start;
245 while ((walk = walk->next()) != start) { 249 while ((walk = walk->next()) != start) {
246 if (walk == check) { 250 if (walk == check) {
247 return true; 251 return true;
248 } 252 }
249 } 253 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 fSegment = segment; 291 fSegment = segment;
288 fPtT.init(this, t, pt, false); 292 fPtT.init(this, t, pt, false);
289 fCoinEnd = this; 293 fCoinEnd = this;
290 fFromAngle = nullptr; 294 fFromAngle = nullptr;
291 fPrev = prev; 295 fPrev = prev;
292 fSpanAdds = 0; 296 fSpanAdds = 0;
293 fAligned = true; 297 fAligned = true;
294 fChased = false; 298 fChased = false;
295 SkDEBUGCODE(fCount = 1); 299 SkDEBUGCODE(fCount = 1);
296 SkDEBUGCODE(fID = globalState()->nextSpanID()); 300 SkDEBUGCODE(fID = globalState()->nextSpanID());
297 SkDEBUGCODE(fDeleted = false); 301 SkDEBUGCODE(fDebugDeleted = false);
298 } 302 }
299 303
300 // this pair of spans share a common t value or point; merge them and eliminate duplicates 304 // this pair of spans share a common t value or point; merge them and eliminate duplicates
301 // this does not compute the best t or pt value; this merely moves all data into a single list 305 // this does not compute the best t or pt value; this merely moves all data into a single list
302 void SkOpSpanBase::merge(SkOpSpan* span) { 306 void SkOpSpanBase::merge(SkOpSpan* span) {
303 SkOpPtT* spanPtT = span->ptT(); 307 SkOpPtT* spanPtT = span->ptT();
304 SkASSERT(this->t() != spanPtT->fT); 308 SkASSERT(this->t() != spanPtT->fT);
305 SkASSERT(!zero_or_one(spanPtT->fT)); 309 SkASSERT(!zero_or_one(spanPtT->fT));
306 span->release(this->ptT()); 310 span->release(this->ptT());
307 if (this->contains(span)) { 311 if (this->contains(span)) {
312 SkOPASSERT(0); // check to see if this ever happens -- should have been found earlier
308 return; // merge is already in the ptT loop 313 return; // merge is already in the ptT loop
309 } 314 }
310 SkOpPtT* remainder = spanPtT->next(); 315 SkOpPtT* remainder = spanPtT->next();
311 this->ptT()->insert(spanPtT); 316 this->ptT()->insert(spanPtT);
312 while (remainder != spanPtT) { 317 while (remainder != spanPtT) {
313 SkOpPtT* next = remainder->next(); 318 SkOpPtT* next = remainder->next();
314 SkOpPtT* compare = spanPtT->next(); 319 SkOpPtT* compare = spanPtT->next();
315 while (compare != spanPtT) { 320 while (compare != spanPtT) {
316 SkOpPtT* nextC = compare->next(); 321 SkOpPtT* nextC = compare->next();
317 if (nextC->span() == remainder->span() && nextC->fT == remainder->fT ) { 322 if (nextC->span() == remainder->span() && nextC->fT == remainder->fT ) {
318 goto tryNextRemainder; 323 goto tryNextRemainder;
319 } 324 }
320 compare = nextC; 325 compare = nextC;
321 } 326 }
322 spanPtT->insert(remainder); 327 spanPtT->insert(remainder);
323 tryNextRemainder: 328 tryNextRemainder:
324 remainder = next; 329 remainder = next;
325 } 330 }
326 fSpanAdds += span->fSpanAdds; 331 fSpanAdds += span->fSpanAdds;
327 this->checkForCollapsedCoincidence(); 332 }
333
334 SkOpSpanBase* SkOpSpanBase::active() {
335 SkOpSpanBase* result = fPrev ? fPrev->next() : upCast()->next()->prev();
336 SkASSERT(this == result || fDebugDeleted);
337 return result;
328 } 338 }
329 339
330 // please keep in sync with debugCheckForCollapsedCoincidence() 340 // please keep in sync with debugCheckForCollapsedCoincidence()
331 void SkOpSpanBase::checkForCollapsedCoincidence() { 341 void SkOpSpanBase::checkForCollapsedCoincidence() {
332 SkOpCoincidence* coins = this->globalState()->coincidence(); 342 SkOpCoincidence* coins = this->globalState()->coincidence();
333 if (coins->isEmpty()) { 343 if (coins->isEmpty()) {
334 return; 344 return;
335 } 345 }
336 // the insert above may have put both ends of a coincident run in the same span 346 // the insert above may have put both ends of a coincident run in the same span
337 // for each coincident ptT in loop; see if its opposite in is also in the loop 347 // for each coincident ptT in loop; see if its opposite in is also in the loop
338 // this implementation is the motivation for marking that a ptT is referenced by a coincident span 348 // this implementation is the motivation for marking that a ptT is referenced by a coincident span
339 SkOpPtT* head = this->ptT(); 349 SkOpPtT* head = this->ptT();
340 SkOpPtT* test = head; 350 SkOpPtT* test = head;
341 do { 351 do {
342 if (!test->coincident()) { 352 if (!test->coincident()) {
343 continue; 353 continue;
344 } 354 }
345 coins->markCollapsed(test); 355 coins->markCollapsed(test);
346 } while ((test = test->next()) != head); 356 } while ((test = test->next()) != head);
357 coins->releaseDeleted();
358 }
359
360 // please keep in sync with debugMergeMatches()
361 // Look to see if pt-t linked list contains same segment more than once
362 // if so, and if each pt-t is directly pointed to by spans in that segment,
363 // merge them
364 // keep the points, but remove spans so that the segment doesn't have 2 or more
365 // spans pointing to the same pt-t loop at different loop elements
366 void SkOpSpanBase::mergeMatches(SkOpSpanBase* opp) {
367 SkOpPtT* test = &fPtT;
368 SkOpPtT* testNext;
369 const SkOpPtT* stop = test;
370 do {
371 testNext = test->next();
372 if (test->deleted()) {
373 continue;
374 }
375 SkOpSpanBase* testBase = test->span();
376 SkASSERT(testBase->ptT() == test);
377 SkOpSegment* segment = test->segment();
378 if (segment->done()) {
379 continue;
380 }
381 SkOpPtT* inner = opp->ptT();
382 const SkOpPtT* innerStop = inner;
383 do {
384 if (inner->segment() != segment) {
385 continue;
386 }
387 if (inner->deleted()) {
388 continue;
389 }
390 SkOpSpanBase* innerBase = inner->span();
391 SkASSERT(innerBase->ptT() == inner);
392 // when the intersection is first detected, the span base is marked if there are
393 // more than one point in the intersection.
394 if (!zero_or_one(inner->fT)) {
395 innerBase->upCast()->release(test);
396 } else {
397 SkASSERT(inner->fT != test->fT);
398 if (!zero_or_one(test->fT)) {
399 testBase->upCast()->release(inner);
400 } else {
401 segment->markAllDone(); // mark segment as collapsed
402 SkDEBUGCODE(testBase->debugSetDeleted());
403 test->setDeleted();
404 SkDEBUGCODE(innerBase->debugSetDeleted());
405 inner->setDeleted();
406 }
407 }
408 #ifdef SK_DEBUG // assert if another undeleted entry points to segment
409 const SkOpPtT* debugInner = inner;
410 while ((debugInner = debugInner->next()) != innerStop) {
411 if (debugInner->segment() != segment) {
412 continue;
413 }
414 if (debugInner->deleted()) {
415 continue;
416 }
417 SkOPASSERT(0);
418 }
419 #endif
420 break;
421 } while ((inner = inner->next()) != innerStop);
422 } while ((test = testNext) != stop);
423 this->checkForCollapsedCoincidence();
347 } 424 }
348 425
349 int SkOpSpan::computeWindSum() { 426 int SkOpSpan::computeWindSum() {
350 SkOpGlobalState* globals = this->globalState(); 427 SkOpGlobalState* globals = this->globalState();
351 SkOpContour* contourHead = globals->contourHead(); 428 SkOpContour* contourHead = globals->contourHead();
352 int windTry = 0; 429 int windTry = 0;
353 while (!this->sortableTop(contourHead) && ++windTry < SkOpGlobalState::kMaxW indingTries) { 430 while (!this->sortableTop(contourHead) && ++windTry < SkOpGlobalState::kMaxW indingTries) {
354 ; 431 ;
355 } 432 }
356 return this->windSum(); 433 return this->windSum();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 return true; 483 return true;
407 } 484 }
408 } 485 }
409 #if DEBUG_COINCIDENCE 486 #if DEBUG_COINCIDENCE
410 SkASSERT(0); // FIXME? if we get here, the span is missing its opposite segm ent... 487 SkASSERT(0); // FIXME? if we get here, the span is missing its opposite segm ent...
411 #endif 488 #endif
412 return true; 489 return true;
413 } 490 }
414 491
415 void SkOpSpan::release(const SkOpPtT* kept) { 492 void SkOpSpan::release(const SkOpPtT* kept) {
416 SkDEBUGCODE(fDeleted = true); 493 SkDEBUGCODE(fDebugDeleted = true);
417 SkASSERT(kept->span() != this); 494 SkASSERT(kept->span() != this);
418 SkASSERT(!final()); 495 SkASSERT(!final());
419 SkOpSpan* prev = this->prev(); 496 SkOpSpan* prev = this->prev();
420 SkASSERT(prev); 497 SkASSERT(prev);
421 SkOpSpanBase* next = this->next(); 498 SkOpSpanBase* next = this->next();
422 SkASSERT(next); 499 SkASSERT(next);
423 prev->setNext(next); 500 prev->setNext(next);
424 next->setPrev(prev); 501 next->setPrev(prev);
425 this->segment()->release(this); 502 this->segment()->release(this);
426 SkOpCoincidence* coincidence = this->globalState()->coincidence(); 503 SkOpCoincidence* coincidence = this->globalState()->coincidence();
(...skipping 23 matching lines...) Expand all
450 527
451 void SkOpSpan::setWindSum(int windSum) { 528 void SkOpSpan::setWindSum(int windSum) {
452 SkASSERT(!final()); 529 SkASSERT(!final());
453 if (fWindSum != SK_MinS32 && fWindSum != windSum) { 530 if (fWindSum != SK_MinS32 && fWindSum != windSum) {
454 this->globalState()->setWindingFailed(); 531 this->globalState()->setWindingFailed();
455 return; 532 return;
456 } 533 }
457 SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(windSum) <= DEBUG_LIMIT_WIND_SUM); 534 SkASSERT(!DEBUG_LIMIT_WIND_SUM || SkTAbs(windSum) <= DEBUG_LIMIT_WIND_SUM);
458 fWindSum = windSum; 535 fWindSum = windSum;
459 } 536 }
OLDNEW
« no previous file with comments | « src/pathops/SkOpSpan.h ('k') | src/pathops/SkPathOpsCommon.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698