| 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 |