1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2012 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SkIntersections_DEFINE
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define SkIntersections_DEFINE
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathOpsConic.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathOpsCubic.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathOpsLine.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathOpsPoint.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathOpsQuad.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkIntersections {
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkIntersections(SkDEBUGCODE(SkOpGlobalState* globalState = nullptr))
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : fSwap(0)
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDEBUGPARAMS(fDebugGlobalState(globalState))
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fDepth(0)
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    {
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_bzero(fPt, sizeof(fPt));
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_bzero(fPt2, sizeof(fPt2));
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_bzero(fT, sizeof(fT));
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_bzero(fNearlySame, sizeof(fNearlySame));
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_T_SECT_LOOP_COUNT
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_bzero(fDebugLoopCount, sizeof(fDebugLoopCount));
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        reset();
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMax = 0;  // require that the caller set the max
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    class TArray {
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    public:
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        explicit TArray(const double ts[10]) : fTArray(ts) {}
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        double operator[](int n) const {
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return fTArray[n];
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const double* fTArray;
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TArray operator[](int n) const { return TArray(fT[n]); }
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void allowNear(bool nearAllowed) {
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fAllowNear = nearAllowed;
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void clearCoincidence(int index) {
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(index >= 0);
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int bit = 1 << index;
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fIsCoincident[0] &= ~bit;
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fIsCoincident[1] &= ~bit;
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int conicHorizontal(const SkPoint a[3], SkScalar weight, SkScalar left, SkScalar right,
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkScalar y, bool flipped) {
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDConic conic;
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        conic.set(a, weight);
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMax = 2;
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return horizontal(conic, left, right, y, flipped);
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int conicVertical(const SkPoint a[3], SkScalar weight, SkScalar top, SkScalar bottom,
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkScalar x, bool flipped) {
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDConic conic;
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        conic.set(a, weight);
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMax = 2;
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return vertical(conic, top, bottom, x, flipped);
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int conicLine(const SkPoint a[3], SkScalar weight, const SkPoint b[2]) {
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDConic conic;
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        conic.set(a, weight);
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDLine line;
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        line.set(b);
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMax = 3; // 2;  permit small coincident segment + non-coincident intersection
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return intersect(conic, line);
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int cubicHorizontal(const SkPoint a[4], SkScalar left, SkScalar right, SkScalar y,
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        bool flipped) {
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDCubic cubic;
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        cubic.set(a);
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMax = 3;
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return horizontal(cubic, left, right, y, flipped);
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int cubicVertical(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDCubic cubic;
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        cubic.set(a);
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMax = 3;
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return vertical(cubic, top, bottom, x, flipped);
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int cubicLine(const SkPoint a[4], const SkPoint b[2]) {
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDCubic cubic;
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        cubic.set(a);
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDLine line;
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        line.set(b);
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMax = 3;
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return intersect(cubic, line);
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkOpGlobalState* globalState() const { return fDebugGlobalState; }
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool hasT(double t) const {
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(t == 0 || t == 1);
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fUsed > 0 && (t == 0 ? fT[0][0] == 0 : fT[0][fUsed - 1] == 1);
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool hasOppT(double t) const {
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(t == 0 || t == 1);
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fUsed > 0 && (fT[1][0] == t || fT[1][fUsed - 1] == t);
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int insertSwap(double one, double two, const SkDPoint& pt) {
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fSwap) {
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return insert(two, one, pt);
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return insert(one, two, pt);
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool isCoincident(int index) {
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return (fIsCoincident[0] & 1 << index) != 0;
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int lineHorizontal(const SkPoint a[2], SkScalar left, SkScalar right, SkScalar y,
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       bool flipped) {
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDLine line;
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        line.set(a);
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMax = 2;
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return horizontal(line, left, right, y, flipped);
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int lineVertical(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDLine line;
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        line.set(a);
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMax = 2;
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return vertical(line, top, bottom, x, flipped);
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int lineLine(const SkPoint a[2], const SkPoint b[2]) {
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDLine aLine, bLine;
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        aLine.set(a);
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bLine.set(b);
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMax = 2;
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return intersect(aLine, bLine);
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool nearlySame(int index) const {
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(index == 0 || index == 1);
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fNearlySame[index];
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkDPoint& pt(int index) const {
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fPt[index];
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkDPoint& pt2(int index) const {
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fPt2[index];
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int quadHorizontal(const SkPoint a[3], SkScalar left, SkScalar right, SkScalar y,
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       bool flipped) {
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDQuad quad;
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        quad.set(a);
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMax = 2;
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return horizontal(quad, left, right, y, flipped);
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int quadVertical(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDQuad quad;
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        quad.set(a);
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMax = 2;
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return vertical(quad, top, bottom, x, flipped);
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int quadLine(const SkPoint a[3], const SkPoint b[2]) {
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDQuad quad;
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        quad.set(a);
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDLine line;
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        line.set(b);
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return intersect(quad, line);
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // leaves swap, max alone
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void reset() {
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fAllowNear = true;
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fUsed = 0;
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_bzero(fIsCoincident, sizeof(fIsCoincident));
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void set(bool swap, int tIndex, double t) {
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fT[(int) swap][tIndex] = t;
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void setMax(int max) {
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(max <= (int) SK_ARRAY_COUNT(fPt));
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMax = max;
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void swap() {
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fSwap ^= true;
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool swapped() const {
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fSwap;
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int used() const {
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fUsed;
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void downDepth() {
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(--fDepth >= 0);
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool unBumpT(int index) {
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(fUsed == 1);
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fT[0][index] = fT[0][index] * (1 + BUMP_EPSILON * 2) - BUMP_EPSILON;
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!between(0, fT[0][index], 1)) {
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fUsed = 0;
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void upDepth() {
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(++fDepth < 16);
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void alignQuadPts(const SkPoint a[3], const SkPoint b[3]);
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int cleanUpCoincidence();
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int closestTo(double rangeStart, double rangeEnd, const SkDPoint& testPt, double* dist) const;
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void cubicInsert(double one, double two, const SkDPoint& pt, const SkDCubic& c1,
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                     const SkDCubic& c2);
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void flip();
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int horizontal(const SkDLine&, double left, double right, double y, bool flipped);
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int horizontal(const SkDQuad&, double left, double right, double y, bool flipped);
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int horizontal(const SkDQuad&, double left, double right, double y, double tRange[2]);
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int horizontal(const SkDCubic&, double y, double tRange[3]);
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int horizontal(const SkDConic&, double left, double right, double y, bool flipped);
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int horizontal(const SkDCubic&, double left, double right, double y, bool flipped);
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int horizontal(const SkDCubic&, double left, double right, double y, double tRange[3]);
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static double HorizontalIntercept(const SkDLine& line, double y);
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static int HorizontalIntercept(const SkDQuad& quad, SkScalar y, double* roots);
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static int HorizontalIntercept(const SkDConic& conic, SkScalar y, double* roots);
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // FIXME : does not respect swap
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int insert(double one, double two, const SkDPoint& pt);
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void insertNear(double one, double two, const SkDPoint& pt1, const SkDPoint& pt2);
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // start if index == 0 : end if index == 1
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int insertCoincident(double one, double two, const SkDPoint& pt);
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int intersect(const SkDLine&, const SkDLine&);
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int intersect(const SkDQuad&, const SkDLine&);
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int intersect(const SkDQuad&, const SkDQuad&);
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int intersect(const SkDConic&, const SkDLine&);
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int intersect(const SkDConic&, const SkDQuad&);
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int intersect(const SkDConic&, const SkDConic&);
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int intersect(const SkDCubic&, const SkDLine&);
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int intersect(const SkDCubic&, const SkDQuad&);
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int intersect(const SkDCubic&, const SkDConic&);
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int intersect(const SkDCubic&, const SkDCubic&);
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int intersectRay(const SkDLine&, const SkDLine&);
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int intersectRay(const SkDQuad&, const SkDLine&);
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int intersectRay(const SkDConic&, const SkDLine&);
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int intersectRay(const SkDCubic&, const SkDLine&);
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void merge(const SkIntersections& , int , const SkIntersections& , int );
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int mostOutside(double rangeStart, double rangeEnd, const SkDPoint& origin) const;
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void removeOne(int index);
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void setCoincident(int index);
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int vertical(const SkDLine&, double top, double bottom, double x, bool flipped);
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int vertical(const SkDQuad&, double top, double bottom, double x, bool flipped);
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int vertical(const SkDConic&, double top, double bottom, double x, bool flipped);
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int vertical(const SkDCubic&, double top, double bottom, double x, bool flipped);
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static double VerticalIntercept(const SkDLine& line, double x);
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static int VerticalIntercept(const SkDQuad& quad, SkScalar x, double* roots);
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static int VerticalIntercept(const SkDConic& conic, SkScalar x, double* roots);
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int depth() const {
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fDepth;
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#else
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return 0;
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum DebugLoop {
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kIterations_DebugLoop,
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kCoinCheck_DebugLoop,
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kComputePerp_DebugLoop,
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void debugBumpLoopCount(DebugLoop );
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int debugCoincidentUsed() const;
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int debugLoopCount(DebugLoop ) const;
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void debugResetLoopCount();
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void dump() const;  // implemented for testing only
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool cubicCheckCoincidence(const SkDCubic& c1, const SkDCubic& c2);
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool cubicExactEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2);
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void cubicNearEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2, const SkDRect& );
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void cleanUpParallelLines(bool parallel);
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void computePoints(const SkDLine& line, int used);
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDPoint fPt[13];  // FIXME: since scans store points as SkPoint, this should also
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDPoint fPt2[2];  // used by nearly same to store alternate intersection point
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    double fT[2][13];
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint16_t fIsCoincident[2];  // bit set for each curve's coincident T
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fNearlySame[2];  // true if end points nearly match
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    unsigned char fUsed;
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    unsigned char fMax;
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fAllowNear;
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fSwap;
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkOpGlobalState* fDebugGlobalState;
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int fDepth;
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if DEBUG_T_SECT_LOOP_COUNT
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int fDebugLoopCount[3];
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
330