1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2015 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOpCoincidence.h" 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOpSegment.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathOpsTSect.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// returns true if coincident span's start and end are the same 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkCoincidentSpans::collapsed(const SkOpPtT* test) const { 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return (fCoinPtTStart == test && fCoinPtTEnd->contains(test)) 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || (fCoinPtTEnd == test && fCoinPtTStart->contains(test)) 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || (fOppPtTStart == test && fOppPtTEnd->contains(test)) 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || (fOppPtTEnd == test && fOppPtTStart->contains(test)); 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// out of line since this function is referenced by address 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkOpPtT* SkCoincidentSpans::coinPtTEnd() const { 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fCoinPtTEnd; 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// out of line since this function is referenced by address 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkOpPtT* SkCoincidentSpans::coinPtTStart() const { 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fCoinPtTStart; 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// sets the span's end to the ptT referenced by the previous-next 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkCoincidentSpans::correctOneEnd( 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* (SkCoincidentSpans::* getEnd)() const, 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void (SkCoincidentSpans::*setEnd)(const SkOpPtT* ptT) ) { 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* origPtT = (this->*getEnd)(); 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* origSpan = origPtT->span(); 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* prev = origSpan->prev(); 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* testPtT = prev ? prev->next()->ptT() 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : origSpan->upCast()->next()->prev()->ptT(); 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (origPtT != testPtT) { 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (this->*setEnd)(testPtT); 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* Please keep this in sync with debugCorrectEnds */ 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// FIXME: member pointers have fallen out of favor and can be replaced with 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// an alternative approach. 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// makes all span ends agree with the segment's spans that define them 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkCoincidentSpans::correctEnds() { 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->correctOneEnd(&SkCoincidentSpans::coinPtTStart, &SkCoincidentSpans::setCoinPtTStart); 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->correctOneEnd(&SkCoincidentSpans::coinPtTEnd, &SkCoincidentSpans::setCoinPtTEnd); 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->correctOneEnd(&SkCoincidentSpans::oppPtTStart, &SkCoincidentSpans::setOppPtTStart); 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->correctOneEnd(&SkCoincidentSpans::oppPtTEnd, &SkCoincidentSpans::setOppPtTEnd); 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* Please keep this in sync with debugExpand */ 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// expand the range by checking adjacent spans for coincidence 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkCoincidentSpans::expand() { 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool expanded = false; 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* segment = coinPtTStart()->segment(); 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* oppSegment = oppPtTStart()->segment(); 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* start = coinPtTStart()->span()->upCast(); 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* prev = start->prev(); 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oppPtT; 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!prev || !(oppPtT = prev->contains(oppSegment))) { 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double midT = (prev->t() + start->t()) / 2; 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!segment->isClose(midT, oppSegment)) { 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot setStarts(prev->ptT(), oppPtT); 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot expanded = true; 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (true); 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* end = coinPtTEnd()->span(); 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* next = end->final() ? nullptr : end->upCast()->next(); 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next && next->deleted()) { 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oppPtT; 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!next || !(oppPtT = next->contains(oppSegment))) { 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double midT = (end->t() + next->t()) / 2; 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!segment->isClose(midT, oppSegment)) { 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot setEnds(next->ptT(), oppPtT); 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot expanded = true; 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (true); 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return expanded; 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// increase the range of this span 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkCoincidentSpans::extend(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) { 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool result = false; 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fCoinPtTStart->fT > coinPtTStart->fT || (this->flipped() 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ? fOppPtTStart->fT < oppPtTStart->fT : fOppPtTStart->fT > oppPtTStart->fT)) { 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->setStarts(coinPtTStart, oppPtTStart); 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = true; 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fCoinPtTEnd->fT < coinPtTEnd->fT || (this->flipped() 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ? fOppPtTEnd->fT > oppPtTEnd->fT : fOppPtTEnd->fT < oppPtTEnd->fT)) { 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->setEnds(coinPtTEnd, oppPtTEnd); 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = true; 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return result; 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// set the range of this span 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkCoincidentSpans::set(SkCoincidentSpans* next, const SkOpPtT* coinPtTStart, 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* coinPtTEnd, const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) { 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(SkOpCoincidence::Ordered(coinPtTStart, oppPtTStart)); 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fNext = next; 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->setStarts(coinPtTStart, oppPtTStart); 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->setEnds(coinPtTEnd, oppPtTEnd); 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// returns true if both points are inside this 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkCoincidentSpans::contains(const SkOpPtT* s, const SkOpPtT* e) const { 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (s->fT > e->fT) { 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(s, e); 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (s->segment() == fCoinPtTStart->segment()) { 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fCoinPtTStart->fT <= s->fT && e->fT <= fCoinPtTEnd->fT; 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(s->segment() == fOppPtTStart->segment()); 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oppTs = fOppPtTStart->fT; 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oppTe = fOppPtTEnd->fT; 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppTs > oppTe) { 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(oppTs, oppTe); 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return oppTs <= s->fT && e->fT <= oppTe; 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// out of line since this function is referenced by address 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkOpPtT* SkCoincidentSpans::oppPtTStart() const { 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fOppPtTStart; 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// out of line since this function is referenced by address 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkOpPtT* SkCoincidentSpans::oppPtTEnd() const { 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fOppPtTEnd; 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// A coincident span is unordered if the pairs of points in the main and opposite curves' 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// t values do not ascend or descend. For instance, if a tightly arced quadratic is 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// coincident with another curve, it may intersect it out of order. 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkCoincidentSpans::ordered(bool* result) const { 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* start = this->coinPtTStart()->span(); 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* end = this->coinPtTEnd()->span(); 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* next = start->upCast()->next(); 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next == end) { 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *result = true; 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool flipped = this->flipped(); 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* oppSeg = this->oppPtTStart()->segment(); 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oppLastT = fOppPtTStart->fT; 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* opp = next->contains(oppSeg); 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!opp) { 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkOPOBJASSERT(start, 0); // may assert if coincident span isn't fully processed 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if ((oppLastT > opp->fT) != flipped) { 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *result = false; 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppLastT = opp->fT; 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next == end) { 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!next->upCastable()) { 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *result = false; 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next = next->upCast()->next(); 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (true); 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *result = true; 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// if there is an existing pair that overlaps the addition, extend it 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::extend(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) { 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* test = fHead; 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!test) { 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* coinSeg = coinPtTStart->segment(); 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* oppSeg = oppPtTStart->segment(); 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!Ordered(coinPtTStart, oppPtTStart)) { 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinSeg, oppSeg); 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinPtTStart, oppPtTStart); 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinPtTEnd, oppPtTEnd); 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinPtTStart->fT > coinPtTEnd->fT) { 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinPtTStart, coinPtTEnd); 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(oppPtTStart, oppPtTEnd); 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oppMinT = SkTMin(oppPtTStart->fT, oppPtTEnd->fT); 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(double oppMaxT = SkTMax(oppPtTStart->fT, oppPtTEnd->fT)); 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinSeg != test->coinPtTStart()->segment()) { 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppSeg != test->oppPtTStart()->segment()) { 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oTestMinT = SkTMin(test->oppPtTStart()->fT, test->oppPtTEnd()->fT); 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oTestMaxT = SkTMax(test->oppPtTStart()->fT, test->oppPtTEnd()->fT); 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // if debug check triggers, caller failed to check if extended already exists 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(test->coinPtTStart()->fT > coinPtTStart->fT 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || coinPtTEnd->fT > test->coinPtTEnd()->fT 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || oTestMinT > oppMinT || oppMaxT > oTestMaxT); 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if ((test->coinPtTStart()->fT <= coinPtTEnd->fT 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot && coinPtTStart->fT <= test->coinPtTEnd()->fT) 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || (oTestMinT <= oTestMaxT && oppMinT <= oTestMaxT)) { 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test->extend(coinPtTStart, coinPtTEnd, oppPtTStart, oppPtTEnd); 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((test = test->next())); 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// verifies that the coincidence hasn't already been added 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void DebugCheckAdd(const SkCoincidentSpans* check, const SkOpPtT* coinPtTStart, 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* coinPtTEnd, const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) { 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (check) { 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(check->coinPtTStart() != coinPtTStart || check->coinPtTEnd() != coinPtTEnd 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || check->oppPtTStart() != oppPtTStart || check->oppPtTEnd() != oppPtTEnd); 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(check->coinPtTStart() != oppPtTStart || check->coinPtTEnd() != oppPtTEnd 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || check->oppPtTStart() != coinPtTStart || check->oppPtTEnd() != coinPtTEnd); 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot check = check->next(); 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// adds a new coincident pair 244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::add(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* oppPtTStart, 245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* oppPtTEnd) { 246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // OPTIMIZE: caller should have already sorted 247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!Ordered(coinPtTStart, oppPtTStart)) { 248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppPtTStart->fT < oppPtTEnd->fT) { 249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->add(oppPtTStart, oppPtTEnd, coinPtTStart, coinPtTEnd); 250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->add(oppPtTEnd, oppPtTStart, coinPtTEnd, coinPtTStart); 252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(Ordered(coinPtTStart, oppPtTStart)); 256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // choose the ptT at the front of the list to track 257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinPtTStart = coinPtTStart->span()->ptT(); 258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinPtTEnd = coinPtTEnd->span()->ptT(); 259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppPtTStart = oppPtTStart->span()->ptT(); 260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppPtTEnd = oppPtTEnd->span()->ptT(); 261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(coinPtTStart->fT < coinPtTEnd->fT); 262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(oppPtTStart->fT != oppPtTEnd->fT); 263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!coinPtTStart->deleted()); 264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!coinPtTEnd->deleted()); 265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!oppPtTStart->deleted()); 266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!oppPtTEnd->deleted()); 267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugCheckAdd(fHead, coinPtTStart, coinPtTEnd, oppPtTStart, oppPtTEnd); 268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DebugCheckAdd(fTop, coinPtTStart, coinPtTEnd, oppPtTStart, oppPtTEnd); 269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* coinRec = this->globalState()->allocator()->make<SkCoincidentSpans>(); 270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinRec->init(SkDEBUGCODE(fGlobalState)); 271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinRec->set(this->fHead, coinPtTStart, coinPtTEnd, oppPtTStart, oppPtTEnd); 272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fHead = coinRec; 273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// description below 276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::addEndMovedSpans(const SkOpSpan* base, const SkOpSpanBase* testSpan) { 277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* testPtT = testSpan->ptT(); 278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* stopPtT = testPtT; 279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* baseSeg = base->segment(); 280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int escapeHatch = 100000; // this is 100 times larger than the debugLoopLimit test 281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((testPtT = testPtT->next()) != stopPtT) { 282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (--escapeHatch <= 0) { 283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; // if triggered (likely by a fuzz-generated test) too complex to succeed 284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* testSeg = testPtT->segment(); 286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (testPtT->deleted()) { 287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (testSeg == baseSeg) { 290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (testPtT->span()->ptT() != testPtT) { 293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->contains(baseSeg, testSeg, testPtT->fT)) { 296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // intersect perp with base->ptT() with testPtT->segment() 299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDVector dxdy = baseSeg->dSlopeAtT(base->t()); 300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& pt = base->pt(); 301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDLine ray = {{{pt.fX, pt.fY}, {pt.fX + dxdy.fY, pt.fY - dxdy.fX}}}; 302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIntersections i SkDEBUGCODE((this->globalState())); 303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (*CurveIntersectRay[testSeg->verb()])(testSeg->pts(), testSeg->weight(), ray, &i); 304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < i.used(); ++index) { 305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double t = i[0][index]; 306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!between(0, t, 1)) { 307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDPoint oppPt = i.pt(index); 310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!oppPt.approximatelyEqual(pt)) { 311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* writableSeg = const_cast<SkOpSegment*>(testSeg); 314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* oppStart = writableSeg->addT(t); 315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppStart == testPtT) { 316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* writableBase = const_cast<SkOpSpan*>(base); 319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppStart->span()->addOpp(writableBase); 320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppStart->deleted()) { 321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* coinSeg = base->segment(); 324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* oppSeg = oppStart->segment(); 325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double coinTs, coinTe, oppTs, oppTe; 326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (Ordered(coinSeg, oppSeg)) { 327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinTs = base->t(); 328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinTe = testSpan->t(); 329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppTs = oppStart->fT; 330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppTe = testPtT->fT; 331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinSeg, oppSeg); 333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinTs = oppStart->fT; 334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinTe = testPtT->fT; 335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppTs = base->t(); 336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppTe = testSpan->t(); 337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinTs > coinTe) { 339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinTs, coinTe); 340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(oppTs, oppTe); 341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool added; 343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!this->addOrOverlap(coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &added)) { 344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// description below 352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::addEndMovedSpans(const SkOpPtT* ptT) { 353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!ptT->span()->upCastable()); 354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* base = ptT->span()->upCast(); 355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpan* prev = base->prev(); 356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!prev); 357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!prev->isCanceled()) { 358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!this->addEndMovedSpans(base, base->prev())) { 359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!base->isCanceled()) { 363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!this->addEndMovedSpans(base, base->next())) { 364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* If A is coincident with B and B includes an endpoint, and A's matching point 371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot is not the endpoint (i.e., there's an implied line connecting B-end and A) 372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot then assume that the same implied line may intersect another curve close to B. 373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Since we only care about coincidence that was undetected, look at the 374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ptT list on B-segment adjacent to the B-end/A ptT loop (not in the loop, but 375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next door) and see if the A matching point is close enough to form another 376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coincident pair. If so, check for a new coincident span between B-end/A ptT loop 377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot and the adjacent ptT loop. 378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot*/ 379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::addEndMovedSpans(DEBUG_COIN_DECLARE_ONLY_PARAMS()) { 380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DEBUG_SET_PHASE(); 381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* span = fHead; 382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!span) { 383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTop = span; 386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fHead = nullptr; 387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->coinPtTStart()->fPt != span->oppPtTStart()->fPt) { 389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(1 == span->coinPtTStart()->fT); 390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool onEnd = span->coinPtTStart()->fT == 0; 391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool oOnEnd = zero_or_one(span->oppPtTStart()->fT); 392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (onEnd) { 393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!oOnEnd) { // if both are on end, any nearby intersect was already found 394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!this->addEndMovedSpans(span->oppPtTStart())) { 395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (oOnEnd) { 399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!this->addEndMovedSpans(span->coinPtTStart())) { 400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (span->coinPtTEnd()->fPt != span->oppPtTEnd()->fPt) { 405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool onEnd = span->coinPtTEnd()->fT == 1; 406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool oOnEnd = zero_or_one(span->oppPtTEnd()->fT); 407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (onEnd) { 408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!oOnEnd) { 409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!this->addEndMovedSpans(span->oppPtTEnd())) { 410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (oOnEnd) { 414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!this->addEndMovedSpans(span->coinPtTEnd())) { 415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((span = span->next())); 420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->restoreHead(); 421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* Please keep this in sync with debugAddExpanded */ 425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// for each coincident pair, match the spans 426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// if the spans don't match, add the missing pt to the segment and loop it in the opposite span 427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::addExpanded(DEBUG_COIN_DECLARE_ONLY_PARAMS()) { 428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DEBUG_SET_PHASE(); 429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* coin = this->fHead; 430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coin) { 431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* startPtT = coin->coinPtTStart(); 435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oStartPtT = coin->oppPtTStart(); 436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double priorT = startPtT->fT; 437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oPriorT = oStartPtT->fT; 438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!startPtT->contains(oStartPtT)); 439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(coin->coinPtTEnd()->contains(coin->oppPtTEnd())); 440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* start = startPtT->span(); 441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oStart = oStartPtT->span(); 442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* end = coin->coinPtTEnd()->span(); 443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oEnd = coin->oppPtTEnd()->span(); 444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(oEnd->deleted()); 445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!start->upCastable()); 446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* test = start->upCast()->next(); 447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!coin->flipped() && !oStart->upCastable()); 448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oTest = coin->flipped() ? oStart->prev() : oStart->upCast()->next(); 449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!oTest); 450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* seg = start->segment(); 451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* oSeg = oStart->segment(); 452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (test != end || oTest != oEnd) { 453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* containedOpp = test->ptT()->contains(oSeg); 454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* containedThis = oTest->ptT()->contains(seg); 455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!containedOpp || !containedThis) { 456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // choose the ends, or the first common pt-t list shared by both 457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double nextT, oNextT; 458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (containedOpp) { 459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot nextT = test->t(); 460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oNextT = containedOpp->fT; 461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (containedThis) { 462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot nextT = containedThis->fT; 463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oNextT = oTest->t(); 464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // iterate through until a pt-t list found that contains the other 466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* walk = test; 467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* walkOpp; 468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!walk->upCastable()); 470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot walk = walk->upCast()->next(); 471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (!(walkOpp = walk->ptT()->contains(oSeg)) 472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot && walk != coin->coinPtTEnd()->span()); 473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!walkOpp); 474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot nextT = walk->t(); 475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oNextT = walkOpp->fT; 476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // use t ranges to guess which one is missing 478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double startRange = nextT - priorT; 479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!startRange); 480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double startPart = (test->t() - priorT) / startRange; 481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oStartRange = oNextT - oPriorT; 482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!oStartRange); 483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oStartPart = (oTest->t() - oPriorT) / oStartRange; 484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(startPart == oStartPart); 485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool addToOpp = !containedOpp && !containedThis ? startPart < oStartPart 486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : !!containedThis; 487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool startOver = false; 488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool success = addToOpp ? oSeg->addExpanded( 489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oPriorT + oStartRange * startPart, test, &startOver) 490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : seg->addExpanded( 491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot priorT + startRange * oStartPart, oTest, &startOver); 492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!success); 493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (startOver) { 494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test = start; 495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oTest = oStart; 496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot end = coin->coinPtTEnd()->span(); 498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oEnd = coin->oppPtTEnd()->span(); 499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (test != end) { 501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!test->upCastable()); 502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot priorT = test->t(); 503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot test = test->upCast()->next(); 504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oTest != oEnd) { 506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oPriorT = oTest->t(); 507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->flipped()) { 508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oTest = oTest->prev(); 509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!oTest->upCastable()); 511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oTest = oTest->upCast()->next(); 512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!oTest); 514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = coin->next())); 518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// given a t span, map the same range on the coincident span 522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotthe curves may not scale linearly, so interpolation may only happen within known points 524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotremap over1s, over1e, cointPtTStart, coinPtTEnd to smallest range that captures over1s 525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotthen repeat to capture over1e 526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot*/ 527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotdouble SkOpCoincidence::TRange(const SkOpPtT* overS, double t, 528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* coinSeg SkDEBUGPARAMS(const SkOpPtT* overE)) { 529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* work = overS->span(); 530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* foundStart = nullptr; 531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* foundEnd = nullptr; 532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* coinStart = nullptr; 533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* coinEnd = nullptr; 534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* contained = work->contains(coinSeg); 536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!contained) { 537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (work->final()) { 538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (work->t() <= t) { 543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinStart = contained; 544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot foundStart = work->ptT(); 545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (work->t() >= t) { 547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinEnd = contained; 548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot foundEnd = work->ptT(); 549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(work->ptT() != overE); 552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((work = work->upCast()->next())); 553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coinStart || !coinEnd) { 554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 1; 555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // while overS->fT <=t and overS contains coinSeg 557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double denom = foundEnd->fT - foundStart->fT; 558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double sRatio = denom ? (t - foundStart->fT) / denom : 1; 559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return coinStart->fT + (coinEnd->fT - coinStart->fT) * sRatio; 560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// return true if span overlaps existing and needs to adjust the coincident list 563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::checkOverlap(SkCoincidentSpans* check, 564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, 565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double coinTs, double coinTe, double oppTs, double oppTe, 566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTDArray<SkCoincidentSpans*>* overlaps) const { 567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!Ordered(coinSeg, oppSeg)) { 568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppTs < oppTe) { 569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return this->checkOverlap(check, oppSeg, coinSeg, oppTs, oppTe, coinTs, coinTe, 570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overlaps); 571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return this->checkOverlap(check, oppSeg, coinSeg, oppTe, oppTs, coinTe, coinTs, overlaps); 573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool swapOpp = oppTs > oppTe; 575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (swapOpp) { 576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(oppTs, oppTe); 577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (check->coinPtTStart()->segment() != coinSeg) { 580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (check->oppPtTStart()->segment() != oppSeg) { 583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double checkTs = check->coinPtTStart()->fT; 586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double checkTe = check->coinPtTEnd()->fT; 587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool coinOutside = coinTe < checkTs || coinTs > checkTe; 588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oCheckTs = check->oppPtTStart()->fT; 589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oCheckTe = check->oppPtTEnd()->fT; 590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (swapOpp) { 591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oCheckTs <= oCheckTe) { 592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(oCheckTs, oCheckTe); 595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool oppOutside = oppTe < oCheckTs || oppTs > oCheckTe; 597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinOutside && oppOutside) { 598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool coinInside = coinTe <= checkTe && coinTs >= checkTs; 601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool oppInside = oppTe <= oCheckTe && oppTs >= oCheckTs; 602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinInside && oppInside) { // already included, do nothing 603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *overlaps->append() = check; // partial overlap, extend existing entry 606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((check = check->next())); 607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* Please keep this in sync with debugAddIfMissing() */ 611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// note that over1s, over1e, over2s, over2e are ordered 612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over2s, 613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double tStart, double tEnd, SkOpSegment* coinSeg, SkOpSegment* oppSeg, bool* added 614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGPARAMS(const SkOpPtT* over1e) SkDEBUGPARAMS(const SkOpPtT* over2e)) { 615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(tStart < tEnd); 616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(over1s->fT < over1e->fT); 617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(between(over1s->fT, tStart, over1e->fT)); 618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(between(over1s->fT, tEnd, over1e->fT)); 619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(over2s->fT < over2e->fT); 620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(between(over2s->fT, tStart, over2e->fT)); 621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(between(over2s->fT, tEnd, over2e->fT)); 622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(over1s->segment() == over1e->segment()); 623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(over2s->segment() == over2e->segment()); 624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(over1s->segment() == over2s->segment()); 625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(over1s->segment() != coinSeg); 626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(over1s->segment() != oppSeg); 627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(coinSeg != oppSeg); 628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double coinTs, coinTe, oppTs, oppTe; 629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinTs = TRange(over1s, tStart, coinSeg SkDEBUGPARAMS(over1e)); 630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinTe = TRange(over1s, tEnd, coinSeg SkDEBUGPARAMS(over1e)); 631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinSeg->collapsed(coinTs, coinTe)) { 632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppTs = TRange(over2s, tStart, oppSeg SkDEBUGPARAMS(over2e)); 635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppTe = TRange(over2s, tEnd, oppSeg SkDEBUGPARAMS(over2e)); 636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppSeg->collapsed(oppTs, oppTe)) { 637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinTs > coinTe) { 640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinTs, coinTe); 641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(oppTs, oppTe); 642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return this->addOrOverlap(coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, added); 644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* Please keep this in sync with debugAddOrOverlap() */ 647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// If this is called by addEndMovedSpans(), a returned false propogates out to an abort. 648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// If this is called by AddIfMissing(), a returned false indicates there was nothing to add 649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::addOrOverlap(SkOpSegment* coinSeg, SkOpSegment* oppSeg, 650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double coinTs, double coinTe, double oppTs, double oppTe, bool* added) { 651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTDArray<SkCoincidentSpans*> overlaps; 652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!fTop); 653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!this->checkOverlap(fTop, coinSeg, oppSeg, coinTs, coinTe, oppTs, oppTe, &overlaps)) { 654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fHead && !this->checkOverlap(fHead, coinSeg, oppSeg, coinTs, 657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coinTe, oppTs, oppTe, &overlaps)) { 658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* overlap = overlaps.count() ? overlaps[0] : nullptr; 661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 1; index < overlaps.count(); ++index) { // combine overlaps before continuing 662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* test = overlaps[index]; 663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (overlap->coinPtTStart()->fT > test->coinPtTStart()->fT) { 664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overlap->setCoinPtTStart(test->coinPtTStart()); 665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (overlap->coinPtTEnd()->fT < test->coinPtTEnd()->fT) { 667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overlap->setCoinPtTEnd(test->coinPtTEnd()); 668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (overlap->flipped() 670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ? overlap->oppPtTStart()->fT < test->oppPtTStart()->fT 671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : overlap->oppPtTStart()->fT > test->oppPtTStart()->fT) { 672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overlap->setOppPtTStart(test->oppPtTStart()); 673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (overlap->flipped() 675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ? overlap->oppPtTEnd()->fT > test->oppPtTEnd()->fT 676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : overlap->oppPtTEnd()->fT < test->oppPtTEnd()->fT) { 677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overlap->setOppPtTEnd(test->oppPtTEnd()); 678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fHead || !this->release(fHead, test)) { 680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAssertResult(this->release(fTop, test)); 681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* cs = coinSeg->existing(coinTs, oppSeg); 684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ce = coinSeg->existing(coinTe, oppSeg); 685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (overlap && cs && ce && overlap->contains(cs, ce)) { 686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(cs == ce && cs); 689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* os = oppSeg->existing(oppTs, coinSeg); 690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oe = oppSeg->existing(oppTe, coinSeg); 691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (overlap && os && oe && overlap->contains(os, oe)) { 692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!cs || !cs->deleted()); 695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!os || !os->deleted()); 696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!ce || !ce->deleted()); 697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!oe || !oe->deleted()); 698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullptr; 699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullptr; 700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(csExisting && csExisting == ceExisting); 701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// FAIL_IF(csExisting && (csExisting == ce || 702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// csExisting->contains(ceExisting ? ceExisting : ce))); 703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(ceExisting && (ceExisting == cs || 704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ceExisting->contains(csExisting ? csExisting : cs))); 705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* osExisting = !os ? oppSeg->existing(oppTs, nullptr) : nullptr; 706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oeExisting = !oe ? oppSeg->existing(oppTe, nullptr) : nullptr; 707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(osExisting && osExisting == oeExisting); 708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(osExisting && (osExisting == oe || 709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot osExisting->contains(oeExisting ? oeExisting : oe))); 710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(oeExisting && (oeExisting == os || 711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oeExisting->contains(osExisting ? osExisting : os))); 712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // extra line in debug code 713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugValidate(); 714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!cs || !os) { 715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* csWritable = cs ? const_cast<SkOpPtT*>(cs) 716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : coinSeg->addT(coinTs); 717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (csWritable == ce) { 718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* osWritable = os ? const_cast<SkOpPtT*>(os) 721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : oppSeg->addT(oppTs); 722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!csWritable || !osWritable); 723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot csWritable->span()->addOpp(osWritable->span()); 724fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cs = csWritable; 725fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot os = osWritable->active(); 726fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF((ce && ce->deleted()) || (oe && oe->deleted())); 727fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 728fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!ce || !oe) { 729fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* ceWritable = ce ? const_cast<SkOpPtT*>(ce) 730fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : coinSeg->addT(coinTe); 731fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpPtT* oeWritable = oe ? const_cast<SkOpPtT*>(oe) 732fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : oppSeg->addT(oppTe); 733fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ceWritable->span()->addOpp(oeWritable->span()); 734fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ce = ceWritable; 735fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oe = oeWritable; 736fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 737fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugValidate(); 738fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(cs->deleted()); 739fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(os->deleted()); 740fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(ce->deleted()); 741fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(oe->deleted()); 742fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(cs->contains(ce) || os->contains(oe)); 743fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool result = true; 744fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (overlap) { 745fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (overlap->coinPtTStart()->segment() == coinSeg) { 746fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = overlap->extend(cs, ce, os, oe); 747fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 748fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (os->fT > oe->fT) { 749fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(cs, ce); 750fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(os, oe); 751fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 752fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = overlap->extend(os, oe, cs, ce); 753fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 754fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE_VERBOSE 755fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (result) { 756fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overlaps[0]->debugShow(); 757fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 758fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 759fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 760fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->add(cs, ce, os, oe); 761fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_COINCIDENCE_VERBOSE 762fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fHead->debugShow(); 763fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 764fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 765fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugValidate(); 766fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (result) { 767fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *added = true; 768fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 769fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 770fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 771fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 772fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Please keep this in sync with debugAddMissing() 773fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* detects overlaps of different coincident runs on same segment */ 774fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* does not detect overlaps for pairs without any segments in common */ 775fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// returns true if caller should loop again 776fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::addMissing(bool* added DEBUG_COIN_DECLARE_PARAMS()) { 777fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* outer = fHead; 778fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *added = false; 779fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!outer) { 780fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 781fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 782fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTop = outer; 783fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fHead = nullptr; 784fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 785fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // addifmissing can modify the list that this is walking 786fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // save head so that walker can iterate over old data unperturbed 787fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // addifmissing adds to head freely then add saved head in the end 788fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ocs = outer->coinPtTStart(); 789fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(ocs->deleted()); 790fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* outerCoin = ocs->segment(); 791fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!outerCoin->done()); // if it's done, should have already been removed from list 792fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oos = outer->oppPtTStart(); 793fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oos->deleted()) { 794fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 795fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 796fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* outerOpp = oos->segment(); 797fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!outerOpp->done()); 798fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* outerCoinWritable = const_cast<SkOpSegment*>(outerCoin); 799fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* outerOppWritable = const_cast<SkOpSegment*>(outerOpp); 800fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* inner = outer; 801fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((inner = inner->next())) { 802fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugValidate(); 803fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double overS, overE; 804fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ics = inner->coinPtTStart(); 805fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(ics->deleted()); 806fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* innerCoin = ics->segment(); 807fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(innerCoin->done()); 808fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ios = inner->oppPtTStart(); 809fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(ios->deleted()); 810fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* innerOpp = ios->segment(); 811fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!innerOpp->done()); 812fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* innerCoinWritable = const_cast<SkOpSegment*>(innerCoin); 813fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* innerOppWritable = const_cast<SkOpSegment*>(innerOpp); 814fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (outerCoin == innerCoin) { 815fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oce = outer->coinPtTEnd(); 816fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oce->deleted()) { 817fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 818fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 819fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ice = inner->coinPtTEnd(); 820fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(ice->deleted()); 821fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (outerOpp != innerOpp && this->overlap(ocs, oce, ics, ice, &overS, &overE)) { 822fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (void) this->addIfMissing(ocs->starter(oce), ics->starter(ice), 823fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overS, overE, outerOppWritable, innerOppWritable, added 824fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGPARAMS(ocs->debugEnder(oce)) 825fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGPARAMS(ics->debugEnder(ice))); 826fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 827fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (outerCoin == innerOpp) { 828fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oce = outer->coinPtTEnd(); 829fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!oce->deleted()); 830fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ioe = inner->oppPtTEnd(); 831fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!ioe->deleted()); 832fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (outerOpp != innerCoin && this->overlap(ocs, oce, ios, ioe, &overS, &overE)) { 833fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (void) this->addIfMissing(ocs->starter(oce), ios->starter(ioe), 834fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overS, overE, outerOppWritable, innerCoinWritable, added 835fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGPARAMS(ocs->debugEnder(oce)) 836fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGPARAMS(ios->debugEnder(ioe))); 837fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 838fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (outerOpp == innerCoin) { 839fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ooe = outer->oppPtTEnd(); 840fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!ooe->deleted()); 841fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ice = inner->coinPtTEnd(); 842fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!ice->deleted()); 843fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(outerCoin != innerOpp); 844fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->overlap(oos, ooe, ics, ice, &overS, &overE)) { 845fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (void) this->addIfMissing(oos->starter(ooe), ics->starter(ice), 846fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overS, overE, outerCoinWritable, innerOppWritable, added 847fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGPARAMS(oos->debugEnder(ooe)) 848fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGPARAMS(ics->debugEnder(ice))); 849fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 850fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (outerOpp == innerOpp) { 851fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ooe = outer->oppPtTEnd(); 852fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!ooe->deleted()); 853fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* ioe = inner->oppPtTEnd(); 854fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ioe->deleted()) { 855fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 856fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 857fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(outerCoin != innerCoin); 858fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->overlap(oos, ooe, ios, ioe, &overS, &overE)) { 859fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (void) this->addIfMissing(oos->starter(ooe), ios->starter(ioe), 860fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overS, overE, outerCoinWritable, innerCoinWritable, added 861fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGPARAMS(oos->debugEnder(ooe)) 862fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGPARAMS(ios->debugEnder(ioe))); 863fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 864fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 865fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->debugValidate(); 866fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 867fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((outer = outer->next())); 868fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->restoreHead(); 869fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 870fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 871fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 872fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::addOverlap(const SkOpSegment* seg1, const SkOpSegment* seg1o, 873fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* seg2, const SkOpSegment* seg2o, 874fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* overS, const SkOpPtT* overE) { 875fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* s1 = overS->find(seg1); 876fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* e1 = overE->find(seg1); 877fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!s1); 878fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!e1); 879fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!s1->starter(e1)->span()->upCast()->windValue()) { 880fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot s1 = overS->find(seg1o); 881fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot e1 = overE->find(seg1o); 882fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!s1); 883fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!e1); 884fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!s1->starter(e1)->span()->upCast()->windValue()) { 885fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 886fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 887fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 888fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* s2 = overS->find(seg2); 889fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* e2 = overE->find(seg2); 890fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!s2); 891fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!e2); 892fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!s2->starter(e2)->span()->upCast()->windValue()) { 893fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot s2 = overS->find(seg2o); 894fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot e2 = overE->find(seg2o); 895fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!s2); 896fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!e2); 897fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!s2->starter(e2)->span()->upCast()->windValue()) { 898fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 899fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 900fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 901fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (s1->segment() == s2->segment()) { 902fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 903fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 904fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (s1->fT > e1->fT) { 905fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(s1, e1); 906fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(s2, e2); 907fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 908fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->add(s1, e1, s2, e2); 909fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 910fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 911fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 912fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::contains(const SkOpSegment* seg, const SkOpSegment* opp, double oppT) const { 913fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->contains(fHead, seg, opp, oppT)) { 914fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 915fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 916fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->contains(fTop, seg, opp, oppT)) { 917fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 918fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 919fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 920fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 921fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 922fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::contains(const SkCoincidentSpans* coin, const SkOpSegment* seg, 923fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* opp, double oppT) const { 924fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coin) { 925fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 926fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 927fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 928fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->coinPtTStart()->segment() == seg && coin->oppPtTStart()->segment() == opp 929fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot && between(coin->oppPtTStart()->fT, oppT, coin->oppPtTEnd()->fT)) { 930fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 931fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 932fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->oppPtTStart()->segment() == seg && coin->coinPtTStart()->segment() == opp 933fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot && between(coin->coinPtTStart()->fT, oppT, coin->coinPtTEnd()->fT)) { 934fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 935fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 936fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = coin->next())); 937fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 938fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 939fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 940fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::contains(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, 941fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) const { 942fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkCoincidentSpans* test = fHead; 943fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!test) { 944fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 945fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 946fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* coinSeg = coinPtTStart->segment(); 947fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* oppSeg = oppPtTStart->segment(); 948fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!Ordered(coinPtTStart, oppPtTStart)) { 949fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinSeg, oppSeg); 950fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinPtTStart, oppPtTStart); 951fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinPtTEnd, oppPtTEnd); 952fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinPtTStart->fT > coinPtTEnd->fT) { 953fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(coinPtTStart, coinPtTEnd); 954fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(oppPtTStart, oppPtTEnd); 955fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 956fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 957fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oppMinT = SkTMin(oppPtTStart->fT, oppPtTEnd->fT); 958fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot double oppMaxT = SkTMax(oppPtTStart->fT, oppPtTEnd->fT); 959fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 960fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinSeg != test->coinPtTStart()->segment()) { 961fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 962fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 963fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinPtTStart->fT < test->coinPtTStart()->fT) { 964fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 965fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 966fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinPtTEnd->fT > test->coinPtTEnd()->fT) { 967fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 968fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 969fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppSeg != test->oppPtTStart()->segment()) { 970fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 971fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 972fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppMinT < SkTMin(test->oppPtTStart()->fT, test->oppPtTEnd()->fT)) { 973fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 974fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 975fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oppMaxT > SkTMax(test->oppPtTStart()->fT, test->oppPtTEnd()->fT)) { 976fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 977fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 978fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 979fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((test = test->next())); 980fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 981fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 982fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 983fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::correctEnds(DEBUG_COIN_DECLARE_ONLY_PARAMS()) { 984fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DEBUG_SET_PHASE(); 985fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* coin = fHead; 986fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coin) { 987fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 988fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 989fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 990fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin->correctEnds(); 991fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = coin->next())); 992fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 993fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 994fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// walk span sets in parallel, moving winding from one to the other 995fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::apply(DEBUG_COIN_DECLARE_ONLY_PARAMS()) { 996fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DEBUG_SET_PHASE(); 997fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* coin = fHead; 998fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coin) { 999fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1000fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1001fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1002fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* startSpan = coin->coinPtTStartWritable()->span(); 1003fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!startSpan->upCastable()); 1004fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* start = startSpan->upCast(); 1005fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (start->deleted()) { 1006fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1007fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1008fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* end = coin->coinPtTEnd()->span(); 1009fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(start == start->starter(end)); 1010fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool flipped = coin->flipped(); 1011fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* oStartBase = (flipped ? coin->oppPtTEndWritable() 1012fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : coin->oppPtTStartWritable())->span(); 1013fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!oStartBase->upCastable()); 1014fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* oStart = oStartBase->upCast(); 1015fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oStart->deleted()) { 1016fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1017fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1018fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSpanBase* oEnd = (flipped ? coin->oppPtTStart() : coin->oppPtTEnd())->span(); 1019fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(oStart == oStart->starter(oEnd)); 1020fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* segment = start->segment(); 1021fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSegment* oSegment = oStart->segment(); 1022fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool operandSwap = segment->operand() != oSegment->operand(); 1023fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (flipped) { 1024fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oEnd->deleted()) { 1025fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1026fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1027fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1028fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* oNext = oStart->next(); 1029fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oNext == oEnd) { 1030fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1031fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1032fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!oNext->upCastable()); 1033fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oStart = oNext->upCast(); 1034fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (true); 1035fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1036fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1037fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int windValue = start->windValue(); 1038fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int oppValue = start->oppValue(); 1039fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int oWindValue = oStart->windValue(); 1040fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int oOppValue = oStart->oppValue(); 1041fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // winding values are added or subtracted depending on direction and wind type 1042fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // same or opposite values are summed depending on the operand value 1043fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int windDiff = operandSwap ? oOppValue : oWindValue; 1044fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int oWindDiff = operandSwap ? oppValue : windValue; 1045fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!flipped) { 1046fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot windDiff = -windDiff; 1047fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oWindDiff = -oWindDiff; 1048fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1049fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool addToStart = windValue && (windValue > windDiff || (windValue == windDiff 1050fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot && oWindValue <= oWindDiff)); 1051fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (addToStart ? start->done() : oStart->done()) { 1052fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot addToStart ^= true; 1053fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1054fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (addToStart) { 1055fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (operandSwap) { 1056fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(oWindValue, oOppValue); 1057fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1058fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (flipped) { 1059fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot windValue -= oWindValue; 1060fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppValue -= oOppValue; 1061fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1062fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot windValue += oWindValue; 1063fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppValue += oOppValue; 1064fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1065fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (segment->isXor()) { 1066fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot windValue &= 1; 1067fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1068fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (segment->oppXor()) { 1069fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oppValue &= 1; 1070fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1071fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oWindValue = oOppValue = 0; 1072fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1073fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (operandSwap) { 1074fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(windValue, oppValue); 1075fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1076fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (flipped) { 1077fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oWindValue -= windValue; 1078fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oOppValue -= oppValue; 1079fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1080fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oWindValue += windValue; 1081fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oOppValue += oppValue; 1082fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1083fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oSegment->isXor()) { 1084fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oWindValue &= 1; 1085fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1086fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (oSegment->oppXor()) { 1087fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oOppValue &= 1; 1088fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1089fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot windValue = oppValue = 0; 1090fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1091fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0 && DEBUG_COINCIDENCE 1092fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("seg=%d span=%d windValue=%d oppValue=%d\n", segment->debugID(), 1093fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot start->debugID(), windValue, oppValue); 1094fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("seg=%d span=%d windValue=%d oppValue=%d\n", oSegment->debugID(), 1095fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oStart->debugID(), oWindValue, oOppValue); 1096fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1097fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot start->setWindValue(windValue); 1098fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot start->setOppValue(oppValue); 1099fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(oWindValue == -1); 1100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oStart->setWindValue(oWindValue); 1101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oStart->setOppValue(oOppValue); 1102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!windValue && !oppValue) { 1103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot segment->markDone(start); 1104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!oWindValue && !oOppValue) { 1106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oSegment->markDone(oStart); 1107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* next = start->next(); 1109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* oNext = flipped ? oStart->prev() : oStart->next(); 1110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (next == end) { 1111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!next->upCastable()); 1114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot start = next->upCast(); 1115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // if the opposite ran out too soon, just reuse the last span 1116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!oNext || !oNext->upCastable()) { 1117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oNext = oStart; 1118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot oStart = oNext->upCast(); 1120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (true); 1121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = coin->next())); 1122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Please keep this in sync with debugRelease() 1126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::release(SkCoincidentSpans* coin, SkCoincidentSpans* remove) { 1127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* head = coin; 1128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* prev = nullptr; 1129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* next; 1130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next = coin->next(); 1132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin == remove) { 1133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (prev) { 1134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot prev->setNext(next); 1135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (head == fHead) { 1136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fHead = next; 1137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTop = next; 1139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot prev = coin; 1143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = next)); 1144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return coin != nullptr; 1145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::releaseDeleted(SkCoincidentSpans* coin) { 1148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coin) { 1149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* head = coin; 1152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* prev = nullptr; 1153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* next; 1154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next = coin->next(); 1156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->coinPtTStart()->deleted()) { 1157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(coin->flipped() ? coin->oppPtTEnd()->deleted() : 1158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin->oppPtTStart()->deleted()); 1159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (prev) { 1160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot prev->setNext(next); 1161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (head == fHead) { 1162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fHead = next; 1163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTop = next; 1165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(coin->flipped() ? !coin->oppPtTEnd()->deleted() : 1168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot !coin->oppPtTStart()->deleted()); 1169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot prev = coin; 1170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = next)); 1172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::releaseDeleted() { 1175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->releaseDeleted(fHead); 1176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->releaseDeleted(fTop); 1177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::restoreHead() { 1180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans** headPtr = &fHead; 1181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (*headPtr) { 1182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot headPtr = (*headPtr)->nextPtr(); 1183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *headPtr = fTop; 1185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fTop = nullptr; 1186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // segments may have collapsed in the meantime; remove empty referenced segments 1187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot headPtr = &fHead; 1188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (*headPtr) { 1189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* test = *headPtr; 1190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (test->coinPtTStart()->segment()->done() || test->oppPtTStart()->segment()->done()) { 1191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *headPtr = test->next(); 1192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot headPtr = (*headPtr)->nextPtr(); 1195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Please keep this in sync with debugExpand() 1199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// expand the range by checking adjacent spans for coincidence 1200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::expand(DEBUG_COIN_DECLARE_ONLY_PARAMS()) { 1201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DEBUG_SET_PHASE(); 1202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* coin = fHead; 1203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coin) { 1204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool expanded = false; 1207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->expand()) { 1209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // check to see if multiple spans expanded so they are now identical 1210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* test = fHead; 1211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin == test) { 1213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->coinPtTStart() == test->coinPtTStart() 1216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot && coin->oppPtTStart() == test->oppPtTStart()) { 1217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->release(fHead, test); 1218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((test = test->next())); 1221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot expanded = true; 1222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = coin->next())); 1224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return expanded; 1225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::findOverlaps(SkOpCoincidence* overlaps DEBUG_COIN_DECLARE_PARAMS()) const { 1228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DEBUG_SET_PHASE(); 1229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overlaps->fHead = overlaps->fTop = nullptr; 1230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* outer = fHead; 1231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (outer) { 1232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* outerCoin = outer->coinPtTStart()->segment(); 1233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* outerOpp = outer->oppPtTStart()->segment(); 1234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* inner = outer; 1235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((inner = inner->next())) { 1236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* innerCoin = inner->coinPtTStart()->segment(); 1237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (outerCoin == innerCoin) { 1238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; // both winners are the same segment, so there's no additional overlap 1239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* innerOpp = inner->oppPtTStart()->segment(); 1241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* overlapS; 1242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* overlapE; 1243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if ((outerOpp == innerCoin && SkOpPtT::Overlaps(outer->oppPtTStart(), 1244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot outer->oppPtTEnd(),inner->coinPtTStart(), inner->coinPtTEnd(), &overlapS, 1245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot &overlapE)) 1246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || (outerCoin == innerOpp && SkOpPtT::Overlaps(outer->coinPtTStart(), 1247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot outer->coinPtTEnd(), inner->oppPtTStart(), inner->oppPtTEnd(), 1248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot &overlapS, &overlapE)) 1249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || (outerOpp == innerOpp && SkOpPtT::Overlaps(outer->oppPtTStart(), 1250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot outer->oppPtTEnd(), inner->oppPtTStart(), inner->oppPtTEnd(), 1251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot &overlapS, &overlapE))) { 1252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!overlaps->addOverlap(outerCoin, outerOpp, innerCoin, innerOpp, 1253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot overlapS, overlapE)) { 1254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot outer = outer->next(); 1259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::fixUp(SkOpPtT* deleted, const SkOpPtT* kept) { 1264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(deleted != kept); 1265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fHead) { 1266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->fixUp(fHead, deleted, kept); 1267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fTop) { 1269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->fixUp(fTop, deleted, kept); 1270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::fixUp(SkCoincidentSpans* coin, SkOpPtT* deleted, const SkOpPtT* kept) { 1274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* head = coin; 1275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->coinPtTStart() == deleted) { 1277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->coinPtTEnd()->span() == kept->span()) { 1278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->release(head, coin); 1279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin->setCoinPtTStart(kept); 1282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->coinPtTEnd() == deleted) { 1284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->coinPtTStart()->span() == kept->span()) { 1285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->release(head, coin); 1286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin->setCoinPtTEnd(kept); 1289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->oppPtTStart() == deleted) { 1291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->oppPtTEnd()->span() == kept->span()) { 1292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->release(head, coin); 1293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin->setOppPtTStart(kept); 1296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->oppPtTEnd() == deleted) { 1298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->oppPtTStart()->span() == kept->span()) { 1299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->release(head, coin); 1300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot continue; 1301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin->setOppPtTEnd(kept); 1303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = coin->next())); 1305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Please keep this in sync with debugMark() 1308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* this sets up the coincidence links in the segments when the coincidence crosses multiple spans */ 1309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::mark(DEBUG_COIN_DECLARE_ONLY_PARAMS()) { 1310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DEBUG_SET_PHASE(); 1311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* coin = fHead; 1312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coin) { 1313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* startBase = coin->coinPtTStartWritable()->span(); 1317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!startBase->upCastable()); 1318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpan* start = startBase->upCast(); 1319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(start->deleted()); 1320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* end = coin->coinPtTEndWritable()->span(); 1321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!end->deleted()); 1322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span(); 1323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOPASSERT(!oStart->deleted()); 1324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* oEnd = coin->oppPtTEndWritable()->span(); 1325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!oEnd->deleted()); 1326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool flipped = coin->flipped(); 1327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (flipped) { 1328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(oStart, oEnd); 1329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /* coin and opp spans may not match up. Mark the ends, and then let the interior 1331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot get marked as many times as the spans allow */ 1332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!oStart->upCastable()); 1333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot start->insertCoincidence(oStart->upCast()); 1334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot end->insertCoinEnd(oEnd); 1335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* segment = start->segment(); 1336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpSegment* oSegment = oStart->segment(); 1337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* next = start; 1338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOpSpanBase* oNext = oStart; 1339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool ordered; 1340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!coin->ordered(&ordered)); 1341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((next = next->upCast()->next()) != end) { 1342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!next->upCastable()); 1343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!next->upCast()->insertCoincidence(oSegment, flipped, ordered)); 1344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while ((oNext = oNext->upCast()->next()) != oEnd) { 1346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!oNext->upCastable()); 1347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FAIL_IF(!oNext->upCast()->insertCoincidence(segment, flipped, ordered)); 1348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = coin->next())); 1350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Please keep in sync with debugMarkCollapsed() 1354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::markCollapsed(SkCoincidentSpans* coin, SkOpPtT* test) { 1355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* head = coin; 1356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (coin) { 1357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->collapsed(test)) { 1358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (zero_or_one(coin->coinPtTStart()->fT) && zero_or_one(coin->coinPtTEnd()->fT)) { 1359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin->coinPtTStartWritable()->segment()->markAllDone(); 1360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (zero_or_one(coin->oppPtTStart()->fT) && zero_or_one(coin->oppPtTEnd()->fT)) { 1362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin->oppPtTStartWritable()->segment()->markAllDone(); 1363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->release(head, coin); 1365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coin = coin->next(); 1367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Please keep in sync with debugMarkCollapsed() 1371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::markCollapsed(SkOpPtT* test) { 1372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot markCollapsed(fHead, test); 1373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot markCollapsed(fTop, test); 1374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::Ordered(const SkOpSegment* coinSeg, const SkOpSegment* oppSeg) { 1377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinSeg->verb() < oppSeg->verb()) { 1378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coinSeg->verb() > oppSeg->verb()) { 1381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count = (SkPathOpsVerbToPoints(coinSeg->verb()) + 1) * 2; 1384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar* cPt = &coinSeg->pts()[0].fX; 1385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar* oPt = &oppSeg->pts()[0].fX; 1386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int index = 0; index < count; ++index) { 1387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (*cPt < *oPt) { 1388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (*cPt > *oPt) { 1391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++cPt; 1394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++oPt; 1395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkOpCoincidence::overlap(const SkOpPtT* coin1s, const SkOpPtT* coin1e, 1400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkOpPtT* coin2s, const SkOpPtT* coin2e, double* overS, double* overE) const { 1401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(coin1s->segment() == coin2s->segment()); 1402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *overS = SkTMax(SkTMin(coin1s->fT, coin1e->fT), SkTMin(coin2s->fT, coin2e->fT)); 1403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *overE = SkTMin(SkTMax(coin1s->fT, coin1e->fT), SkTMax(coin2s->fT, coin2e->fT)); 1404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return *overS < *overE; 1405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Commented-out lines keep this in sync with debugRelease() 1408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkOpCoincidence::release(const SkOpSegment* deleted) { 1409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCoincidentSpans* coin = fHead; 1410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coin) { 1411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coin->coinPtTStart()->segment() == deleted 1415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || coin->coinPtTEnd()->segment() == deleted 1416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || coin->oppPtTStart()->segment() == deleted 1417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || coin->oppPtTEnd()->segment() == deleted) { 1418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->release(fHead, coin); 1419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while ((coin = coin->next())); 1421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1422