OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 #include "SkOpCoincidence.h" | 7 #include "SkOpCoincidence.h" |
8 #include "SkOpSegment.h" | 8 #include "SkOpSegment.h" |
9 #include "SkPathOpsTSect.h" | 9 #include "SkPathOpsTSect.h" |
10 | 10 |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |