1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7#ifndef Intersections_DEFINE
8#define Intersections_DEFINE
9
10class Intersections {
11public:
12    Intersections()
13        : fFlip(0)
14#if SK_DEBUG
15        , fDepth(0)
16#endif
17        , fSwap(0)
18    {
19#if SK_DEBUG
20        bzero(fPt, sizeof(fPt));
21        bzero(fT, sizeof(fT));
22        bzero(fIsCoincident, sizeof(fIsCoincident));
23#endif
24        reset();
25    }
26
27    int coincidentUsed() const {
28        if (!fIsCoincident[0]) {
29            SkASSERT(!fIsCoincident[0]);
30            return 0;
31        }
32        int count = 0;
33        SkDEBUGCODE(int count2 = 0;)
34        for (int index = 0; index < fUsed; ++index) {
35            if (fIsCoincident[0] & (1 << index)) {
36                ++count;
37            }
38    #if SK_DEBUG
39            if (fIsCoincident[1] & (1 << index)) {
40                ++count2;
41            }
42    #endif
43        }
44        SkASSERT(count == count2);
45        return count;
46    }
47
48    void offset(int base, double start, double end) {
49        for (int index = base; index < fUsed; ++index) {
50            double val = fT[fSwap][index];
51            val *= end - start;
52            val += start;
53            fT[fSwap][index] = val;
54        }
55    }
56
57    // FIXME : does not respect swap
58    int insert(double one, double two, const _Point& pt);
59
60    // start if index == 0 : end if index == 1
61    void insertCoincident(double one, double two, const _Point& pt) {
62        int index = insertSwap(one, two, pt);
63        int bit = 1 << index;
64        fIsCoincident[0] |= bit;
65        fIsCoincident[1] |= bit;
66    }
67
68    void insertCoincidentPair(double s1, double e1, double s2, double e2,
69            const _Point& startPt, const _Point& endPt);
70
71    int insertSwap(double one, double two, const _Point& pt) {
72        if (fSwap) {
73            return insert(two, one, pt);
74        } else {
75            return insert(one, two, pt);
76        }
77    }
78
79    bool intersected() const {
80        return fUsed > 0;
81    }
82
83    void removeOne(int index);
84
85    // leaves flip, swap alone
86    void reset() {
87        fUsed = 0;
88        fUnsortable = false;
89    }
90
91    void swap() {
92        fSwap ^= true;
93    }
94
95    void swapPts() {
96        int index;
97        for (index = 0; index < fUsed; ++index) {
98            SkTSwap(fT[0][index], fT[1][index]);
99        }
100    }
101
102    bool swapped() const {
103        return fSwap;
104    }
105
106    bool unsortable() const {
107        return fUnsortable;
108    }
109
110    int used() const {
111        return fUsed;
112    }
113
114    void downDepth() {
115        SkASSERT(--fDepth >= 0);
116    }
117
118    void upDepth() {
119        SkASSERT(++fDepth < 16);
120    }
121
122#if SK_DEBUG
123    int depth() const {
124        return fDepth;
125    }
126#endif
127
128    _Point fPt[9];
129    double fT[2][9];
130    unsigned short fIsCoincident[2]; // bit arrays, one bit set for each coincident T
131    unsigned char fUsed;
132    bool fFlip;
133    bool fUnsortable;
134#if SK_DEBUG
135    int fDepth;
136#endif
137protected:
138    // used by addCoincident to remove ordinary intersections in range
139    void remove(double one, double two, const _Point& startPt, const _Point& endPt);
140private:
141    bool fSwap;
142};
143
144#endif
145