SkIntersections.h revision 7eaa53d8f7e48fd17d02b5e3bd91f90e9c1899ef
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 SkIntersections_DEFINE
8#define SkIntersections_DEFINE
9
10#include "SkPathOpsCubic.h"
11#include "SkPathOpsLine.h"
12#include "SkPathOpsPoint.h"
13#include "SkPathOpsQuad.h"
14
15class SkIntersections {
16public:
17    SkIntersections()
18        : fSwap(0)
19#ifdef SK_DEBUG
20        , fDepth(0)
21#endif
22    {
23        sk_bzero(fPt, sizeof(fPt));
24        sk_bzero(fT, sizeof(fT));
25        sk_bzero(fIsCoincident, sizeof(fIsCoincident));
26        sk_bzero(&fIsNear, sizeof(fIsNear));
27        reset();
28        fMax = 0;  // require that the caller set the max
29    }
30
31    class TArray {
32    public:
33        explicit TArray(const double ts[9]) : fTArray(ts) {}
34        double operator[](int n) const {
35            return fTArray[n];
36        }
37        const double* fTArray;
38    };
39    TArray operator[](int n) const { return TArray(fT[n]); }
40
41    void set(const SkIntersections& i) {
42        memcpy(fPt, i.fPt, sizeof(fPt));
43        memcpy(fT, i.fT, sizeof(fT));
44        memcpy(fIsCoincident, i.fIsCoincident, sizeof(fIsCoincident));
45        memcpy(&fIsNear, &i.fIsNear, sizeof(fIsNear));
46        fUsed = i.fUsed;
47        fMax = i.fMax;
48        fSwap = i.fSwap;
49        SkDEBUGCODE(fDepth = i.fDepth);
50    }
51
52    void allowNear(bool nearAllowed) {
53        fAllowNear = nearAllowed;
54    }
55
56    int cubic(const SkPoint a[4]) {
57        SkDCubic cubic;
58        cubic.set(a);
59        fMax = 1;  // self intersect
60        return intersect(cubic);
61    }
62
63    int cubicCubic(const SkPoint a[4], const SkPoint b[4]) {
64        SkDCubic aCubic;
65        aCubic.set(a);
66        SkDCubic bCubic;
67        bCubic.set(b);
68        fMax = 9;
69        return intersect(aCubic, bCubic);
70    }
71
72    int cubicHorizontal(const SkPoint a[4], SkScalar left, SkScalar right, SkScalar y,
73                        bool flipped) {
74        SkDCubic cubic;
75        cubic.set(a);
76        fMax = 3;
77        return horizontal(cubic, left, right, y, flipped);
78    }
79
80    int cubicVertical(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
81        SkDCubic cubic;
82        cubic.set(a);
83        fMax = 3;
84        return vertical(cubic, top, bottom, x, flipped);
85    }
86
87    int cubicLine(const SkPoint a[4], const SkPoint b[2]) {
88        SkDCubic cubic;
89        cubic.set(a);
90        SkDLine line;
91        line.set(b);
92        fMax = 3;
93        return intersect(cubic, line);
94    }
95
96    int cubicQuad(const SkPoint a[4], const SkPoint b[3]) {
97        SkDCubic cubic;
98        cubic.set(a);
99        SkDQuad quad;
100        quad.set(b);
101        fMax = 6;
102        return intersect(cubic, quad);
103    }
104
105    bool hasT(double t) const {
106        SkASSERT(t == 0 || t == 1);
107        return fUsed > 0 && (t == 0 ? fT[0][0] == 0 : fT[0][fUsed - 1] == 1);
108    }
109
110    int insertSwap(double one, double two, const SkDPoint& pt) {
111        if (fSwap) {
112            return insert(two, one, pt);
113        } else {
114            return insert(one, two, pt);
115        }
116    }
117
118    bool isCoincident(int index) {
119        return (fIsCoincident[0] & 1 << index) != 0;
120    }
121
122    bool isNear(int index) {
123        return (fIsNear & 1 << index) != 0;
124    }
125
126    int lineHorizontal(const SkPoint a[2], SkScalar left, SkScalar right, SkScalar y,
127                       bool flipped) {
128        SkDLine line;
129        line.set(a);
130        fMax = 2;
131        return horizontal(line, left, right, y, flipped);
132    }
133
134    int lineVertical(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
135        SkDLine line;
136        line.set(a);
137        fMax = 2;
138        return vertical(line, top, bottom, x, flipped);
139    }
140
141    int lineLine(const SkPoint a[2], const SkPoint b[2]) {
142        SkDLine aLine, bLine;
143        aLine.set(a);
144        bLine.set(b);
145        fMax = 2;
146        return intersect(aLine, bLine);
147    }
148
149    const SkDPoint& pt(int index) const {
150        return fPt[index];
151    }
152
153    int quadHorizontal(const SkPoint a[3], SkScalar left, SkScalar right, SkScalar y,
154                       bool flipped) {
155        SkDQuad quad;
156        quad.set(a);
157        fMax = 2;
158        return horizontal(quad, left, right, y, flipped);
159    }
160
161    int quadVertical(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
162        SkDQuad quad;
163        quad.set(a);
164        fMax = 2;
165        return vertical(quad, top, bottom, x, flipped);
166    }
167
168    int quadLine(const SkPoint a[3], const SkPoint b[2]) {
169        SkDQuad quad;
170        quad.set(a);
171        SkDLine line;
172        line.set(b);
173        fMax = 2;
174        return intersect(quad, line);
175    }
176
177    int quadQuad(const SkPoint a[3], const SkPoint b[3]) {
178        SkDQuad aQuad;
179        aQuad.set(a);
180        SkDQuad bQuad;
181        bQuad.set(b);
182        fMax = 4;
183        return intersect(aQuad, bQuad);
184    }
185
186    int quadRay(const SkPoint pts[3], const SkDLine& line);
187    void removeOne(int index);
188
189    // leaves flip, swap, max alone
190    void reset() {
191        fAllowNear = true;
192        fUsed = 0;
193    }
194
195    void setMax(int max) {
196        fMax = max;
197    }
198
199    void swap() {
200        fSwap ^= true;
201    }
202
203    void swapPts();
204
205    bool swapped() const {
206        return fSwap;
207    }
208
209    int used() const {
210        return fUsed;
211    }
212
213    void downDepth() {
214        SkASSERT(--fDepth >= 0);
215    }
216
217    void upDepth() {
218        SkASSERT(++fDepth < 16);
219    }
220
221    static double Axial(const SkDQuad& , const SkDPoint& , bool vertical);
222    void cleanUpCoincidence();
223    int coincidentUsed() const;
224    int cubicRay(const SkPoint pts[4], const SkDLine& line);
225    void flip();
226    int horizontal(const SkDLine&, double y);
227    int horizontal(const SkDLine&, double left, double right, double y, bool flipped);
228    int horizontal(const SkDQuad&, double left, double right, double y, bool flipped);
229    int horizontal(const SkDQuad&, double left, double right, double y, double tRange[2]);
230    int horizontal(const SkDCubic&, double y, double tRange[3]);
231    int horizontal(const SkDCubic&, double left, double right, double y, bool flipped);
232    int horizontal(const SkDCubic&, double left, double right, double y, double tRange[3]);
233    // FIXME : does not respect swap
234    int insert(double one, double two, const SkDPoint& pt);
235    void insertNear(double one, double two, const SkDPoint& pt);
236    // start if index == 0 : end if index == 1
237    void insertCoincident(double one, double two, const SkDPoint& pt);
238    int intersect(const SkDLine&, const SkDLine&);
239    int intersect(const SkDQuad&, const SkDLine&);
240    int intersect(const SkDQuad&, const SkDQuad&);
241    int intersect(const SkDCubic&);  // return true if cubic self-intersects
242    int intersect(const SkDCubic&, const SkDLine&);
243    int intersect(const SkDCubic&, const SkDQuad&);
244    int intersect(const SkDCubic&, const SkDCubic&);
245    int intersectRay(const SkDLine&, const SkDLine&);
246    int intersectRay(const SkDQuad&, const SkDLine&);
247    int intersectRay(const SkDCubic&, const SkDLine&);
248    static SkDPoint Line(const SkDLine&, const SkDLine&);
249    void offset(int base, double start, double end);
250    void quickRemoveOne(int index, int replace);
251    static bool Test(const SkDLine& , const SkDLine&);
252    int vertical(const SkDLine&, double x);
253    int vertical(const SkDLine&, double top, double bottom, double x, bool flipped);
254    int vertical(const SkDQuad&, double top, double bottom, double x, bool flipped);
255    int vertical(const SkDCubic&, double top, double bottom, double x, bool flipped);
256    int verticalCubic(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
257    int verticalLine(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
258    int verticalQuad(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
259
260    int depth() const {
261#ifdef SK_DEBUG
262        return fDepth;
263#else
264        return 0;
265#endif
266    }
267
268private:
269    bool cubicCheckCoincidence(const SkDCubic& c1, const SkDCubic& c2);
270    bool cubicExactEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2);
271    void cubicNearEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2, const SkDRect& );
272    void cleanUpParallelLines(bool parallel);
273    void computePoints(const SkDLine& line, int used);
274    // used by addCoincident to remove ordinary intersections in range
275 //   void remove(double one, double two, const SkDPoint& startPt, const SkDPoint& endPt);
276
277    SkDPoint fPt[9];  // FIXME: since scans store points as SkPoint, this should also
278    double fT[2][9];
279    uint16_t fIsCoincident[2];  // bit set for each curve's coincident T
280    uint16_t fIsNear;  // bit set for each T if 2nd curve's point is near but not equal to 1st
281    unsigned char fUsed;
282    unsigned char fMax;
283    bool fAllowNear;
284    bool fSwap;
285#ifdef SK_DEBUG
286    int fDepth;
287#endif
288};
289
290extern int (SkIntersections::*CurveRay[])(const SkPoint[], const SkDLine& );
291extern int (SkIntersections::*CurveVertical[])(const SkPoint[], SkScalar top, SkScalar bottom,
292            SkScalar x, bool flipped);
293
294#endif
295