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