SkOpContour.h revision dac1d17027dcaa5596885a9f333979418b35001c
107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/*
207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2013 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 SkOpContour_DEFINED
807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#define SkOpContour_DEFINED
907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkOpSegment.h"
1107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkTArray.h"
1207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
130bcb8ca8a8fc04a4a9c69013ccc46645d2f2ae77commit-bot@chromium.org#if defined(SK_DEBUG) || !FORCE_RELEASE
140bcb8ca8a8fc04a4a9c69013ccc46645d2f2ae77commit-bot@chromium.org#include "SkThread.h"
150bcb8ca8a8fc04a4a9c69013ccc46645d2f2ae77commit-bot@chromium.org#endif
160bcb8ca8a8fc04a4a9c69013ccc46645d2f2ae77commit-bot@chromium.org
1707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass SkIntersections;
1807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass SkOpContour;
1907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass SkPathWriter;
2007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comstruct SkCoincidence {
22570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    SkOpContour* fOther;
2307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int fSegments[2];
2407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double fTs[2][2];
25dac1d17027dcaa5596885a9f333979418b35001ccaryclark    SkPoint fPts[2][2];
26dac1d17027dcaa5596885a9f333979418b35001ccaryclark    int fNearly[2];
2707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
2807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comclass SkOpContour {
3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.compublic:
3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpContour() {
3207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        reset();
334431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if defined(SK_DEBUG) || !FORCE_RELEASE
340bcb8ca8a8fc04a4a9c69013ccc46645d2f2ae77commit-bot@chromium.org        fID = sk_atomic_inc(&SkPathOpsDebug::gContourID);
3507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
3607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
3707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool operator<(const SkOpContour& rh) const {
3907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fBounds.fTop == rh.fBounds.fTop
4007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                ? fBounds.fLeft < rh.fBounds.fLeft
4107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                : fBounds.fTop < rh.fBounds.fTop;
4207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
4307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
447eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com    bool addCoincident(int index, SkOpContour* other, int otherIndex,
4507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                       const SkIntersections& ts, bool swap);
4607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void addCoincidentPoints();
4707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
4807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void addCross(const SkOpContour* crosser) {
4907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#ifdef DEBUG_CROSS
5007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        for (int index = 0; index < fCrosses.count(); ++index) {
5107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            SkASSERT(fCrosses[index] != crosser);
5207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
5307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
54d892bd8ba676d34d4ce4a73ac7aad88e102fad70caryclark@google.com        fCrosses.push_back(crosser);
5507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
5607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
5707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void addCubic(const SkPoint pts[4]) {
5807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fSegments.push_back().addCubic(pts, fOperand, fXor);
5907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fContainsCurves = fContainsCubics = true;
6007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
6107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
6207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int addLine(const SkPoint pts[2]) {
6307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fSegments.push_back().addLine(pts, fOperand, fXor);
6407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fSegments.count();
6507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
6607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
6707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void addOtherT(int segIndex, int tIndex, double otherT, int otherIndex) {
6807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fSegments[segIndex].addOtherT(tIndex, otherT, otherIndex);
6907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
7007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
717eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com    bool addPartialCoincident(int index, SkOpContour* other, int otherIndex,
72570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com                       const SkIntersections& ts, int ptIndex, bool swap);
73570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
7407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int addQuad(const SkPoint pts[3]) {
7507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fSegments.push_back().addQuad(pts, fOperand, fXor);
7607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fContainsCurves = true;
7707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fSegments.count();
7807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
7907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
80866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org    int addT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt, double newT) {
8107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        setContainsIntercepts();
82866f4e34a943c115ac372c22123a1520aa5f9b06commit-bot@chromium.org        return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT);
8307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
8407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int addSelfT(int segIndex, const SkPoint& pt, double newT) {
8607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        setContainsIntercepts();
874431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return fSegments[segIndex].addSelfT(pt, newT);
8807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
8907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
90dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void align(const SkOpSegment::AlignedSpan& aligned, bool swap, SkCoincidence* coincidence);
91dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void alignCoincidence(const SkOpSegment::AlignedSpan& aligned,
92dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkTArray<SkCoincidence, true>* coincidences);
93dac1d17027dcaa5596885a9f333979418b35001ccaryclark
94dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void alignCoincidence(const SkOpSegment::AlignedSpan& aligned) {
95dac1d17027dcaa5596885a9f333979418b35001ccaryclark        alignCoincidence(aligned, &fCoincidences);
96dac1d17027dcaa5596885a9f333979418b35001ccaryclark        alignCoincidence(aligned, &fPartialCoincidences);
97dac1d17027dcaa5596885a9f333979418b35001ccaryclark    }
98dac1d17027dcaa5596885a9f333979418b35001ccaryclark
99dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void alignMultiples(SkTDArray<SkOpSegment::AlignedSpan>* aligned) {
100dac1d17027dcaa5596885a9f333979418b35001ccaryclark        int segmentCount = fSegments.count();
101dac1d17027dcaa5596885a9f333979418b35001ccaryclark        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
102dac1d17027dcaa5596885a9f333979418b35001ccaryclark            SkOpSegment& segment = fSegments[sIndex];
103dac1d17027dcaa5596885a9f333979418b35001ccaryclark            if (segment.hasMultiples()) {
104dac1d17027dcaa5596885a9f333979418b35001ccaryclark                segment.alignMultiples(aligned);
105dac1d17027dcaa5596885a9f333979418b35001ccaryclark            }
106dac1d17027dcaa5596885a9f333979418b35001ccaryclark        }
107dac1d17027dcaa5596885a9f333979418b35001ccaryclark    }
108dac1d17027dcaa5596885a9f333979418b35001ccaryclark
109dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void alignTPt(int segmentIndex, const SkOpContour* other, int otherIndex,
110dac1d17027dcaa5596885a9f333979418b35001ccaryclark                  bool swap, int tIndex, SkIntersections* ts, SkPoint* point) const;
111dac1d17027dcaa5596885a9f333979418b35001ccaryclark
11207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const SkPathOpsBounds& bounds() const {
11307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fBounds;
11407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
11507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool calcAngles();
11707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void calcCoincidentWinding();
118570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    void calcPartialCoincidentWinding();
11907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void checkDuplicates() {
1214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        int segmentCount = fSegments.count();
1224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
1234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            SkOpSegment& segment = fSegments[sIndex];
1244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            if (segment.count() > 2) {
1254431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                segment.checkDuplicates();
1264431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
1274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
1284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
1294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
130fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com    void checkEnds() {
131fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com        if (!fContainsCurves) {
132fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com            return;
133fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com        }
134fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com        int segmentCount = fSegments.count();
135fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
136fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com            SkOpSegment* segment = &fSegments[sIndex];
137fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com            if (segment->verb() == SkPath::kLine_Verb) {
138fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com                continue;
139fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com            }
1407eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com            if (segment->done()) {
1417eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com                continue;   // likely coincident, nothing to do
1427eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com            }
143570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            segment->checkEnds();
144570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
145570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
146570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
1474431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void checkMultiples() {
1484431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        int segmentCount = fSegments.count();
1494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
1504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            SkOpSegment& segment = fSegments[sIndex];
1514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            if (segment.count() > 2) {
1524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                segment.checkMultiples();
153dac1d17027dcaa5596885a9f333979418b35001ccaryclark                fMultiples |= segment.hasMultiples();
1544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
1554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
1564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
1574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
1584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void checkSmall() {
1594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        int segmentCount = fSegments.count();
1604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
1614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            SkOpSegment& segment = fSegments[sIndex];
162dac1d17027dcaa5596885a9f333979418b35001ccaryclark            // OPTIMIZATION : skip segments that are done?
1634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            if (segment.hasSmall()) {
1644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                segment.checkSmall();
1654431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
1664431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
1674431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
1684431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
169570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    // if same point has different T values, choose a common T
170570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    void checkTiny() {
171570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        int segmentCount = fSegments.count();
172570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        if (segmentCount <= 2) {
173570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com            return;
174570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        }
175570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
1764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            SkOpSegment& segment = fSegments[sIndex];
1774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            if (segment.hasTiny()) {
1784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org                segment.checkTiny();
1794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            }
180fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com        }
181fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com    }
182fa2aeee27af27f2934ee52a9732148f66481fb03caryclark@google.com
18307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void complete() {
18407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        setBounds();
18507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fContainsIntercepts = false;
18607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
18707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
18807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool containsCubics() const {
18907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fContainsCubics;
19007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
19107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
19207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool crosses(const SkOpContour* crosser) const {
19307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        for (int index = 0; index < fCrosses.count(); ++index) {
19407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            if (fCrosses[index] == crosser) {
19507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com                return true;
19607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            }
19707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
19807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return false;
19907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
20007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
20107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool done() const {
20207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fDone;
20307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
20407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
20507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const SkPoint& end() const {
20607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        const SkOpSegment& segment = fSegments.back();
207277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        return segment.pts()[SkPathOpsVerbToPoints(segment.verb())];
20807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
20907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
21007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void fixOtherTIndex() {
21107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        int segmentCount = fSegments.count();
21207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
21307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            fSegments[sIndex].fixOtherTIndex();
21407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
21507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
21607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
217dac1d17027dcaa5596885a9f333979418b35001ccaryclark    bool hasMultiples() const {
218dac1d17027dcaa5596885a9f333979418b35001ccaryclark        return fMultiples;
219dac1d17027dcaa5596885a9f333979418b35001ccaryclark    }
220dac1d17027dcaa5596885a9f333979418b35001ccaryclark
221a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com    void joinCoincidence() {
222a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com        joinCoincidence(fCoincidences, false);
223a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com        joinCoincidence(fPartialCoincidences, true);
224a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com    }
225a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com
22607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* nonVerticalSegment(int* start, int* end);
2273284017a60ea4fc3dc5b95838ba0c301ee1e4e8dskia.committer@gmail.com
22807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool operand() const {
22907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fOperand;
23007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
23107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
23207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void reset() {
23307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fSegments.reset();
23407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
235dac1d17027dcaa5596885a9f333979418b35001ccaryclark        fContainsCurves = fContainsCubics = fContainsIntercepts = fDone = fMultiples = false;
23607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
23707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
238dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void resolveNearCoincidence();
239dac1d17027dcaa5596885a9f333979418b35001ccaryclark
24007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkTArray<SkOpSegment>& segments() {
24107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fSegments;
24207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
24307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
24407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void setContainsIntercepts() {
24507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fContainsIntercepts = true;
24607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
24707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
24807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void setOperand(bool isOp) {
24907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fOperand = isOp;
25007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
25107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
25207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void setOppXor(bool isOppXor) {
25307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fOppXor = isOppXor;
25407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        int segmentCount = fSegments.count();
25507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        for (int test = 0; test < segmentCount; ++test) {
25607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            fSegments[test].setOppXor(isOppXor);
25707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
25807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
25907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
26007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void setXor(bool isXor) {
26107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fXor = isXor;
26207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
26307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2644431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void sortAngles();
26507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void sortSegments();
2663284017a60ea4fc3dc5b95838ba0c301ee1e4e8dskia.committer@gmail.com
26707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const SkPoint& start() const {
26807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fSegments.front().pts()[0];
26907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
2703284017a60ea4fc3dc5b95838ba0c301ee1e4e8dskia.committer@gmail.com
27107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void toPath(SkPathWriter* path) const;
2723284017a60ea4fc3dc5b95838ba0c301ee1e4e8dskia.committer@gmail.com
27307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void toPartialBackward(SkPathWriter* path) const {
27407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        int segmentCount = fSegments.count();
27507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        for (int test = segmentCount - 1; test >= 0; --test) {
27607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            fSegments[test].addCurveTo(1, 0, path, true);
27707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
27807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
27907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
28007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void toPartialForward(SkPathWriter* path) const {
28107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        int segmentCount = fSegments.count();
28207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        for (int test = 0; test < segmentCount; ++test) {
28307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            fSegments[test].addCurveTo(0, 1, path, true);
28407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
28507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
28607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
28707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY, SkOpSegment** topStart);
28807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkOpSegment* undoneSegment(int* start, int* end);
28907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
29007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int updateSegment(int index, const SkPoint* pts) {
29107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkOpSegment& segment = fSegments[index];
29207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        segment.updatePts(pts);
293277c3f87656c44e0a651ed0dd56efa16c0ab07b4reed@google.com        return SkPathOpsVerbToPoints(segment.verb()) + 1;
29407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
29507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
29607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_TEST
29707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkTArray<SkOpSegment>& debugSegments() {
29807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fSegments;
29907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
30007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
30107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
302a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
30307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void debugShowActiveSpans() {
30407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        for (int index = 0; index < fSegments.count(); ++index) {
30507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            fSegments[index].debugShowActiveSpans();
30607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
30707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
30807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
30907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
31007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_SHOW_WINDING
31107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int debugShowWindingValues(int totalSegments, int ofInterest);
312d892bd8ba676d34d4ce4a73ac7aad88e102fad70caryclark@google.com    static void debugShowWindingValues(const SkTArray<SkOpContour*, true>& contourList);
31307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
31407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3154431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    // available to test routines only
3164431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void dump() const;
3174431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void dumpAngles() const;
318dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void dumpCoincidence(const SkCoincidence& ) const;
319dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void dumpCoincidences() const;
320dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void dumpPt(int ) const;
3214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void dumpPts() const;
322dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void dumpSpan(int ) const;
3234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void dumpSpans() const;
3244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
32507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comprivate:
326dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void alignPt(int index, SkPoint* point, int zeroPt) const;
327dac1d17027dcaa5596885a9f333979418b35001ccaryclark    int alignT(bool swap, int tIndex, SkIntersections* ts) const;
328a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com    void calcCommonCoincidentWinding(const SkCoincidence& );
329dac1d17027dcaa5596885a9f333979418b35001ccaryclark    void checkCoincidentPair(const SkCoincidence& oneCoin, int oneIdx,
330dac1d17027dcaa5596885a9f333979418b35001ccaryclark                             const SkCoincidence& twoCoin, int twoIdx, bool partial);
331a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com    void joinCoincidence(const SkTArray<SkCoincidence, true>& , bool partial);
33207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void setBounds();
33307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
33407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkTArray<SkOpSegment> fSegments;
335d892bd8ba676d34d4ce4a73ac7aad88e102fad70caryclark@google.com    SkTArray<SkOpSegment*, true> fSortedSegments;
33607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int fFirstSorted;
337d892bd8ba676d34d4ce4a73ac7aad88e102fad70caryclark@google.com    SkTArray<SkCoincidence, true> fCoincidences;
338570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    SkTArray<SkCoincidence, true> fPartialCoincidences;
339d892bd8ba676d34d4ce4a73ac7aad88e102fad70caryclark@google.com    SkTArray<const SkOpContour*, true> fCrosses;
34007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkPathOpsBounds fBounds;
34107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool fContainsIntercepts;  // FIXME: is this used by anybody?
34207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool fContainsCubics;
34307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool fContainsCurves;
34407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool fDone;
345dac1d17027dcaa5596885a9f333979418b35001ccaryclark    bool fMultiples;  // set if some segment has multiple identical intersections with other curves
34607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool fOperand;  // true for the second argument to a binary operator
34707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool fXor;
34807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool fOppXor;
3494431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#if defined(SK_DEBUG) || !FORCE_RELEASE
3504431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int debugID() const { return fID; }
35107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int fID;
3524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org#else
3534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int debugID() const { return -1; }
35407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
35507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
35607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
35707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
358