SkOpSpan.cpp revision bca19f77479adfd8ba2171753382bc8bf4c2b4ca
154359294a7c9dc54802d512a5d891a35c1663392caryclark/*
254359294a7c9dc54802d512a5d891a35c1663392caryclark * Copyright 2014 Google Inc.
354359294a7c9dc54802d512a5d891a35c1663392caryclark *
454359294a7c9dc54802d512a5d891a35c1663392caryclark * Use of this source code is governed by a BSD-style license that can be
554359294a7c9dc54802d512a5d891a35c1663392caryclark * found in the LICENSE file.
654359294a7c9dc54802d512a5d891a35c1663392caryclark */
754359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkOpCoincidence.h"
854359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkOpContour.h"
954359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkOpSegment.h"
1054359294a7c9dc54802d512a5d891a35c1663392caryclark#include "SkPathWriter.h"
1154359294a7c9dc54802d512a5d891a35c1663392caryclark
1254359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpPtT::alias() const {
1354359294a7c9dc54802d512a5d891a35c1663392caryclark    return this->span()->ptT() != this;
1454359294a7c9dc54802d512a5d891a35c1663392caryclark}
1554359294a7c9dc54802d512a5d891a35c1663392caryclark
1654359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpContour* SkOpPtT::contour() const {
1754359294a7c9dc54802d512a5d891a35c1663392caryclark    return segment()->contour();
1854359294a7c9dc54802d512a5d891a35c1663392caryclark}
1954359294a7c9dc54802d512a5d891a35c1663392caryclark
2054359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpGlobalState* SkOpPtT::globalState() const {
2154359294a7c9dc54802d512a5d891a35c1663392caryclark    return contour()->globalState();
2254359294a7c9dc54802d512a5d891a35c1663392caryclark}
2354359294a7c9dc54802d512a5d891a35c1663392caryclark
2454359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpPtT::init(SkOpSpanBase* span, double t, const SkPoint& pt, bool duplicate) {
2554359294a7c9dc54802d512a5d891a35c1663392caryclark    fT = t;
2654359294a7c9dc54802d512a5d891a35c1663392caryclark    fPt = pt;
2754359294a7c9dc54802d512a5d891a35c1663392caryclark    fSpan = span;
2854359294a7c9dc54802d512a5d891a35c1663392caryclark    fNext = this;
2954359294a7c9dc54802d512a5d891a35c1663392caryclark    fDuplicatePt = duplicate;
3054359294a7c9dc54802d512a5d891a35c1663392caryclark    fDeleted = false;
311049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDEBUGCODE(fID = span->globalState()->nextPtTID());
3254359294a7c9dc54802d512a5d891a35c1663392caryclark}
3354359294a7c9dc54802d512a5d891a35c1663392caryclark
3454359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpPtT::onEnd() const {
3554359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpanBase* span = this->span();
3654359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->ptT() != this) {
3754359294a7c9dc54802d512a5d891a35c1663392caryclark        return false;
3854359294a7c9dc54802d512a5d891a35c1663392caryclark    }
3954359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSegment* segment = this->segment();
4054359294a7c9dc54802d512a5d891a35c1663392caryclark    return span == segment->head() || span == segment->tail();
4154359294a7c9dc54802d512a5d891a35c1663392caryclark}
4254359294a7c9dc54802d512a5d891a35c1663392caryclark
4354359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpPtT* SkOpPtT::prev() {
4454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpPtT* result = this;
4554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpPtT* next = this;
4654359294a7c9dc54802d512a5d891a35c1663392caryclark    while ((next = next->fNext) != this) {
4754359294a7c9dc54802d512a5d891a35c1663392caryclark        result = next;
4854359294a7c9dc54802d512a5d891a35c1663392caryclark    }
4954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(result->fNext == this);
5054359294a7c9dc54802d512a5d891a35c1663392caryclark    return result;
5154359294a7c9dc54802d512a5d891a35c1663392caryclark}
5254359294a7c9dc54802d512a5d891a35c1663392caryclark
5354359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpPtT* SkOpPtT::remove() {
5454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpPtT* prev = this;
5554359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
5654359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpPtT* next = prev->fNext;
5754359294a7c9dc54802d512a5d891a35c1663392caryclark        if (next == this) {
5854359294a7c9dc54802d512a5d891a35c1663392caryclark            prev->removeNext(this);
5954359294a7c9dc54802d512a5d891a35c1663392caryclark            SkASSERT(prev->fNext != prev);
6054359294a7c9dc54802d512a5d891a35c1663392caryclark            fDeleted = true;
6154359294a7c9dc54802d512a5d891a35c1663392caryclark            return prev;
6254359294a7c9dc54802d512a5d891a35c1663392caryclark        }
6354359294a7c9dc54802d512a5d891a35c1663392caryclark        prev = next;
6454359294a7c9dc54802d512a5d891a35c1663392caryclark    } while (prev != this);
6554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(0);
6654359294a7c9dc54802d512a5d891a35c1663392caryclark    return NULL;
6754359294a7c9dc54802d512a5d891a35c1663392caryclark}
6854359294a7c9dc54802d512a5d891a35c1663392caryclark
6954359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpPtT::removeNext(SkOpPtT* kept) {
7054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(this->fNext);
7154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpPtT* next = this->fNext;
7254359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(this != next->fNext);
7354359294a7c9dc54802d512a5d891a35c1663392caryclark    this->fNext = next->fNext;
7454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* span = next->span();
7554359294a7c9dc54802d512a5d891a35c1663392caryclark    next->setDeleted();
7654359294a7c9dc54802d512a5d891a35c1663392caryclark    if (span->ptT() == next) {
7754359294a7c9dc54802d512a5d891a35c1663392caryclark        span->upCast()->detach(kept);
7854359294a7c9dc54802d512a5d891a35c1663392caryclark    }
7954359294a7c9dc54802d512a5d891a35c1663392caryclark}
8054359294a7c9dc54802d512a5d891a35c1663392caryclark
8154359294a7c9dc54802d512a5d891a35c1663392caryclarkconst SkOpSegment* SkOpPtT::segment() const {
8254359294a7c9dc54802d512a5d891a35c1663392caryclark    return span()->segment();
8354359294a7c9dc54802d512a5d891a35c1663392caryclark}
8454359294a7c9dc54802d512a5d891a35c1663392caryclark
8554359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpSegment* SkOpPtT::segment() {
8654359294a7c9dc54802d512a5d891a35c1663392caryclark    return span()->segment();
8754359294a7c9dc54802d512a5d891a35c1663392caryclark}
8854359294a7c9dc54802d512a5d891a35c1663392caryclark
8954359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpanBase::align() {
9054359294a7c9dc54802d512a5d891a35c1663392caryclark    if (this->fAligned) {
9154359294a7c9dc54802d512a5d891a35c1663392caryclark        return;
9254359294a7c9dc54802d512a5d891a35c1663392caryclark    }
9354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(!zero_or_one(this->fPtT.fT));
9454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(this->fPtT.next());
9554359294a7c9dc54802d512a5d891a35c1663392caryclark    // if a linked pt/t pair has a t of zero or one, use it as the base for alignment
9654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpPtT* ptT = &this->fPtT, * stopPtT = ptT;
9754359294a7c9dc54802d512a5d891a35c1663392caryclark    while ((ptT = ptT->next()) != stopPtT) {
9854359294a7c9dc54802d512a5d891a35c1663392caryclark        if (zero_or_one(ptT->fT)) {
9954359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpSegment* segment = ptT->segment();
10054359294a7c9dc54802d512a5d891a35c1663392caryclark            SkASSERT(this->segment() != segment);
10154359294a7c9dc54802d512a5d891a35c1663392caryclark            SkASSERT(segment->head()->ptT() == ptT || segment->tail()->ptT() == ptT);
10254359294a7c9dc54802d512a5d891a35c1663392caryclark            if (ptT->fT) {
10354359294a7c9dc54802d512a5d891a35c1663392caryclark                segment->tail()->alignEnd(1, segment->lastPt());
10454359294a7c9dc54802d512a5d891a35c1663392caryclark            } else {
10554359294a7c9dc54802d512a5d891a35c1663392caryclark                segment->head()->alignEnd(0, segment->pts()[0]);
10654359294a7c9dc54802d512a5d891a35c1663392caryclark            }
10754359294a7c9dc54802d512a5d891a35c1663392caryclark            return;
10854359294a7c9dc54802d512a5d891a35c1663392caryclark        }
10954359294a7c9dc54802d512a5d891a35c1663392caryclark    }
11054359294a7c9dc54802d512a5d891a35c1663392caryclark    alignInner();
11154359294a7c9dc54802d512a5d891a35c1663392caryclark    this->fAligned = true;
11254359294a7c9dc54802d512a5d891a35c1663392caryclark}
11354359294a7c9dc54802d512a5d891a35c1663392caryclark
11454359294a7c9dc54802d512a5d891a35c1663392caryclark
11554359294a7c9dc54802d512a5d891a35c1663392caryclark// FIXME: delete spans that collapse
11654359294a7c9dc54802d512a5d891a35c1663392caryclark// delete segments that collapse
11754359294a7c9dc54802d512a5d891a35c1663392caryclark// delete contours that collapse
11854359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpanBase::alignEnd(double t, const SkPoint& pt) {
11954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(zero_or_one(t));
12054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSegment* segment = this->segment();
12154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(t ? segment->lastPt() == pt : segment->pts()[0] == pt);
12254359294a7c9dc54802d512a5d891a35c1663392caryclark    alignInner();
12354359294a7c9dc54802d512a5d891a35c1663392caryclark    *segment->writablePt(!!t) = pt;
12454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpPtT* ptT = &this->fPtT;
12554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(t == ptT->fT);
12654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(pt == ptT->fPt);
12754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpPtT* test = ptT, * stopPtT = ptT;
12854359294a7c9dc54802d512a5d891a35c1663392caryclark    while ((test = test->next()) != stopPtT) {
12954359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpSegment* other = test->segment();
13054359294a7c9dc54802d512a5d891a35c1663392caryclark        if (other == this->segment()) {
13154359294a7c9dc54802d512a5d891a35c1663392caryclark            continue;
13254359294a7c9dc54802d512a5d891a35c1663392caryclark        }
13354359294a7c9dc54802d512a5d891a35c1663392caryclark        if (!zero_or_one(test->fT)) {
13454359294a7c9dc54802d512a5d891a35c1663392caryclark            continue;
13554359294a7c9dc54802d512a5d891a35c1663392caryclark        }
13654359294a7c9dc54802d512a5d891a35c1663392caryclark        *other->writablePt(!!test->fT) = pt;
13754359294a7c9dc54802d512a5d891a35c1663392caryclark    }
13854359294a7c9dc54802d512a5d891a35c1663392caryclark    this->fAligned = true;
13954359294a7c9dc54802d512a5d891a35c1663392caryclark}
14054359294a7c9dc54802d512a5d891a35c1663392caryclark
14154359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpanBase::alignInner() {
14254359294a7c9dc54802d512a5d891a35c1663392caryclark    // force the spans to share points and t values
14354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpPtT* ptT = &this->fPtT, * stopPtT = ptT;
14454359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkPoint& pt = ptT->fPt;
14554359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
14654359294a7c9dc54802d512a5d891a35c1663392caryclark        ptT->fPt = pt;
14754359294a7c9dc54802d512a5d891a35c1663392caryclark        const SkOpSpanBase* span = ptT->span();
14854359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpPtT* test = ptT;
14954359294a7c9dc54802d512a5d891a35c1663392caryclark        do {
15054359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpPtT* prev = test;
15154359294a7c9dc54802d512a5d891a35c1663392caryclark            if ((test = test->next()) == stopPtT) {
15254359294a7c9dc54802d512a5d891a35c1663392caryclark                break;
15354359294a7c9dc54802d512a5d891a35c1663392caryclark            }
15454359294a7c9dc54802d512a5d891a35c1663392caryclark            if (span == test->span() && !span->segment()->ptsDisjoint(*ptT, *test)) {
15554359294a7c9dc54802d512a5d891a35c1663392caryclark                // omit aliases that alignment makes redundant
15654359294a7c9dc54802d512a5d891a35c1663392caryclark                if ((!ptT->alias() || test->alias()) && (ptT->onEnd() || !test->onEnd())) {
15754359294a7c9dc54802d512a5d891a35c1663392caryclark                    SkASSERT(test->alias());
15854359294a7c9dc54802d512a5d891a35c1663392caryclark                    prev->removeNext(ptT);
15954359294a7c9dc54802d512a5d891a35c1663392caryclark                    test = prev;
16054359294a7c9dc54802d512a5d891a35c1663392caryclark                } else {
16154359294a7c9dc54802d512a5d891a35c1663392caryclark                    SkASSERT(ptT->alias());
16254359294a7c9dc54802d512a5d891a35c1663392caryclark                    stopPtT = ptT = ptT->remove();
16354359294a7c9dc54802d512a5d891a35c1663392caryclark                    break;
16454359294a7c9dc54802d512a5d891a35c1663392caryclark                }
16554359294a7c9dc54802d512a5d891a35c1663392caryclark            }
16654359294a7c9dc54802d512a5d891a35c1663392caryclark        } while (true);
16754359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((ptT = ptT->next()) != stopPtT);
16854359294a7c9dc54802d512a5d891a35c1663392caryclark}
16954359294a7c9dc54802d512a5d891a35c1663392caryclark
17054359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpanBase::contains(const SkOpSpanBase* span) const {
17154359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpPtT* start = &fPtT;
17254359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpPtT* check = &span->fPtT;
17354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(start != check);
17454359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpPtT* walk = start;
17554359294a7c9dc54802d512a5d891a35c1663392caryclark    while ((walk = walk->next()) != start) {
17654359294a7c9dc54802d512a5d891a35c1663392caryclark        if (walk == check) {
17754359294a7c9dc54802d512a5d891a35c1663392caryclark            return true;
17854359294a7c9dc54802d512a5d891a35c1663392caryclark        }
17954359294a7c9dc54802d512a5d891a35c1663392caryclark    }
18054359294a7c9dc54802d512a5d891a35c1663392caryclark    return false;
18154359294a7c9dc54802d512a5d891a35c1663392caryclark}
18254359294a7c9dc54802d512a5d891a35c1663392caryclark
18354359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpPtT* SkOpSpanBase::contains(const SkOpSegment* segment) {
18454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpPtT* start = &fPtT;
18554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpPtT* walk = start;
18654359294a7c9dc54802d512a5d891a35c1663392caryclark    while ((walk = walk->next()) != start) {
18754359294a7c9dc54802d512a5d891a35c1663392caryclark        if (walk->segment() == segment) {
18854359294a7c9dc54802d512a5d891a35c1663392caryclark            return walk;
18954359294a7c9dc54802d512a5d891a35c1663392caryclark        }
19054359294a7c9dc54802d512a5d891a35c1663392caryclark    }
19154359294a7c9dc54802d512a5d891a35c1663392caryclark    return NULL;
19254359294a7c9dc54802d512a5d891a35c1663392caryclark}
19354359294a7c9dc54802d512a5d891a35c1663392caryclark
19454359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpanBase::containsCoinEnd(const SkOpSegment* segment) const {
19554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(this->segment() != segment);
19654359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpanBase* next = this;
19754359294a7c9dc54802d512a5d891a35c1663392caryclark    while ((next = next->fCoinEnd) != this) {
19854359294a7c9dc54802d512a5d891a35c1663392caryclark        if (next->segment() == segment) {
19954359294a7c9dc54802d512a5d891a35c1663392caryclark            return true;
20054359294a7c9dc54802d512a5d891a35c1663392caryclark        }
20154359294a7c9dc54802d512a5d891a35c1663392caryclark    }
20254359294a7c9dc54802d512a5d891a35c1663392caryclark    return false;
20354359294a7c9dc54802d512a5d891a35c1663392caryclark}
20454359294a7c9dc54802d512a5d891a35c1663392caryclark
20554359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpContour* SkOpSpanBase::contour() const {
20654359294a7c9dc54802d512a5d891a35c1663392caryclark    return segment()->contour();
20754359294a7c9dc54802d512a5d891a35c1663392caryclark}
20854359294a7c9dc54802d512a5d891a35c1663392caryclark
20954359294a7c9dc54802d512a5d891a35c1663392caryclarkSkOpGlobalState* SkOpSpanBase::globalState() const {
21054359294a7c9dc54802d512a5d891a35c1663392caryclark    return contour()->globalState();
21154359294a7c9dc54802d512a5d891a35c1663392caryclark}
21254359294a7c9dc54802d512a5d891a35c1663392caryclark
21354359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpanBase::initBase(SkOpSegment* segment, SkOpSpan* prev, double t, const SkPoint& pt) {
21454359294a7c9dc54802d512a5d891a35c1663392caryclark    fSegment = segment;
21554359294a7c9dc54802d512a5d891a35c1663392caryclark    fPtT.init(this, t, pt, false);
21654359294a7c9dc54802d512a5d891a35c1663392caryclark    fCoinEnd = this;
21754359294a7c9dc54802d512a5d891a35c1663392caryclark    fFromAngle = NULL;
21854359294a7c9dc54802d512a5d891a35c1663392caryclark    fPrev = prev;
21908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    fSpanAdds = 0;
22054359294a7c9dc54802d512a5d891a35c1663392caryclark    fAligned = true;
22154359294a7c9dc54802d512a5d891a35c1663392caryclark    fChased = false;
2221049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDEBUGCODE(fCount = 1);
2231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDEBUGCODE(fID = globalState()->nextSpanID());
22454359294a7c9dc54802d512a5d891a35c1663392caryclark}
22554359294a7c9dc54802d512a5d891a35c1663392caryclark
22654359294a7c9dc54802d512a5d891a35c1663392caryclark// this pair of spans share a common t value or point; merge them and eliminate duplicates
22754359294a7c9dc54802d512a5d891a35c1663392caryclark// this does not compute the best t or pt value; this merely moves all data into a single list
22854359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpanBase::merge(SkOpSpan* span) {
22954359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpPtT* spanPtT = span->ptT();
23054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(this->t() != spanPtT->fT);
23154359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(!zero_or_one(spanPtT->fT));
23254359294a7c9dc54802d512a5d891a35c1663392caryclark    span->detach(this->ptT());
23354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpPtT* remainder = spanPtT->next();
23454359294a7c9dc54802d512a5d891a35c1663392caryclark    ptT()->insert(spanPtT);
23554359294a7c9dc54802d512a5d891a35c1663392caryclark    while (remainder != spanPtT) {
23654359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpPtT* next = remainder->next();
23754359294a7c9dc54802d512a5d891a35c1663392caryclark        SkOpPtT* compare = spanPtT->next();
23854359294a7c9dc54802d512a5d891a35c1663392caryclark        while (compare != spanPtT) {
23954359294a7c9dc54802d512a5d891a35c1663392caryclark            SkOpPtT* nextC = compare->next();
24054359294a7c9dc54802d512a5d891a35c1663392caryclark            if (nextC->span() == remainder->span() && nextC->fT == remainder->fT) {
24154359294a7c9dc54802d512a5d891a35c1663392caryclark                goto tryNextRemainder;
24254359294a7c9dc54802d512a5d891a35c1663392caryclark            }
24354359294a7c9dc54802d512a5d891a35c1663392caryclark            compare = nextC;
24454359294a7c9dc54802d512a5d891a35c1663392caryclark        }
24554359294a7c9dc54802d512a5d891a35c1663392caryclark        spanPtT->insert(remainder);
24654359294a7c9dc54802d512a5d891a35c1663392caryclarktryNextRemainder:
24754359294a7c9dc54802d512a5d891a35c1663392caryclark        remainder = next;
24854359294a7c9dc54802d512a5d891a35c1663392caryclark    }
24908bc8488fa2ea2d2a17efb1443f0ec6579d5a3c8caryclark    fSpanAdds += span->fSpanAdds;
25054359294a7c9dc54802d512a5d891a35c1663392caryclark}
25154359294a7c9dc54802d512a5d891a35c1663392caryclark
252bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclarkint SkOpSpan::computeWindSum() {
253bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    SkOpGlobalState* globals = this->globalState();
254bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    SkOpContour* contourHead = globals->contourHead();
255bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    int windTry = 0;
256bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    while (!this->sortableTop(contourHead) && ++windTry < SkOpGlobalState::kMaxWindingTries) {
257bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark        ;
258bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    }
259bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark    return this->windSum();
260bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark}
261bca19f77479adfd8ba2171753382bc8bf4c2b4cacaryclark
26254359294a7c9dc54802d512a5d891a35c1663392caryclarkbool SkOpSpan::containsCoincidence(const SkOpSegment* segment) const {
26354359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(this->segment() != segment);
26454359294a7c9dc54802d512a5d891a35c1663392caryclark    const SkOpSpan* next = fCoincident;
26554359294a7c9dc54802d512a5d891a35c1663392caryclark    do {
26654359294a7c9dc54802d512a5d891a35c1663392caryclark        if (next->segment() == segment) {
26754359294a7c9dc54802d512a5d891a35c1663392caryclark            return true;
26854359294a7c9dc54802d512a5d891a35c1663392caryclark        }
26954359294a7c9dc54802d512a5d891a35c1663392caryclark    } while ((next = next->fCoincident) != this);
27054359294a7c9dc54802d512a5d891a35c1663392caryclark    return false;
27154359294a7c9dc54802d512a5d891a35c1663392caryclark}
27254359294a7c9dc54802d512a5d891a35c1663392caryclark
27354359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpan::detach(SkOpPtT* kept) {
27454359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(!final());
27554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpan* prev = this->prev();
27654359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(prev);
27754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkOpSpanBase* next = this->next();
27854359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(next);
27954359294a7c9dc54802d512a5d891a35c1663392caryclark    prev->setNext(next);
28054359294a7c9dc54802d512a5d891a35c1663392caryclark    next->setPrev(prev);
28154359294a7c9dc54802d512a5d891a35c1663392caryclark    this->segment()->detach(this);
28254359294a7c9dc54802d512a5d891a35c1663392caryclark    this->globalState()->coincidence()->fixUp(this->ptT(), kept);
28354359294a7c9dc54802d512a5d891a35c1663392caryclark    this->ptT()->setDeleted();
28454359294a7c9dc54802d512a5d891a35c1663392caryclark}
28554359294a7c9dc54802d512a5d891a35c1663392caryclark
28654359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpan::init(SkOpSegment* segment, SkOpSpan* prev, double t, const SkPoint& pt) {
28754359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(t != 1);
28854359294a7c9dc54802d512a5d891a35c1663392caryclark    initBase(segment, prev, t, pt);
28954359294a7c9dc54802d512a5d891a35c1663392caryclark    fCoincident = this;
29054359294a7c9dc54802d512a5d891a35c1663392caryclark    fToAngle = NULL;
29154359294a7c9dc54802d512a5d891a35c1663392caryclark    fWindSum = fOppSum = SK_MinS32;
29254359294a7c9dc54802d512a5d891a35c1663392caryclark    fWindValue = 1;
29354359294a7c9dc54802d512a5d891a35c1663392caryclark    fOppValue = 0;
294624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    fTopTTry = 0;
29554359294a7c9dc54802d512a5d891a35c1663392caryclark    fChased = fDone = false;
29654359294a7c9dc54802d512a5d891a35c1663392caryclark    segment->bumpCount();
29754359294a7c9dc54802d512a5d891a35c1663392caryclark}
29854359294a7c9dc54802d512a5d891a35c1663392caryclark
29954359294a7c9dc54802d512a5d891a35c1663392caryclarkvoid SkOpSpan::setOppSum(int oppSum) {
30054359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(!final());
30154359294a7c9dc54802d512a5d891a35c1663392caryclark    if (fOppSum != SK_MinS32 && fOppSum != oppSum) {
30254359294a7c9dc54802d512a5d891a35c1663392caryclark        this->globalState()->setWindingFailed();
30354359294a7c9dc54802d512a5d891a35c1663392caryclark        return;
30454359294a7c9dc54802d512a5d891a35c1663392caryclark    }
30554359294a7c9dc54802d512a5d891a35c1663392caryclark    SkASSERT(!DEBUG_LIMIT_WIND_SUM || abs(oppSum) <= DEBUG_LIMIT_WIND_SUM);
30654359294a7c9dc54802d512a5d891a35c1663392caryclark    fOppSum = oppSum;
30754359294a7c9dc54802d512a5d891a35c1663392caryclark}
308624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark
309624637cc8ec22c000409704d0b403ac1b81ad4b0caryclarkvoid SkOpSpan::setWindSum(int windSum) {
310624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkASSERT(!final());
311624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    if (fWindSum != SK_MinS32 && fWindSum != windSum) {
312624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        this->globalState()->setWindingFailed();
313624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark        return;
314624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    }
315624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    SkASSERT(!DEBUG_LIMIT_WIND_SUM || abs(windSum) <= DEBUG_LIMIT_WIND_SUM);
316624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark    fWindSum = windSum;
317624637cc8ec22c000409704d0b403ac1b81ad4b0caryclark}
318