107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/*
207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2012 Google Inc.
307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *
407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be
507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * found in the LICENSE file.
607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */
707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#ifndef SkOpSegment_DEFINE
807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#define SkOpSegment_DEFINE
907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkOpAngle.h"
11cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com#include "SkOpSpan.h"
1207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkPathOpsBounds.h"
1307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkPathOpsCurve.h"
14d892bd8ba676d34d4ce4a73ac7aad88e102fad70caryclark@google.com#include "SkTArray.h"
1507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkTDArray.h"
1607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
170bcb8ca8a8fc04a4a9c69013ccc46645d2f2ae77commit-bot@chromium.org#if defined(SK_DEBUG) || !FORCE_RELEASE
180bcb8ca8a8fc04a4a9c69013ccc46645d2f2ae77commit-bot@chromium.org#include "SkThread.h"
190bcb8ca8a8fc04a4a9c69013ccc46645d2f2ae77commit-bot@chromium.org#endif
200bcb8ca8a8fc04a4a9c69013ccc46645d2f2ae77commit-bot@chromium.org
21dac1d17027dcaa5596885a9f333979418b35001ccaryclarkstruct SkCoincidence;
2207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass SkPathWriter;
2307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass SkOpSegment {
2507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.compublic:
2607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment() {
274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if defined(SK_DEBUG) || !FORCE_RELEASE
280bcb8ca8a8fc04a4a9c69013ccc46645d2f2ae77commit-bot@chromium.org        fID = sk_atomic_inc(&SkPathOpsDebug::gSegmentID);
2907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool operator<(const SkOpSegment& rh) const {
3307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fBounds.fTop < rh.fBounds.fTop;
3407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
3507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
36dac1d17027dcaa5596885a9f333979418b35001ccaryclark    struct AlignedSpan  {
37dac1d17027dcaa5596885a9f333979418b35001ccaryclark        double fOldT;
38dac1d17027dcaa5596885a9f333979418b35001ccaryclark        double fT;
39dac1d17027dcaa5596885a9f333979418b35001ccaryclark        SkPoint fOldPt;
40dac1d17027dcaa5596885a9f333979418b35001ccaryclark        SkPoint fPt;
41dac1d17027dcaa5596885a9f333979418b35001ccaryclark        const SkOpSegment* fSegment;
42dac1d17027dcaa5596885a9f333979418b35001ccaryclark        const SkOpSegment* fOther1;
43dac1d17027dcaa5596885a9f333979418b35001ccaryclark        const SkOpSegment* fOther2;
44dac1d17027dcaa5596885a9f333979418b35001ccaryclark    };
454431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
4607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const SkPathOpsBounds& bounds() const {
4707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fBounds;
4807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
4907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
5007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // OPTIMIZE
5107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // when the edges are initially walked, they don't automatically get the prior and next
5207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // edges assigned to positions t=0 and t=1. Doing that would remove the need for this check,
5307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // and would additionally remove the need for similar checks in condition edges. It would
5407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // also allow intersection code to assume end of segment intersections (maybe?)
5507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool complete() const {
5607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        int count = fTs.count();
5707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return count > 1 && fTs[0].fT == 0 && fTs[--count].fT == 1;
5807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
5907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
60cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    int count() const {
61cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        return fTs.count();
62cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    }
63cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com
6407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool done() const {
6507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkASSERT(fDoneSpans <= fTs.count());
6607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fDoneSpans == fTs.count();
6707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
6807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
6907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool done(int min) const {
7007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fTs[min].fDone;
7107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
7207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
7307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool done(const SkOpAngle* angle) const {
7407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return done(SkMin32(angle->start(), angle->end()));
7507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
7607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
77570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    SkDPoint dPtAtT(double mid) const {
78570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        return (*CurveDPointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid);
79570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
80570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
8107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkVector dxdy(int index) const {
82277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        return (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, fTs[index].fT);
8307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
8407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
8507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkScalar dy(int index) const {
8607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return dxdy(index).fY;
8707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
8807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
89dac1d17027dcaa5596885a9f333979418b35001ccaryclark    bool hasMultiples() const {
90dac1d17027dcaa5596885a9f333979418b35001ccaryclark        return fMultiples;
91dac1d17027dcaa5596885a9f333979418b35001ccaryclark    }
92dac1d17027dcaa5596885a9f333979418b35001ccaryclark
934431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool hasSmall() const {
944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return fSmall;
954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool hasTiny() const {
984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return fTiny;
994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
1004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
10107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool intersected() const {
10207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fTs.count() > 0;
10307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
10407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
10507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool isCanceled(int tIndex) const {
10607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fTs[tIndex].fWindValue == 0 && fTs[tIndex].fOppValue == 0;
10707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
10807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
10907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool isConnected(int startIndex, int endIndex) const {
11007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fTs[startIndex].fWindSum != SK_MinS32 || fTs[endIndex].fWindSum != SK_MinS32;
11107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
11207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
11307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool isHorizontal() const {
11407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fBounds.fTop == fBounds.fBottom;
11507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
11607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
11707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool isVertical() const {
11807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fBounds.fLeft == fBounds.fRight;
11907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
12007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
12107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool isVertical(int start, int end) const {
122277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        return (*CurveIsVertical[SkPathOpsVerbToPoints(fVerb)])(fPts, start, end);
12307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
12407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
12507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool operand() const {
12607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fOperand;
12707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
12807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
12907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int oppSign(const SkOpAngle* angle) const {
13007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkASSERT(angle->segment() == this);
13107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return oppSign(angle->start(), angle->end());
13207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
13307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
13407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int oppSign(int startIndex, int endIndex) const {
13507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        int result = startIndex < endIndex ? -fTs[startIndex].fOppValue : fTs[endIndex].fOppValue;
13607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WIND_BUMP
13707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("%s oppSign=%d\n", __FUNCTION__, result);
13807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
13907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return result;
14007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
14107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
14207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int oppSum(int tIndex) const {
14307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fTs[tIndex].fOppSum;
14407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
14507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
14607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int oppSum(const SkOpAngle* angle) const {
14707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        int lesser = SkMin32(angle->start(), angle->end());
14807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fTs[lesser].fOppSum;
14907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
15007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
15107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int oppValue(int tIndex) const {
15207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fTs[tIndex].fOppValue;
15307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
15407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
15507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int oppValue(const SkOpAngle* angle) const {
15607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        int lesser = SkMin32(angle->start(), angle->end());
15707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fTs[lesser].fOppValue;
15807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
15907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_VALIDATE
1614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool oppXor() const {
1624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return fOppXor;
163cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    }
1644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
165cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com
1664fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    SkPoint ptAtT(double mid) const {
1674fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com        return (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid);
1684fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com    }
1694fdbb229649caf74e5c1b55a1823926df903af34caryclark@google.com
17007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const SkPoint* pts() const {
17107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fPts;
17207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
17307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
17407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void reset() {
17507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        init(NULL, (SkPath::Verb) -1, false, false);
17607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
17707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fTs.reset();
17807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
17907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1805e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark    bool reversePoints(const SkPoint& p1, const SkPoint& p2) const;
1815e27e0eb1d1d4c7674e221d3ba3314500ea0b97acaryclark
18207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void setOppXor(bool isOppXor) {
18307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fOppXor = isOppXor;
18407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
18507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
18607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void setUpWinding(int index, int endIndex, int* maxWinding, int* sumWinding) {
18707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        int deltaSum = spanSign(index, endIndex);
18807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *maxWinding = *sumWinding;
18907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        *sumWinding -= deltaSum;
19007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
19107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
19207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const SkOpSpan& span(int tIndex) const {
19307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fTs[tIndex];
19407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
19507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    const SkOpAngle* spanToAngle(int tStart, int tEnd) const {
1974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        SkASSERT(tStart != tEnd);
1984431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        const SkOpSpan& span = fTs[tStart];
199dac1d17027dcaa5596885a9f333979418b35001ccaryclark        return tStart < tEnd ? span.fToAngle : span.fFromAngle;
2004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
2014431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
2024431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    // FIXME: create some sort of macro or template that avoids casting
2034431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkOpAngle* spanToAngle(int tStart, int tEnd) {
2044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        const SkOpAngle* cAngle = (const_cast<const SkOpSegment*>(this))->spanToAngle(tStart, tEnd);
2054431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return const_cast<SkOpAngle*>(cAngle);
2064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
2074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
20807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int spanSign(const SkOpAngle* angle) const {
20907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkASSERT(angle->segment() == this);
21007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return spanSign(angle->start(), angle->end());
21107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
21207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
21307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int spanSign(int startIndex, int endIndex) const {
21407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        int result = startIndex < endIndex ? -fTs[startIndex].fWindValue : fTs[endIndex].fWindValue;
21507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WIND_BUMP
21607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("%s spanSign=%d\n", __FUNCTION__, result);
21707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
21807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return result;
21907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
22007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
22107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double t(int tIndex) const {
22207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fTs[tIndex].fT;
22307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
22407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
22507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double tAtMid(int start, int end, double mid) const {
22607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fTs[start].fT * (1 - mid) + fTs[end].fT * mid;
22707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
22807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
22907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void updatePts(const SkPoint pts[]) {
23007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fPts = pts;
23107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
2323284017a60ea4fc3dc5b95838ba0c301ee1e4e8dskia.committer@gmail.com
23307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkPath::Verb verb() const {
23407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fVerb;
23507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
23607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
23707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int windSum(int tIndex) const {
23807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fTs[tIndex].fWindSum;
23907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
24007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
24107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int windValue(int tIndex) const {
24207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fTs[tIndex].fWindValue;
24307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
24407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
245927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com#if defined(SK_DEBUG) || DEBUG_WINDING
24607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkScalar xAtT(int index) const {
24707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return xAtT(&fTs[index]);
24807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
249927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com#endif
25007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_VALIDATE
2524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool _xor() const {  // FIXME: used only by SkOpAngle::debugValidateLoop()
2534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return fXor;
2544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
2554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
2564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
25707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const SkPoint& xyAtT(const SkOpSpan* span) const {
25807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return span->fPt;
25907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
26007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
26107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const SkPoint& xyAtT(int index) const {
26207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return xyAtT(&fTs[index]);
26307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
2643284017a60ea4fc3dc5b95838ba0c301ee1e4e8dskia.committer@gmail.com
265927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com#if defined(SK_DEBUG) || DEBUG_WINDING
26607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkScalar yAtT(int index) const {
26707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return yAtT(&fTs[index]);
26807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
269927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com#endif
27007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2714431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    const SkOpAngle* activeAngle(int index, int* start, int* end, bool* done,
2724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                                 bool* sortable) const;
2738cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    SkPoint activeLeftTop(int* firstT) const;
27407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathOp op);
27507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool activeWinding(int index, int endIndex);
27607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void addCubic(const SkPoint pts[4], bool operand, bool evenOdd);
27707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void addCurveTo(int start, int end, SkPathWriter* path, bool active) const;
2784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void addEndSpan(int endIndex);
27907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void addLine(const SkPoint pts[2], bool operand, bool evenOdd);
28007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void addOtherT(int index, double otherT, int otherIndex);
28107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void addQuad(const SkPoint pts[3], bool operand, bool evenOdd);
2824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void addSimpleAngle(int endIndex);
2834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int addSelfT(const SkPoint& pt, double newT);
2844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void addStartSpan(int endIndex);
285866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org    int addT(SkOpSegment* other, const SkPoint& pt, double newT);
286570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    void addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
287630240d18805faf81d8e75172496ad165c2226b2caryclark    bool addTCoincident(const SkPoint& startPt, const SkPoint& endPt, double endT,
2884431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                        SkOpSegment* other);
2894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    const SkOpSpan* addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind,
2904431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                             const SkPoint& pt);
291dac1d17027dcaa5596885a9f333979418b35001ccaryclark    const SkOpSpan* addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind,
292dac1d17027dcaa5596885a9f333979418b35001ccaryclark                             const SkPoint& pt, const SkPoint& oPt);
293dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void alignMultiples(SkTDArray<AlignedSpan>* aligned);
2944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool alignSpan(int index, double thisT, const SkPoint& thisPt);
2954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void alignSpanState(int start, int end);
29607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool betweenTs(int lesser, double testT, int greater) const;
297dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void blindCancel(const SkCoincidence& coincidence, SkOpSegment* other);
298dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void blindCoincident(const SkCoincidence& coincidence, SkOpSegment* other);
2994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool calcAngles();
300dac1d17027dcaa5596885a9f333979418b35001ccaryclark    double calcMissingTEnd(const SkOpSegment* ref, double loEnd, double min, double max,
301dac1d17027dcaa5596885a9f333979418b35001ccaryclark                           double hiEnd, const SkOpSegment* other, int thisEnd);
302dac1d17027dcaa5596885a9f333979418b35001ccaryclark    double calcMissingTStart(const SkOpSegment* ref, double loEnd, double min, double max,
303dac1d17027dcaa5596885a9f333979418b35001ccaryclark                             double hiEnd, const SkOpSegment* other, int thisEnd);
3044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void checkDuplicates();
305fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com    void checkEnds();
3064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void checkMultiples();
3074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void checkSmall();
308570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool checkSmall(int index) const;
309570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    void checkTiny();
3104431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeType);
3118cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    bool containsPt(const SkPoint& , int index, int endIndex) const;
31207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hitT, bool* hitSomething,
31307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                     double mid, bool opp, bool current) const;
314a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com    bool findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* other, int oStart, int oEnd,
315a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com                             int step, SkPoint* startPt, SkPoint* endPt, double* endT) const;
31607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* nextEnd,
3174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                            bool* unsortable, SkPathOp op, int xorMiMask, int xorSuMask);
31807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* findNextWinding(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* nextEnd,
31907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                                 bool* unsortable);
32007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* findNextXor(int* nextStart, int* nextEnd, bool* unsortable);
3214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int findExactT(double t, const SkOpSegment* ) const;
322dac1d17027dcaa5596885a9f333979418b35001ccaryclark    int findOtherT(double t, const SkOpSegment* ) const;
3238cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    int findT(double t, const SkPoint& , const SkOpSegment* ) const;
3248cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    SkOpSegment* findTop(int* tIndex, int* endIndex, bool* unsortable, bool firstPass);
32507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void fixOtherTIndex();
3264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void initWinding(int start, int end, SkOpAngle::IncludeType angleIncludeType);
32707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void initWinding(int start, int end, double tHit, int winding, SkScalar hitDx, int oppWind,
328570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com                     SkScalar hitOppDx);
3297eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com    bool isMissing(double startT, const SkPoint& pt) const;
330cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    bool isTiny(const SkOpAngle* angle) const;
3318cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    bool joinCoincidence(SkOpSegment* other, double otherT, const SkPoint& otherPt, int step,
3328cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org                         bool cancel);
33307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSpan* markAndChaseDoneBinary(int index, int endIndex);
33407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSpan* markAndChaseDoneUnary(int index, int endIndex);
33507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding);
33607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSpan* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int oppSumWinding,
337866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org                        const SkOpAngle* angle);
33807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void markDone(int index, int winding);
33907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void markDoneBinary(int index);
34007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void markDoneUnary(int index);
34107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool nextCandidate(int* start, int* end) const;
34207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int nextSpan(int from, int step) const;
343dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void pinT(const SkPoint& pt, double* t);
34407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void setUpWindings(int index, int endIndex, int* sumMiWinding, int* sumSuWinding,
34507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWinding);
3464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void sortAngles();
347cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    bool subDivide(int start, int end, SkPoint edge[4]) const;
348cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    bool subDivide(int start, int end, SkDCubic* result) const;
34907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void undoneSpan(int* start, int* end);
35007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int updateOppWindingReverse(const SkOpAngle* angle) const;
35107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int updateWindingReverse(const SkOpAngle* angle) const;
35207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    static bool UseInnerWinding(int outerWinding, int innerWinding);
3534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    static bool UseInnerWindingReverse(int outerWinding, int innerWinding);
35407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx) const;
35507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int windSum(const SkOpAngle* angle) const;
3564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org// available for testing only
3574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if defined(SK_DEBUG) || !FORCE_RELEASE
35807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int debugID() const {
35907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fID;
36007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
3614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#else
3624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int debugID() const {
3634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return -1;
3644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
36507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
366a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
36707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void debugShowActiveSpans() const;
36807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
36907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_CONCIDENT
3707eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com    void debugShowTs(const char* prefix) const;
37107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
37207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_SHOW_WINDING
37307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int debugShowWindingValues(int slotCount, int ofInterest) const;
37407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
3758cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    const SkTDArray<SkOpSpan>& debugSpans() const;
3764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void debugValidate() const;
3774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    // available to testing only
378dac1d17027dcaa5596885a9f333979418b35001ccaryclark    const SkOpAngle* debugLastAngle() const;
3794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void dumpAngles() const;
3804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void dumpContour(int firstID, int lastID) const;
3814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void dumpPts() const;
3824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void dumpSpans() const;
38307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
38407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comprivate:
385570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    struct MissingSpan  {
386570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        double fT;
387570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        double fEndT;
388570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        SkOpSegment* fSegment;
389570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        SkOpSegment* fOther;
390570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        double fOtherT;
391570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        SkPoint fPt;
392570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    };
393570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
3944431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    const SkOpAngle* activeAngleInner(int index, int* start, int* end, bool* done,
3954431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                                      bool* sortable) const;
3964431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    const SkOpAngle* activeAngleOther(int index, int* start, int* end, bool* done,
3974431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                                      bool* sortable) const;
398570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathOp op,
3994431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                  int* sumMiWinding, int* sumSuWinding);
4004431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool activeWinding(int index, int endIndex, int* sumWinding);
401570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    void addCancelOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
402570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    void addCoinOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* other);
403dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkOpAngle* addSingletonAngleDown(SkOpSegment** otherPtr, SkOpAngle** );
404dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkOpAngle* addSingletonAngleUp(SkOpSegment** otherPtr, SkOpAngle** );
405dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkOpAngle* addSingletonAngles(int step);
406dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void alignSpan(const SkPoint& newPt, double newT, const SkOpSegment* other, double otherT,
407dac1d17027dcaa5596885a9f333979418b35001ccaryclark                   const SkOpSegment* other2, SkOpSpan* oSpan, SkTDArray<AlignedSpan>* );
408570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const;
409dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void bumpCoincidentBlind(bool binary, int index, int last);
410570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    void bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* index,
411570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com                           SkTArray<SkPoint, true>* outsideTs);
412dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void bumpCoincidentOBlind(int index, int last);
413570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    void bumpCoincidentOther(const SkOpSpan& oTest, int* index,
414570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com                           SkTArray<SkPoint, true>* outsideTs);
41507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool bumpSpan(SkOpSpan* span, int windDelta, int oppDelta);
4164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool calcLoopSpanCount(const SkOpSpan& thisSpan, int* smallCounts);
417dac1d17027dcaa5596885a9f333979418b35001ccaryclark    bool checkForSmall(const SkOpSpan* span, const SkPoint& pt, double newT,
418dac1d17027dcaa5596885a9f333979418b35001ccaryclark                       int* less, int* more) const;
4194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void checkLinks(const SkOpSpan* ,
4204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                    SkTArray<MissingSpan, true>* missingSpans) const;
4214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    static void CheckOneLink(const SkOpSpan* test, const SkOpSpan* oSpan,
4224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                             const SkOpSpan* oFirst, const SkOpSpan* oLast,
4234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                             const SkOpSpan** missingPtr,
4244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                             SkTArray<MissingSpan, true>* missingSpans);
4254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int checkSetAngle(int tIndex) const;
4264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void checkSmallCoincidence(const SkOpSpan& span, SkTArray<MissingSpan, true>* );
427dac1d17027dcaa5596885a9f333979418b35001ccaryclark    bool coincidentSmall(const SkPoint& pt, double t, const SkOpSegment* other) const;
428e4097e3a0b10bb0047a45b6949ca01826f0807a7caryclark    bool clockwise(int tStart, int tEnd, bool* swap) const;
429570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    static void ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
430570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com                              SkOpAngle::IncludeType );
431570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    static void ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
432570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com                                     SkOpAngle::IncludeType );
433dac1d17027dcaa5596885a9f333979418b35001ccaryclark    bool containsT(double t, const SkOpSegment* other, double otherT) const;
434570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool decrementSpan(SkOpSpan* span);
4354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int findEndSpan(int endIndex) const;
4364431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int findStartSpan(int startIndex) const;
4374431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int firstActive(int tIndex) const;
4384431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    const SkOpSpan& firstSpan(const SkOpSpan& thisSpan) const;
43907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd);
440dac1d17027dcaa5596885a9f333979418b35001ccaryclark    bool inCoincidentSpan(double t, const SkOpSegment* other) const;
4414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPtr) const;
442dac1d17027dcaa5596885a9f333979418b35001ccaryclark#if OLD_CHASE
443570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool isSimple(int end) const;
444dac1d17027dcaa5596885a9f333979418b35001ccaryclark#else
445dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkOpSegment* isSimple(int* end, int* step);
446dac1d17027dcaa5596885a9f333979418b35001ccaryclark#endif
447570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool isTiny(int index) const;
4484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    const SkOpSpan& lastSpan(const SkOpSpan& thisSpan) const;
44907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void matchWindingValue(int tIndex, double t, bool borrowWind);
45007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSpan* markAndChaseDone(int index, int endIndex, int winding);
45107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSpan* markAndChaseDoneBinary(const SkOpAngle* angle, int winding, int oppWinding);
4524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding);
4534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding);
45407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding, int oppWinding);
455866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org    SkOpSpan* markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle);
45607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void markDoneBinary(int index, int winding, int oppWinding);
45707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSpan* markAndChaseDoneUnary(const SkOpAngle* angle, int winding);
45807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void markOneDone(const char* funName, int tIndex, int winding);
45907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void markOneDoneBinary(const char* funName, int tIndex);
46007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void markOneDoneBinary(const char* funName, int tIndex, int winding, int oppWinding);
46107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void markOneDoneUnary(const char* funName, int tIndex);
462570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding);
463570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding, int oppWinding);
464570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    void markWinding(int index, int winding);
465570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    void markWinding(int index, int winding, int oppWinding);
46607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool monotonicInY(int tStart, int tEnd) const;
4674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
468dac1d17027dcaa5596885a9f333979418b35001ccaryclark    bool multipleEnds() const { return fTs[count() - 2].fT == 1; }
469dac1d17027dcaa5596885a9f333979418b35001ccaryclark    bool multipleStarts() const { return fTs[1].fT == 0; }
4704431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
471dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkOpSegment* nextChase(int* index, int* step, int* min, SkOpSpan** last);
472570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    int nextExactSpan(int from, int step) const;
47307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool serpentine(int tStart, int tEnd) const;
474dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void setCoincidentRange(const SkPoint& startPt, const SkPoint& endPt,  SkOpSegment* other);
475dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void setFromAngle(int endIndex, SkOpAngle* );
476dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void setToAngle(int endIndex, SkOpAngle* );
477570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    void setUpWindings(int index, int endIndex, int* sumMiWinding,
478570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            int* maxWinding, int* sumWinding);
47907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void subDivideBounds(int start, int end, SkPathOpsBounds* bounds) const;
480570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    static void TrackOutsidePair(SkTArray<SkPoint, true>* outsideTs, const SkPoint& endPt,
481570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            const SkPoint& startPt);
482570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    static void TrackOutside(SkTArray<SkPoint, true>* outsideTs, const SkPoint& startPt);
48307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int updateOppWinding(int index, int endIndex) const;
48407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int updateOppWinding(const SkOpAngle* angle) const;
48507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int updateWinding(int index, int endIndex) const;
48607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int updateWinding(const SkOpAngle* angle) const;
487570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    int updateWindingReverse(int index, int endIndex) const;
48807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSpan* verifyOneWinding(const char* funName, int tIndex);
48907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSpan* verifyOneWindingU(const char* funName, int tIndex);
490927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com
491927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com    SkScalar xAtT(const SkOpSpan* span) const {
492927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com        return xyAtT(span).fX;
493927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com    }
494927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com
495927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com    SkScalar yAtT(const SkOpSpan* span) const {
496927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com        return xyAtT(span).fY;
497927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com    }
498927b7028d44c46e9cbc18368f16ec2262d59d94dcaryclark@google.com
49907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void zeroSpan(SkOpSpan* span);
50007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
50107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_SWAP_TOP
50207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool controlsContainedByEnds(int tStart, int tEnd) const;
50307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
5044431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void debugAddAngle(int start, int end);
50507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_CONCIDENT
5064431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void debugAddTPair(double t, const SkOpSegment& other, double otherT) const;
5074431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#endif
5084431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if DEBUG_ANGLE
5094431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void debugCheckPointsEqualish(int tStart, int tEnd) const;
51007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
5118cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#if DEBUG_SWAP_TOP
5128cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org    int debugInflections(int index, int endIndex) const;
5138cb1daaa1e4343eb60a7c4f21c12e33de30dad64commit-bot@chromium.org#endif
51407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
51507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding);
51607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding, int oppWinding);
51707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
51807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_WINDING
51907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    static char as_digit(int value) {
52007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return value < 0 ? '?' : value <= 9 ? '0' + value : '+';
52107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
52207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
5234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    // available to testing only
5244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void debugConstruct();
5254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void debugConstructCubic(SkPoint shortQuad[4]);
5264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void debugConstructLine(SkPoint shortQuad[2]);
5274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void debugConstructQuad(SkPoint shortQuad[3]);
5284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void debugReset();
529570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    void dumpDPts() const;
5304431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void dumpSpan(int index) const;
53107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
53207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const SkPoint* fPts;
53307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkPathOpsBounds fBounds;
534d892bd8ba676d34d4ce4a73ac7aad88e102fad70caryclark@google.com    // FIXME: can't convert to SkTArray because it uses insert
5354431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    SkTDArray<SkOpSpan> fTs;  // 2+ (always includes t=0 t=1) -- at least (number of spans) + 1
536dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkOpAngleSet fAngles;  // empty or 2+ -- (number of non-zero spans) * 2
53707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized value
53807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int fDoneSpans;  // quick check that segment is finished
53907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // OPTIMIZATION: force the following to be byte-sized
54007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkPath::Verb fVerb;
5414431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool fLoop;   // set if cubic intersects itself
542dac1d17027dcaa5596885a9f333979418b35001ccaryclark    bool fMultiples;  // set if curve intersects multiple other curves at one interior point
54307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool fOperand;
54407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool fXor;  // set if original contour had even-odd fill
54507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool fOppXor;  // set if opposite operand had even-odd fill
5464431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool fSmall;  // set if some span is small
5474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool fTiny;  // set if some span is tiny
5484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if defined(SK_DEBUG) || !FORCE_RELEASE
54907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int fID;
55007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
5514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
5524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    friend class PathOpsSegmentTester;
55307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
55407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
55507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
556