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

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

Issue 2321773002: pathops tiger checkpoint (Closed)
Patch Set: checkpoint (all not-under-development tests work) 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/SkOpCoincidence.h ('k') | src/pathops/SkOpSpan.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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 const SkOpSpanBase* oppStart = (flipped() ? oppPtTEnd() : oppPtTStart())->sp an(); 139 const SkOpSpanBase* oppStart = (flipped() ? oppPtTEnd() : oppPtTStart())->sp an();
140 const SkOpSpanBase* oppEnd = (flipped() ? oppPtTStart() : oppPtTEnd())->span (); 140 const SkOpSpanBase* oppEnd = (flipped() ? oppPtTStart() : oppPtTEnd())->span ();
141 int oppIntervals = 0; 141 int oppIntervals = 0;
142 while (oppStart != oppEnd) { 142 while (oppStart != oppEnd) {
143 oppIntervals++; 143 oppIntervals++;
144 oppStart = oppStart->upCast()->next(); 144 oppStart = oppStart->upCast()->next();
145 } 145 }
146 return coinIntervals == oppIntervals ? coinIntervals : -1; 146 return coinIntervals == oppIntervals ? coinIntervals : -1;
147 } 147 }
148 148
149 // A coincident span is unordered if the pairs of points in the main and opposit e curves'
150 // t values do not ascend or descend. For instance, if a tightly arced quadratic is
151 // coincident with another curve, it may intersect it out of order.
152 bool SkCoincidentSpans::ordered() const {
153 const SkOpSpanBase* start = this->coinPtTStart()->span();
154 const SkOpSpanBase* end = this->coinPtTEnd()->span();
155 const SkOpSpanBase* next = start->upCast()->next();
156 if (next == end) {
157 return true;
158 }
159 bool flipped = this->flipped();
160 const SkOpSegment* oppSeg = this->oppPtTStart()->segment();
161 double oppLastT = fOppPtTStart->fT;
162 do {
163 const SkOpPtT* opp = next->contains(oppSeg);
164 if (!opp) {
165 SkASSERT(0); // may assert if coincident span isn't fully processed
166 continue;
167 }
168 if ((oppLastT > opp->fT) != flipped) {
169 return false;
170 }
171 oppLastT = opp->fT;
172 if (next == end) {
173 break;
174 }
175 next = next->upCast()->next();
176 } while (true);
177 return true;
178 }
179
149 // returns true if the point is on a coincident edge, and if it is the start of that edge 180 // returns true if the point is on a coincident edge, and if it is the start of that edge
150 bool SkOpCoincidence::edge(const SkOpPtT* test, bool* start) const { 181 bool SkOpCoincidence::edge(const SkOpPtT* test, bool* start) const {
151 SkCoincidentSpans* coinRec = fHead; 182 SkCoincidentSpans* coinRec = fHead;
152 if (!coinRec) { 183 if (!coinRec) {
153 return false; 184 return false;
154 } 185 }
155 do { 186 do {
156 if (coinRec->coinPtTStart() == test) { 187 if (coinRec->coinPtTStart() == test) {
157 *start = true; 188 *start = true;
158 return true; 189 return true;
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 SkTSwap(coinSeg, oppSeg); 348 SkTSwap(coinSeg, oppSeg);
318 coinTs = oppStart->fT; 349 coinTs = oppStart->fT;
319 coinTe = testPtT->fT; 350 coinTe = testPtT->fT;
320 oppTs = base->t(); 351 oppTs = base->t();
321 oppTe = testSpan->t(); 352 oppTe = testSpan->t();
322 } 353 }
323 if (coinTs > coinTe) { 354 if (coinTs > coinTe) {
324 SkTSwap(coinTs, coinTe); 355 SkTSwap(coinTs, coinTe);
325 SkTSwap(oppTs, oppTe); 356 SkTSwap(oppTs, oppTe);
326 } 357 }
327 if (!this->addOrOverlap(coinSeg, oppSeg, coinTs, coinTe, oppTs, oppT e 358 bool added;
328 SkDEBUGPARAMS(true) /* do assert if addOrOverlap fails */ )) { 359 if (!this->addOrOverlap(coinSeg, oppSeg, coinTs, coinTe, oppTs, oppT e, &added)) {
329 return false; 360 return false;
330 } 361 }
331 } 362 }
332 } 363 }
333 return true; 364 return true;
334 } 365 }
335 366
336 // description below 367 // description below
337 bool SkOpCoincidence::addEndMovedSpans(const SkOpPtT* ptT) { 368 bool SkOpCoincidence::addEndMovedSpans(const SkOpPtT* ptT) {
338 FAIL_IF(!ptT->span()->upCastable()); 369 FAIL_IF(!ptT->span()->upCastable());
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 if (check->oppPtTStart()->segment() != oppSeg) { 630 if (check->oppPtTStart()->segment() != oppSeg) {
600 continue; 631 continue;
601 } 632 }
602 double checkTs = check->coinPtTStart()->fT; 633 double checkTs = check->coinPtTStart()->fT;
603 double checkTe = check->coinPtTEnd()->fT; 634 double checkTe = check->coinPtTEnd()->fT;
604 bool coinOutside = coinTe < checkTs || coinTs > checkTe; 635 bool coinOutside = coinTe < checkTs || coinTs > checkTe;
605 double oCheckTs = check->oppPtTStart()->fT; 636 double oCheckTs = check->oppPtTStart()->fT;
606 double oCheckTe = check->oppPtTEnd()->fT; 637 double oCheckTe = check->oppPtTEnd()->fT;
607 if (swapOpp) { 638 if (swapOpp) {
608 if (oCheckTs <= oCheckTe) { 639 if (oCheckTs <= oCheckTe) {
609 return false; 640 return false;
610 } 641 }
611 SkTSwap(oCheckTs, oCheckTe); 642 SkTSwap(oCheckTs, oCheckTe);
612 } 643 }
613 bool oppOutside = oppTe < oCheckTs || oppTs > oCheckTe; 644 bool oppOutside = oppTe < oCheckTs || oppTs > oCheckTe;
614 if (coinOutside && oppOutside) { 645 if (coinOutside && oppOutside) {
615 continue; 646 continue;
616 } 647 }
617 bool coinInside = coinTe <= checkTe && coinTs >= checkTs; 648 bool coinInside = coinTe <= checkTe && coinTs >= checkTs;
618 bool oppInside = oppTe <= oCheckTe && oppTs >= oCheckTs; 649 bool oppInside = oppTe <= oCheckTe && oppTs >= oCheckTs;
619 if (coinInside && oppInside) { 650 if (coinInside && oppInside) { // already included, do nothing
620 return false; // complete overlap, already included, do nothing 651 return false;
621 } 652 }
622 *overlaps->append() = check; // partial overlap, extend existing entry 653 *overlaps->append() = check; // partial overlap, extend existing entry
623 } while ((check = check->next())); 654 } while ((check = check->next()));
624 return true; 655 return true;
625 } 656 }
626 657
627 /* Please keep this in sync with debugAddIfMissing() */ 658 /* Please keep this in sync with debugAddIfMissing() */
628 // note that over1s, over1e, over2s, over2e are ordered 659 // note that over1s, over1e, over2s, over2e are ordered
629 bool SkOpCoincidence::addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over2s, 660 bool SkOpCoincidence::addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over2s,
630 double tStart, double tEnd, SkOpSegment* coinSeg, SkOpSegment* oppSeg 661 double tStart, double tEnd, SkOpSegment* coinSeg, SkOpSegment* oppSeg, b ool* added
631 SkDEBUGPARAMS(const SkOpPtT* over1e) SkDEBUGPARAMS(const SkOpPtT* over2e )) { 662 SkDEBUGPARAMS(const SkOpPtT* over1e) SkDEBUGPARAMS(const SkOpPtT* over2e )) {
632 SkASSERT(tStart < tEnd); 663 SkASSERT(tStart < tEnd);
633 SkASSERT(over1s->fT < over1e->fT); 664 SkASSERT(over1s->fT < over1e->fT);
634 SkASSERT(between(over1s->fT, tStart, over1e->fT)); 665 SkASSERT(between(over1s->fT, tStart, over1e->fT));
635 SkASSERT(between(over1s->fT, tEnd, over1e->fT)); 666 SkASSERT(between(over1s->fT, tEnd, over1e->fT));
636 SkASSERT(over2s->fT < over2e->fT); 667 SkASSERT(over2s->fT < over2e->fT);
637 SkASSERT(between(over2s->fT, tStart, over2e->fT)); 668 SkASSERT(between(over2s->fT, tStart, over2e->fT));
638 SkASSERT(between(over2s->fT, tEnd, over2e->fT)); 669 SkASSERT(between(over2s->fT, tEnd, over2e->fT));
639 SkASSERT(over1s->segment() == over1e->segment()); 670 SkASSERT(over1s->segment() == over1e->segment());
640 SkASSERT(over2s->segment() == over2e->segment()); 671 SkASSERT(over2s->segment() == over2e->segment());
641 SkASSERT(over1s->segment() == over2s->segment()); 672 SkASSERT(over1s->segment() == over2s->segment());
642 SkASSERT(over1s->segment() != coinSeg); 673 SkASSERT(over1s->segment() != coinSeg);
643 SkASSERT(over1s->segment() != oppSeg); 674 SkASSERT(over1s->segment() != oppSeg);
644 SkASSERT(coinSeg != oppSeg); 675 SkASSERT(coinSeg != oppSeg);
645 double coinTs, coinTe, oppTs, oppTe; 676 double coinTs, coinTe, oppTs, oppTe;
646 coinTs = TRange(over1s, tStart, coinSeg SkDEBUGPARAMS(over1e)); 677 coinTs = TRange(over1s, tStart, coinSeg SkDEBUGPARAMS(over1e));
647 coinTe = TRange(over1s, tEnd, coinSeg SkDEBUGPARAMS(over1e)); 678 coinTe = TRange(over1s, tEnd, coinSeg SkDEBUGPARAMS(over1e));
648 if (coinSeg->collapsed(coinTs, coinTe)) { 679 if (coinSeg->collapsed(coinTs, coinTe)) {
649 return false; 680 return true;
650 } 681 }
651 oppTs = TRange(over2s, tStart, oppSeg SkDEBUGPARAMS(over2e)); 682 oppTs = TRange(over2s, tStart, oppSeg SkDEBUGPARAMS(over2e));
652 oppTe = TRange(over2s, tEnd, oppSeg SkDEBUGPARAMS(over2e)); 683 oppTe = TRange(over2s, tEnd, oppSeg SkDEBUGPARAMS(over2e));
653 if (oppSeg->collapsed(oppTs, oppTe)) { 684 if (oppSeg->collapsed(oppTs, oppTe)) {
654 return false; 685 return true;
655 } 686 }
656 if (coinTs > coinTe) { 687 if (coinTs > coinTe) {
657 SkTSwap(coinTs, coinTe); 688 SkTSwap(coinTs, coinTe);
658 SkTSwap(oppTs, oppTe); 689 SkTSwap(oppTs, oppTe);
659 } 690 }
660 return this->addOrOverlap(coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe 691 return this->addOrOverlap(coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, add ed);
661 SkDEBUGPARAMS(false) /* don't assert if addOrOverlap fails */ );
662 } 692 }
663 693
664 /* Please keep this in sync with debugAddOrOverlap() */ 694 /* Please keep this in sync with debugAddOrOverlap() */
665 // If this is called by addEndMovedSpans(), a returned false propogates out to a n abort. 695 // If this is called by addEndMovedSpans(), a returned false propogates out to a n abort.
666 // If this is called by AddIfMissing(), a returned false indicates there was not hing to add 696 // If this is called by AddIfMissing(), a returned false indicates there was not hing to add
667 bool SkOpCoincidence::addOrOverlap(SkOpSegment* coinSeg, SkOpSegment* oppSeg, 697 bool SkOpCoincidence::addOrOverlap(SkOpSegment* coinSeg, SkOpSegment* oppSeg,
668 double coinTs, double coinTe, double oppTs, double oppTe 698 double coinTs, double coinTe, double oppTs, double oppTe, bool* added) {
669 SkDEBUGPARAMS(bool callerAborts)) {
670 SkTDArray<SkCoincidentSpans*> overlaps; 699 SkTDArray<SkCoincidentSpans*> overlaps;
671 RETURN_FALSE_IF(callerAborts, !fTop); 700 FAIL_IF(!fTop);
672 if (!this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &overlaps)) { 701 if (!this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &overlaps)) {
673 return false; 702 return true;
674 } 703 }
675 if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs, 704 if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs,
676 coinTe, oppTs, oppTe, &overlaps)) { 705 coinTe, oppTs, oppTe, &overlaps)) {
677 return false; 706 return true;
678 } 707 }
679 SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr; 708 SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr;
680 for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps before continuing 709 for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps before continuing
681 SkCoincidentSpans* test = overlaps[index]; 710 SkCoincidentSpans* test = overlaps[index];
682 if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) { 711 if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) {
683 overlap->setCoinPtTStart(test->coinPtTStart()); 712 overlap->setCoinPtTStart(test->coinPtTStart());
684 } 713 }
685 if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) { 714 if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) {
686 overlap->setCoinPtTEnd(test->coinPtTEnd()); 715 overlap->setCoinPtTEnd(test->coinPtTEnd());
687 } 716 }
688 if (overlap->flipped() 717 if (overlap->flipped()
689 ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT 718 ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT
690 : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) { 719 : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) {
691 overlap->setOppPtTStart(test->oppPtTStart()); 720 overlap->setOppPtTStart(test->oppPtTStart());
692 } 721 }
693 if (overlap->flipped() 722 if (overlap->flipped()
694 ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT 723 ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT
695 : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) { 724 : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) {
696 overlap->setOppPtTEnd(test->oppPtTEnd()); 725 overlap->setOppPtTEnd(test->oppPtTEnd());
697 } 726 }
698 if (!fHead || !this->release(fHead, test)) { 727 if (!fHead || !this->release(fHead, test)) {
699 SkAssertResult(this->release(fTop, test)); 728 SkAssertResult(this->release(fTop, test));
700 } 729 }
701 } 730 }
702 const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg); 731 const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg);
703 const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg); 732 const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg);
704 RETURN_FALSE_IF(callerAborts, overlap && cs && ce && overlap->contains(cs, c e)); 733 if (overlap && cs && ce && overlap->contains(cs, ce)) {
705 RETURN_FALSE_IF(callerAborts, cs == ce && cs); 734 return true;
735 }
736 FAIL_IF(cs == ce && cs);
706 const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg); 737 const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg);
707 const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg); 738 const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg);
708 RETURN_FALSE_IF(callerAborts, overlap && os && oe && overlap->contains(os, o e)); 739 if (overlap && os && oe && overlap->contains(os, oe)) {
740 return true;
741 }
709 SkASSERT(!cs || !cs->deleted()); 742 SkASSERT(!cs || !cs->deleted());
710 SkASSERT(!os || !os->deleted()); 743 SkASSERT(!os || !os->deleted());
711 SkASSERT(!ce || !ce->deleted()); 744 SkASSERT(!ce || !ce->deleted());
712 SkASSERT(!oe || !oe->deleted()); 745 SkASSERT(!oe || !oe->deleted());
713 const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullp tr; 746 const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullp tr;
714 const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullp tr; 747 const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullp tr;
715 RETURN_FALSE_IF(callerAborts, csExisting && csExisting == ceExisting); 748 FAIL_IF(csExisting && csExisting == ceExisting);
716 RETURN_FALSE_IF(callerAborts, csExisting && (csExisting == ce || 749 FAIL_IF(csExisting && (csExisting == ce ||
717 csExisting->contains(ceExisting ? ceExisting : ce))); 750 csExisting->contains(ceExisting ? ceExisting : ce)));
718 RETURN_FALSE_IF(callerAborts, ceExisting && (ceExisting == cs || 751 FAIL_IF(ceExisting && (ceExisting == cs ||
719 ceExisting->contains(csExisting ? csExisting : cs))); 752 ceExisting->contains(csExisting ? csExisting : cs)));
720 const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr ; 753 const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr ;
721 const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr ; 754 const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr ;
722 RETURN_FALSE_IF(callerAborts, osExisting && osExisting == oeExisting); 755 FAIL_IF(osExisting && osExisting == oeExisting);
723 RETURN_FALSE_IF(callerAborts, osExisting && (osExisting == oe || 756 FAIL_IF(osExisting && (osExisting == oe ||
724 osExisting->contains(oeExisting ? oeExisting : oe))); 757 osExisting->contains(oeExisting ? oeExisting : oe)));
725 RETURN_FALSE_IF(callerAborts, oeExisting && (oeExisting == os || 758 FAIL_IF(oeExisting && (oeExisting == os ||
726 oeExisting->contains(osExisting ? osExisting : os))); 759 oeExisting->contains(osExisting ? osExisting : os)));
727 // extra line in debug code 760 // extra line in debug code
728 this->debugValidate(); 761 this->debugValidate();
729 if (!cs || !os) { 762 if (!cs || !os) {
730 SkOpPtT* csWritable = cs ? const_cast<SkOpPtT*>(cs) 763 SkOpPtT* csWritable = cs ? const_cast<SkOpPtT*>(cs)
731 : coinSeg->addT(coinTs); 764 : coinSeg->addT(coinTs);
732 SkOpPtT* osWritable = os ? const_cast<SkOpPtT*>(os) 765 SkOpPtT* osWritable = os ? const_cast<SkOpPtT*>(os)
733 : oppSeg->addT(oppTs); 766 : oppSeg->addT(oppTs);
734 RETURN_FALSE_IF(callerAborts, !csWritable || !osWritable); 767 FAIL_IF(!csWritable || !osWritable);
735 csWritable->span()->addOpp(osWritable->span()); 768 csWritable->span()->addOpp(osWritable->span());
736 cs = csWritable; 769 cs = csWritable;
737 os = osWritable->active(); 770 os = osWritable->active();
738 RETURN_FALSE_IF(callerAborts, (ce && ce->deleted()) || (oe && oe->delete d())); 771 FAIL_IF((ce && ce->deleted()) || (oe && oe->deleted()));
739 } 772 }
740 if (!ce || !oe) { 773 if (!ce || !oe) {
741 SkOpPtT* ceWritable = ce ? const_cast<SkOpPtT*>(ce) 774 SkOpPtT* ceWritable = ce ? const_cast<SkOpPtT*>(ce)
742 : coinSeg->addT(coinTe); 775 : coinSeg->addT(coinTe);
743 SkOpPtT* oeWritable = oe ? const_cast<SkOpPtT*>(oe) 776 SkOpPtT* oeWritable = oe ? const_cast<SkOpPtT*>(oe)
744 : oppSeg->addT(oppTe); 777 : oppSeg->addT(oppTe);
745 ceWritable->span()->addOpp(oeWritable->span()); 778 ceWritable->span()->addOpp(oeWritable->span());
746 ce = ceWritable; 779 ce = ceWritable;
747 oe = oeWritable; 780 oe = oeWritable;
748 } 781 }
749 this->debugValidate(); 782 this->debugValidate();
750 RETURN_FALSE_IF(callerAborts, cs->deleted()); 783 FAIL_IF(cs->deleted());
751 RETURN_FALSE_IF(callerAborts, os->deleted()); 784 FAIL_IF(os->deleted());
752 RETURN_FALSE_IF(callerAborts, ce->deleted()); 785 FAIL_IF(ce->deleted());
753 RETURN_FALSE_IF(callerAborts, oe->deleted()); 786 FAIL_IF(oe->deleted());
754 RETURN_FALSE_IF(callerAborts, cs->contains(ce) || os->contains(oe)); 787 FAIL_IF(cs->contains(ce) || os->contains(oe));
755 bool result = true; 788 bool result = true;
756 if (overlap) { 789 if (overlap) {
757 if (overlap->coinPtTStart()->segment() == coinSeg) { 790 if (overlap->coinPtTStart()->segment() == coinSeg) {
758 result = overlap->extend(cs, ce, os, oe); 791 result = overlap->extend(cs, ce, os, oe);
759 } else { 792 } else {
760 if (os->fT > oe->fT) { 793 if (os->fT > oe->fT) {
761 SkTSwap(cs, ce); 794 SkTSwap(cs, ce);
762 SkTSwap(os, oe); 795 SkTSwap(os, oe);
763 } 796 }
764 result = overlap->extend(os, oe, cs, ce); 797 result = overlap->extend(os, oe, cs, ce);
765 } 798 }
766 #if DEBUG_COINCIDENCE_VERBOSE 799 #if DEBUG_COINCIDENCE_VERBOSE
767 if (result) { 800 if (result) {
768 overlaps[0]->debugShow(); 801 overlaps[0]->debugShow();
769 } 802 }
770 #endif 803 #endif
771 } else { 804 } else {
772 this->add(cs, ce, os, oe); 805 this->add(cs, ce, os, oe);
773 #if DEBUG_COINCIDENCE_VERBOSE 806 #if DEBUG_COINCIDENCE_VERBOSE
774 fHead->debugShow(); 807 fHead->debugShow();
775 #endif 808 #endif
776 } 809 }
777 this->debugValidate(); 810 this->debugValidate();
778 return result; 811 if (result) {
812 *added = true;
813 }
814 return true;
779 } 815 }
780 816
781 // Please keep this in sync with debugAddMissing() 817 // Please keep this in sync with debugAddMissing()
782 /* detects overlaps of different coincident runs on same segment */ 818 /* detects overlaps of different coincident runs on same segment */
783 /* does not detect overlaps for pairs without any segments in common */ 819 /* does not detect overlaps for pairs without any segments in common */
784 // returns true if caller should loop again 820 // returns true if caller should loop again
785 bool SkOpCoincidence::addMissing() { 821 bool SkOpCoincidence::addMissing(bool* added) {
786 SkCoincidentSpans* outer = fHead; 822 SkCoincidentSpans* outer = fHead;
823 *added = false;
787 if (!outer) { 824 if (!outer) {
788 return false; 825 return true;
789 } 826 }
790 bool added = false;
791 fTop = outer; 827 fTop = outer;
792 fHead = nullptr; 828 fHead = nullptr;
793 do { 829 do {
794 // addifmissing can modify the list that this is walking 830 // addifmissing can modify the list that this is walking
795 // save head so that walker can iterate over old data unperturbed 831 // save head so that walker can iterate over old data unperturbed
796 // addifmissing adds to head freely then add saved head in the end 832 // addifmissing adds to head freely then add saved head in the end
797 const SkOpPtT* ocs = outer->coinPtTStart(); 833 const SkOpPtT* ocs = outer->coinPtTStart();
798 SkASSERT(!ocs->deleted()); 834 SkASSERT(!ocs->deleted());
799 const SkOpSegment* outerCoin = ocs->segment(); 835 const SkOpSegment* outerCoin = ocs->segment();
800 SkASSERT(!outerCoin->done()); // if it's done, should have already been removed from list 836 SkASSERT(!outerCoin->done()); // if it's done, should have already been removed from list
801 const SkOpPtT* oos = outer->oppPtTStart(); 837 const SkOpPtT* oos = outer->oppPtTStart();
802 if (oos->deleted()) { 838 if (oos->deleted()) {
803 return false; 839 return true;
804 } 840 }
805 const SkOpSegment* outerOpp = oos->segment(); 841 const SkOpSegment* outerOpp = oos->segment();
806 SkASSERT(!outerOpp->done()); 842 SkASSERT(!outerOpp->done());
807 SkOpSegment* outerCoinWritable = const_cast<SkOpSegment*>(outerCoin); 843 SkOpSegment* outerCoinWritable = const_cast<SkOpSegment*>(outerCoin);
808 SkOpSegment* outerOppWritable = const_cast<SkOpSegment*>(outerOpp); 844 SkOpSegment* outerOppWritable = const_cast<SkOpSegment*>(outerOpp);
809 SkCoincidentSpans* inner = outer; 845 SkCoincidentSpans* inner = outer;
810 while ((inner = inner->next())) { 846 while ((inner = inner->next())) {
811 this->debugValidate(); 847 this->debugValidate();
812 double overS, overE; 848 double overS, overE;
813 const SkOpPtT* ics = inner->coinPtTStart(); 849 const SkOpPtT* ics = inner->coinPtTStart();
814 SkASSERT(!ics->deleted()); 850 SkASSERT(!ics->deleted());
815 const SkOpSegment* innerCoin = ics->segment(); 851 const SkOpSegment* innerCoin = ics->segment();
816 SkASSERT(!innerCoin->done()); 852 SkASSERT(!innerCoin->done());
817 const SkOpPtT* ios = inner->oppPtTStart(); 853 const SkOpPtT* ios = inner->oppPtTStart();
818 SkASSERT(!ios->deleted()); 854 SkASSERT(!ios->deleted());
819 const SkOpSegment* innerOpp = ios->segment(); 855 const SkOpSegment* innerOpp = ios->segment();
820 SkASSERT(!innerOpp->done()); 856 SkASSERT(!innerOpp->done());
821 SkOpSegment* innerCoinWritable = const_cast<SkOpSegment*>(innerCoin) ; 857 SkOpSegment* innerCoinWritable = const_cast<SkOpSegment*>(innerCoin) ;
822 SkOpSegment* innerOppWritable = const_cast<SkOpSegment*>(innerOpp); 858 SkOpSegment* innerOppWritable = const_cast<SkOpSegment*>(innerOpp);
823 if (outerCoin == innerCoin) { 859 if (outerCoin == innerCoin) {
824 const SkOpPtT* oce = outer->coinPtTEnd(); 860 const SkOpPtT* oce = outer->coinPtTEnd();
825 if (oce->deleted()) { 861 if (oce->deleted()) {
826 return false; 862 return true;
827 } 863 }
828 const SkOpPtT* ice = inner->coinPtTEnd(); 864 const SkOpPtT* ice = inner->coinPtTEnd();
829 SkASSERT(!ice->deleted()); 865 SkASSERT(!ice->deleted());
830 if (outerOpp != innerOpp && this->overlap(ocs, oce, ics, ice, &o verS, &overE)) { 866 if (outerOpp != innerOpp && this->overlap(ocs, oce, ics, ice, &o verS, &overE)) {
831 added |= this->addIfMissing(ocs->starter(oce), ics->starter( ice), 867 (void) this->addIfMissing(ocs->starter(oce), ics->starter(ic e),
832 overS, overE, outerOppWritable, innerOppWritable 868 overS, overE, outerOppWritable, innerOppWritable, ad ded
833 SkDEBUGPARAMS(ocs->debugEnder(oce)) 869 SkDEBUGPARAMS(ocs->debugEnder(oce))
834 SkDEBUGPARAMS(ics->debugEnder(ice))); 870 SkDEBUGPARAMS(ics->debugEnder(ice)));
835 } 871 }
836 } else if (outerCoin == innerOpp) { 872 } else if (outerCoin == innerOpp) {
837 const SkOpPtT* oce = outer->coinPtTEnd(); 873 const SkOpPtT* oce = outer->coinPtTEnd();
838 SkASSERT(!oce->deleted()); 874 SkASSERT(!oce->deleted());
839 const SkOpPtT* ioe = inner->oppPtTEnd(); 875 const SkOpPtT* ioe = inner->oppPtTEnd();
840 SkASSERT(!ioe->deleted()); 876 SkASSERT(!ioe->deleted());
841 if (outerOpp != innerCoin && this->overlap(ocs, oce, ios, ioe, & overS, &overE)) { 877 if (outerOpp != innerCoin && this->overlap(ocs, oce, ios, ioe, & overS, &overE)) {
842 added |= this->addIfMissing(ocs->starter(oce), ios->starter( ioe), 878 (void) this->addIfMissing(ocs->starter(oce), ios->starter(io e),
843 overS, overE, outerOppWritable, innerCoinWritable 879 overS, overE, outerOppWritable, innerCoinWritable, a dded
844 SkDEBUGPARAMS(ocs->debugEnder(oce)) 880 SkDEBUGPARAMS(ocs->debugEnder(oce))
845 SkDEBUGPARAMS(ios->debugEnder(ioe))); 881 SkDEBUGPARAMS(ios->debugEnder(ioe)));
846 } 882 }
847 } else if (outerOpp == innerCoin) { 883 } else if (outerOpp == innerCoin) {
848 const SkOpPtT* ooe = outer->oppPtTEnd(); 884 const SkOpPtT* ooe = outer->oppPtTEnd();
849 SkASSERT(!ooe->deleted()); 885 SkASSERT(!ooe->deleted());
850 const SkOpPtT* ice = inner->coinPtTEnd(); 886 const SkOpPtT* ice = inner->coinPtTEnd();
851 SkASSERT(!ice->deleted()); 887 SkASSERT(!ice->deleted());
852 SkASSERT(outerCoin != innerOpp); 888 SkASSERT(outerCoin != innerOpp);
853 if (this->overlap(oos, ooe, ics, ice, &overS, &overE)) { 889 if (this->overlap(oos, ooe, ics, ice, &overS, &overE)) {
854 added |= this->addIfMissing(oos->starter(ooe), ics->starter( ice), 890 (void) this->addIfMissing(oos->starter(ooe), ics->starter(ic e),
855 overS, overE, outerCoinWritable, innerOppWritable 891 overS, overE, outerCoinWritable, innerOppWritable, a dded
856 SkDEBUGPARAMS(oos->debugEnder(ooe)) 892 SkDEBUGPARAMS(oos->debugEnder(ooe))
857 SkDEBUGPARAMS(ics->debugEnder(ice))); 893 SkDEBUGPARAMS(ics->debugEnder(ice)));
858 } 894 }
859 } else if (outerOpp == innerOpp) { 895 } else if (outerOpp == innerOpp) {
860 const SkOpPtT* ooe = outer->oppPtTEnd(); 896 const SkOpPtT* ooe = outer->oppPtTEnd();
861 SkASSERT(!ooe->deleted()); 897 SkASSERT(!ooe->deleted());
862 const SkOpPtT* ioe = inner->oppPtTEnd(); 898 const SkOpPtT* ioe = inner->oppPtTEnd();
863 if (ioe->deleted()) { 899 if (ioe->deleted()) {
864 return false; 900 return true;
865 } 901 }
866 SkASSERT(outerCoin != innerCoin); 902 SkASSERT(outerCoin != innerCoin);
867 if (this->overlap(oos, ooe, ios, ioe, &overS, &overE)) { 903 if (this->overlap(oos, ooe, ios, ioe, &overS, &overE)) {
868 added |= this->addIfMissing(oos->starter(ooe), ios->starter( ioe), 904 (void) this->addIfMissing(oos->starter(ooe), ios->starter(io e),
869 overS, overE, outerCoinWritable, innerCoinWritable 905 overS, overE, outerCoinWritable, innerCoinWritable, added
870 SkDEBUGPARAMS(oos->debugEnder(ooe)) 906 SkDEBUGPARAMS(oos->debugEnder(ooe))
871 SkDEBUGPARAMS(ios->debugEnder(ioe))); 907 SkDEBUGPARAMS(ios->debugEnder(ioe)));
872 } 908 }
873 } 909 }
874 this->debugValidate(); 910 this->debugValidate();
875 } 911 }
876 } while ((outer = outer->next())); 912 } while ((outer = outer->next()));
877 this->restoreHead(); 913 this->restoreHead();
878 return added; 914 return true;
879 } 915 }
880 916
881 bool SkOpCoincidence::addOverlap(const SkOpSegment* seg1, const SkOpSegment* seg 1o, 917 bool SkOpCoincidence::addOverlap(const SkOpSegment* seg1, const SkOpSegment* seg 1o,
882 const SkOpSegment* seg2, const SkOpSegment* seg2o, 918 const SkOpSegment* seg2, const SkOpSegment* seg2o,
883 const SkOpPtT* overS, const SkOpPtT* overE) { 919 const SkOpPtT* overS, const SkOpPtT* overE) {
884 const SkOpPtT* s1, * e1, * s2, * e2; 920 const SkOpPtT* s1, * e1, * s2, * e2;
885 if (!(s1 = overS->find(seg1))) { 921 if (!(s1 = overS->find(seg1))) {
886 return true; 922 return true;
887 } 923 }
888 if (!(e1 = overE->find(seg1))) { 924 if (!(e1 = overE->find(seg1))) {
(...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after
1448 } 1484 }
1449 1485
1450 // Please keep this in sync with debugMark() 1486 // Please keep this in sync with debugMark()
1451 /* this sets up the coincidence links in the segments when the coincidence cross es multiple spans */ 1487 /* this sets up the coincidence links in the segments when the coincidence cross es multiple spans */
1452 bool SkOpCoincidence::mark() { 1488 bool SkOpCoincidence::mark() {
1453 SkCoincidentSpans* coin = fHead; 1489 SkCoincidentSpans* coin = fHead;
1454 if (!coin) { 1490 if (!coin) {
1455 return true; 1491 return true;
1456 } 1492 }
1457 do { 1493 do {
1458 if (!coin->coinPtTStartWritable()->span()->upCastable()) { 1494 FAIL_IF(!coin->coinPtTStartWritable()->span()->upCastable());
1459 return false;
1460 }
1461 SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast(); 1495 SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast();
1462 SkASSERT(!start->deleted()); 1496 SkASSERT(!start->deleted());
1463 SkOpSpanBase* end = coin->coinPtTEndWritable()->span(); 1497 SkOpSpanBase* end = coin->coinPtTEndWritable()->span();
1464 SkASSERT(!end->deleted()); 1498 SkASSERT(!end->deleted());
1465 SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span(); 1499 SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span();
1466 if (oStart->deleted()) { 1500 FAIL_IF(oStart->deleted());
1467 return false;
1468 }
1469 SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span(); 1501 SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span();
1470 SkASSERT(!oEnd->deleted()); 1502 SkASSERT(!oEnd->deleted());
1471 bool flipped = coin->flipped(); 1503 bool flipped = coin->flipped();
1472 if (flipped) { 1504 if (flipped) {
1473 SkTSwap(oStart, oEnd); 1505 SkTSwap(oStart, oEnd);
1474 } 1506 }
1475 /* coin and opp spans may not match up. Mark the ends, and then let the interior 1507 /* coin and opp spans may not match up. Mark the ends, and then let the interior
1476 get marked as many times as the spans allow */ 1508 get marked as many times as the spans allow */
1477 start->insertCoincidence(oStart->upCast()); 1509 start->insertCoincidence(oStart->upCast());
1478 end->insertCoinEnd(oEnd); 1510 end->insertCoinEnd(oEnd);
1479 const SkOpSegment* segment = start->segment(); 1511 const SkOpSegment* segment = start->segment();
1480 const SkOpSegment* oSegment = oStart->segment(); 1512 const SkOpSegment* oSegment = oStart->segment();
1481 SkOpSpanBase* next = start; 1513 SkOpSpanBase* next = start;
1482 SkOpSpanBase* oNext = oStart; 1514 SkOpSpanBase* oNext = oStart;
1515 bool ordered = coin->ordered();
1483 while ((next = next->upCast()->next()) != end) { 1516 while ((next = next->upCast()->next()) != end) {
1484 if (!next->upCastable()) { 1517 FAIL_IF(!next->upCastable());
1485 return false; 1518 if (!next->upCast()->insertCoincidence(oSegment, flipped, ordered)) {
1486 }
1487 if (!next->upCast()->insertCoincidence(oSegment, flipped)) {
1488 return false; 1519 return false;
1489 } 1520 }
1490 } 1521 }
1491 while ((oNext = oNext->upCast()->next()) != oEnd) { 1522 while ((oNext = oNext->upCast()->next()) != oEnd) {
1492 if (!oNext->upCastable()) { 1523 FAIL_IF(!oNext->upCastable());
1493 return false; 1524 if (!oNext->upCast()->insertCoincidence(segment, flipped, ordered)) {
1494 }
1495 if (!oNext->upCast()->insertCoincidence(segment, flipped)) {
1496 return false; 1525 return false;
1497 } 1526 }
1498 } 1527 }
1499 } while ((coin = coin->next())); 1528 } while ((coin = coin->next()));
1500 return true; 1529 return true;
1501 } 1530 }
1502 1531
1503 // Please keep in sync with debugMarkCollapsed() 1532 // Please keep in sync with debugMarkCollapsed()
1504 void SkOpCoincidence::markCollapsed(SkCoincidentSpans* coin, SkOpPtT* test) { 1533 void SkOpCoincidence::markCollapsed(SkCoincidentSpans* coin, SkOpPtT* test) {
1505 SkCoincidentSpans* head = coin; 1534 SkCoincidentSpans* head = coin;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1568 this->release(fHead, coin); 1597 this->release(fHead, coin);
1569 } 1598 }
1570 } while ((coin = coin->next())); 1599 } while ((coin = coin->next()));
1571 } 1600 }
1572 1601
1573 bool SkOpCoincidence::testForCoincidence(const SkCoincidentSpans* outer, const S kOpPtT* testS, 1602 bool SkOpCoincidence::testForCoincidence(const SkCoincidentSpans* outer, const S kOpPtT* testS,
1574 const SkOpPtT* testE) const { 1603 const SkOpPtT* testE) const {
1575 return testS->segment()->testForCoincidence(testS, testE, testS->span(), 1604 return testS->segment()->testForCoincidence(testS, testE, testS->span(),
1576 testE->span(), outer->coinPtTStart()->segment()); 1605 testE->span(), outer->coinPtTStart()->segment());
1577 } 1606 }
OLDNEW
« no previous file with comments | « src/pathops/SkOpCoincidence.h ('k') | src/pathops/SkOpSpan.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698