| Index: src/pathops/SkOpSpan.cpp
|
| diff --git a/src/pathops/SkPathOpsPostSect.cpp b/src/pathops/SkOpSpan.cpp
|
| old mode 100644
|
| new mode 100755
|
| similarity index 55%
|
| copy from src/pathops/SkPathOpsPostSect.cpp
|
| copy to src/pathops/SkOpSpan.cpp
|
| index 15a1900ce3b1ad48a8a62768d5564379873cda51..37d5120019dae9dc772762dd9d974626b966b6db
|
| --- a/src/pathops/SkPathOpsPostSect.cpp
|
| +++ b/src/pathops/SkOpSpan.cpp
|
| @@ -17,8 +17,8 @@ SkOpContour* SkOpPtT::contour() const {
|
| return segment()->contour();
|
| }
|
|
|
| -SkOpDebugState* SkOpPtT::debugState() const {
|
| - return PATH_OPS_DEBUG_RELEASE(contour()->debugState(), NULL);
|
| +SkOpGlobalState* SkOpPtT::globalState() const {
|
| + return contour()->globalState();
|
| }
|
|
|
| void SkOpPtT::init(SkOpSpanBase* span, double t, const SkPoint& pt, bool duplicate) {
|
| @@ -28,7 +28,7 @@ void SkOpPtT::init(SkOpSpanBase* span, double t, const SkPoint& pt, bool duplica
|
| fNext = this;
|
| fDuplicatePt = duplicate;
|
| fDeleted = false;
|
| - PATH_OPS_DEBUG_CODE(fID = ++span->debugState()->fPtTID);
|
| + PATH_OPS_DEBUG_CODE(fID = span->globalState()->nextPtTID());
|
| }
|
|
|
| bool SkOpPtT::onEnd() const {
|
| @@ -40,12 +40,23 @@ bool SkOpPtT::onEnd() const {
|
| return span == segment->head() || span == segment->tail();
|
| }
|
|
|
| +SkOpPtT* SkOpPtT::prev() {
|
| + SkOpPtT* result = this;
|
| + SkOpPtT* next = this;
|
| + while ((next = next->fNext) != this) {
|
| + result = next;
|
| + }
|
| + SkASSERT(result->fNext == this);
|
| + return result;
|
| +}
|
| +
|
| SkOpPtT* SkOpPtT::remove() {
|
| SkOpPtT* prev = this;
|
| do {
|
| SkOpPtT* next = prev->fNext;
|
| if (next == this) {
|
| - prev->removeNext();
|
| + prev->removeNext(this);
|
| + SkASSERT(prev->fNext != prev);
|
| fDeleted = true;
|
| return prev;
|
| }
|
| @@ -55,14 +66,15 @@ SkOpPtT* SkOpPtT::remove() {
|
| return NULL;
|
| }
|
|
|
| -void SkOpPtT::removeNext() {
|
| +void SkOpPtT::removeNext(SkOpPtT* kept) {
|
| SkASSERT(this->fNext);
|
| SkOpPtT* next = this->fNext;
|
| + SkASSERT(this != next->fNext);
|
| this->fNext = next->fNext;
|
| SkOpSpanBase* span = next->span();
|
| next->setDeleted();
|
| if (span->ptT() == next) {
|
| - span->upCast()->detach();
|
| + span->upCast()->detach(kept);
|
| }
|
| }
|
|
|
| @@ -199,7 +211,7 @@ void SkOpSpanBase::alignInner() {
|
| // omit aliases that alignment makes redundant
|
| if ((!ptT->alias() || test->alias()) && (ptT->onEnd() || !test->onEnd())) {
|
| SkASSERT(test->alias());
|
| - prev->removeNext();
|
| + prev->removeNext(ptT);
|
| test = prev;
|
| } else {
|
| SkASSERT(ptT->alias());
|
| @@ -224,6 +236,17 @@ bool SkOpSpanBase::contains(const SkOpSpanBase* span) const {
|
| return false;
|
| }
|
|
|
| +SkOpPtT* SkOpSpanBase::contains(const SkOpSegment* segment) {
|
| + SkOpPtT* start = &fPtT;
|
| + SkOpPtT* walk = start;
|
| + while ((walk = walk->next()) != start) {
|
| + if (walk->segment() == segment) {
|
| + return walk;
|
| + }
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| bool SkOpSpanBase::containsCoinEnd(const SkOpSegment* segment) const {
|
| SkASSERT(this->segment() != segment);
|
| const SkOpSpanBase* next = this;
|
| @@ -239,8 +262,8 @@ SkOpContour* SkOpSpanBase::contour() const {
|
| return segment()->contour();
|
| }
|
|
|
| -SkOpDebugState* SkOpSpanBase::debugState() const {
|
| - return PATH_OPS_DEBUG_RELEASE(contour()->debugState(), NULL);
|
| +SkOpGlobalState* SkOpSpanBase::globalState() const {
|
| + return contour()->globalState();
|
| }
|
|
|
| void SkOpSpanBase::initBase(SkOpSegment* segment, SkOpSpan* prev, double t, const SkPoint& pt) {
|
| @@ -252,7 +275,7 @@ void SkOpSpanBase::initBase(SkOpSegment* segment, SkOpSpan* prev, double t, cons
|
| fAligned = true;
|
| fChased = false;
|
| PATH_OPS_DEBUG_CODE(fCount = 1);
|
| - PATH_OPS_DEBUG_CODE(fID = ++debugState()->fSpanID);
|
| + PATH_OPS_DEBUG_CODE(fID = globalState()->nextSpanID());
|
| }
|
|
|
| // this pair of spans share a common t value or point; merge them and eliminate duplicates
|
| @@ -261,7 +284,7 @@ void SkOpSpanBase::merge(SkOpSpan* span) {
|
| SkOpPtT* spanPtT = span->ptT();
|
| SkASSERT(this->t() != spanPtT->fT);
|
| SkASSERT(!zero_or_one(spanPtT->fT));
|
| - span->detach();
|
| + span->detach(this->ptT());
|
| SkOpPtT* remainder = spanPtT->next();
|
| ptT()->insert(spanPtT);
|
| while (remainder != spanPtT) {
|
| @@ -280,14 +303,6 @@ tryNextRemainder:
|
| }
|
| }
|
|
|
| -void SkOpSpanBase::mergeBaseAttributes(SkOpSpanBase* span) {
|
| - SkASSERT(!span->fChased);
|
| - SkASSERT(!span->fFromAngle);
|
| - if (this->upCastable() && span->upCastable()) {
|
| - this->upCast()->mergeAttributes(span->upCast());
|
| - }
|
| -}
|
| -
|
| void SkOpSpan::applyCoincidence(SkOpSpan* opp) {
|
| SkASSERT(!final());
|
| SkASSERT(0); // incomplete
|
| @@ -295,16 +310,16 @@ void SkOpSpan::applyCoincidence(SkOpSpan* opp) {
|
|
|
| bool SkOpSpan::containsCoincidence(const SkOpSegment* segment) const {
|
| SkASSERT(this->segment() != segment);
|
| - const SkOpSpan* next = this;
|
| - while ((next = next->fCoincident) != this) {
|
| + const SkOpSpan* next = fCoincident;
|
| + do {
|
| if (next->segment() == segment) {
|
| return true;
|
| }
|
| - }
|
| + } while ((next = next->fCoincident) != this);
|
| return false;
|
| }
|
|
|
| -void SkOpSpan::detach() {
|
| +void SkOpSpan::detach(SkOpPtT* kept) {
|
| SkASSERT(!final());
|
| SkOpSpan* prev = this->prev();
|
| SkASSERT(prev);
|
| @@ -313,6 +328,7 @@ void SkOpSpan::detach() {
|
| prev->setNext(next);
|
| next->setPrev(prev);
|
| this->segment()->detach(this);
|
| + this->globalState()->coincidence()->fixUp(this->ptT(), kept);
|
| this->ptT()->setDeleted();
|
| }
|
|
|
| @@ -328,175 +344,12 @@ void SkOpSpan::init(SkOpSegment* segment, SkOpSpan* prev, double t, const SkPoin
|
| segment->bumpCount();
|
| }
|
|
|
| -void SkOpSpan::mergeAttributes(SkOpSpan* span) {
|
| - SkASSERT(!span->fToAngle);
|
| - if (span->fCoincident) {
|
| - this->insertCoincidence(span);
|
| - }
|
| -}
|
| -
|
| -void SkOpCoincidence::add(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* oppPtTStart,
|
| - SkOpPtT* oppPtTEnd, bool flipped, SkChunkAlloc* allocator) {
|
| - SkCoincidentSpans* coinRec = SkOpTAllocator<SkCoincidentSpans>::Allocate(allocator);
|
| - SkOpSpanBase* coinEnd = coinPtTEnd->span();
|
| - SkOpSpanBase* oppEnd = oppPtTEnd->span();
|
| - SkOpSpan* coinStart = coinPtTStart->span()->upCast();
|
| - SkASSERT(coinStart == coinStart->starter(coinEnd));
|
| - SkOpSpan* oppStart = (flipped ? oppPtTEnd : oppPtTStart)->span()->upCast();
|
| - SkASSERT(oppStart == oppStart->starter(oppEnd));
|
| - coinStart->insertCoincidence(oppStart);
|
| - coinEnd->insertCoinEnd(oppEnd);
|
| - coinRec->fNext = this->fHead;
|
| - coinRec->fCoinPtTStart = coinPtTStart;
|
| - coinRec->fCoinPtTEnd = coinPtTEnd;
|
| - coinRec->fOppPtTStart = oppPtTStart;
|
| - coinRec->fOppPtTEnd = oppPtTEnd;
|
| - coinRec->fFlipped = flipped;
|
| - this->fHead = coinRec;
|
| -}
|
| -
|
| -bool SkOpCoincidence::contains(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* oppPtTStart,
|
| - SkOpPtT* oppPtTEnd, bool flipped) {
|
| - SkCoincidentSpans* coin = fHead;
|
| - if (!coin) {
|
| - return false;
|
| - }
|
| - do {
|
| - if (coin->fCoinPtTStart == coinPtTStart && coin->fCoinPtTEnd == coinPtTEnd
|
| - && coin->fOppPtTStart == oppPtTStart && coin->fOppPtTEnd == oppPtTEnd
|
| - && coin->fFlipped == flipped) {
|
| - return true;
|
| - }
|
| - } while ((coin = coin->fNext));
|
| - return false;
|
| -}
|
| -
|
| -// walk span sets in parallel, moving winding from one to the other
|
| -void SkOpCoincidence::apply() {
|
| - SkCoincidentSpans* coin = fHead;
|
| - if (!coin) {
|
| - return;
|
| - }
|
| - do {
|
| - SkOpSpanBase* end = coin->fCoinPtTEnd->span();
|
| - SkOpSpan* start = coin->fCoinPtTStart->span()->upCast();
|
| - SkASSERT(start == start->starter(end));
|
| - bool flipped = coin->fFlipped;
|
| - SkOpSpanBase* oEnd = (flipped ? coin->fOppPtTStart : coin->fOppPtTEnd)->span();
|
| - SkOpSpan* oStart = (flipped ? coin->fOppPtTEnd : coin->fOppPtTStart)->span()->upCast();
|
| - SkASSERT(oStart == oStart->starter(oEnd));
|
| - SkOpSegment* segment = start->segment();
|
| - SkOpSegment* oSegment = oStart->segment();
|
| - bool operandSwap = segment->operand() != oSegment->operand();
|
| - if (flipped) {
|
| - do {
|
| - SkOpSpanBase* oNext = oStart->next();
|
| - if (oNext == oEnd) {
|
| - break;
|
| - }
|
| - oStart = oNext->upCast();
|
| - } while (true);
|
| - }
|
| - bool isXor = segment->isXor();
|
| - bool oppXor = oSegment->isXor();
|
| - do {
|
| - int windValue = start->windValue();
|
| - int oWindValue = oStart->windValue();
|
| - int oppValue = start->oppValue();
|
| - int oOppValue = oStart->oppValue();
|
| - // winding values are added or subtracted depending on direction and wind type
|
| - // same or opposite values are summed depending on the operand value
|
| - if (windValue >= oWindValue) {
|
| - if (operandSwap) {
|
| - SkTSwap(oWindValue, oOppValue);
|
| - }
|
| - if (flipped) {
|
| - windValue -= oWindValue;
|
| - oppValue -= oOppValue;
|
| - } else {
|
| - windValue += oWindValue;
|
| - oppValue += oOppValue;
|
| - }
|
| - if (isXor) {
|
| - windValue &= 1;
|
| - }
|
| - if (oppXor) {
|
| - oppValue &= 1;
|
| - }
|
| - oWindValue = oOppValue = 0;
|
| - } else {
|
| - if (operandSwap) {
|
| - SkTSwap(windValue, oppValue);
|
| - }
|
| - if (flipped) {
|
| - oWindValue -= windValue;
|
| - oOppValue -= oppValue;
|
| - } else {
|
| - oWindValue += windValue;
|
| - oOppValue += oppValue;
|
| - }
|
| - if (isXor) {
|
| - oOppValue &= 1;
|
| - }
|
| - if (oppXor) {
|
| - oWindValue &= 1;
|
| - }
|
| - windValue = oppValue = 0;
|
| - }
|
| - start->setWindValue(windValue);
|
| - start->setOppValue(oppValue);
|
| - oStart->setWindValue(oWindValue);
|
| - oStart->setOppValue(oOppValue);
|
| - if (!windValue && !oppValue) {
|
| - segment->markDone(start);
|
| - }
|
| - if (!oWindValue && !oOppValue) {
|
| - oSegment->markDone(oStart);
|
| - }
|
| - SkOpSpanBase* next = start->next();
|
| - SkOpSpanBase* oNext = flipped ? oStart->prev() : oStart->next();
|
| - if (next == end) {
|
| - break;
|
| - }
|
| - start = next->upCast();
|
| - oStart = oNext->upCast();
|
| - } while (true);
|
| - } while ((coin = coin->fNext));
|
| -}
|
| -
|
| -void SkOpCoincidence::mark() {
|
| - SkCoincidentSpans* coin = fHead;
|
| - if (!coin) {
|
| +void SkOpSpan::setOppSum(int oppSum) {
|
| + SkASSERT(!final());
|
| + if (fOppSum != SK_MinS32 && fOppSum != oppSum) {
|
| + this->globalState()->setWindingFailed();
|
| return;
|
| }
|
| - do {
|
| - SkOpSpanBase* end = coin->fCoinPtTEnd->span();
|
| - SkOpSpanBase* oldEnd = end;
|
| - SkOpSpan* start = coin->fCoinPtTStart->span()->starter(&end);
|
| - SkOpSpanBase* oEnd = coin->fOppPtTEnd->span();
|
| - SkOpSpanBase* oOldEnd = oEnd;
|
| - SkOpSpanBase* oStart = coin->fOppPtTStart->span()->starter(&oEnd);
|
| - bool flipped = (end == oldEnd) != (oEnd == oOldEnd);
|
| - if (flipped) {
|
| - SkTSwap(oStart, oEnd);
|
| - }
|
| - SkOpSpanBase* next = start;
|
| - SkOpSpanBase* oNext = oStart;
|
| - do {
|
| - next = next->upCast()->next();
|
| - oNext = flipped ? oNext->prev() : oNext->upCast()->next();
|
| - if (next == end) {
|
| - SkASSERT(oNext == oEnd);
|
| - break;
|
| - }
|
| - if (!next->containsCoinEnd(oNext)) {
|
| - next->insertCoinEnd(oNext);
|
| - }
|
| - SkOpSpan* nextSpan = next->upCast();
|
| - SkOpSpan* oNextSpan = oNext->upCast();
|
| - if (!nextSpan->containsCoincidence(oNextSpan)) {
|
| - nextSpan->insertCoincidence(oNextSpan);
|
| - }
|
| - } while (true);
|
| - } while ((coin = coin->fNext));
|
| + SkASSERT(!DEBUG_LIMIT_WIND_SUM || abs(oppSum) <= DEBUG_LIMIT_WIND_SUM);
|
| + fOppSum = oppSum;
|
| }
|
|
|