blob: 26a1d1a559e56c132418ba71da9e5eeb6c2c2604 [file] [log] [blame]
caryclark@google.com07393ca2013-04-08 11:47:37 +00001/*
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 reset();
27 }
28
29 class TArray {
30 public:
31 explicit TArray(const double ts[9]) : fTArray(ts) {}
32 double operator[](int n) const {
33 return fTArray[n];
34 }
35 const double* fTArray;
36 };
37 TArray operator[](int n) const { return TArray(fT[n]); }
38
caryclark@google.comb3f09212013-04-17 15:49:16 +000039 void set(const SkIntersections& i) {
40 memcpy(fPt, i.fPt, sizeof(fPt));
41 memcpy(fT, i.fT, sizeof(fT));
42 memcpy(fIsCoincident, i.fIsCoincident, sizeof(fIsCoincident));
43 fUsed = i.fUsed;
44 fSwap = i.fSwap;
45 SkDEBUGCODE(fDepth = i.fDepth);
46 }
47
caryclark@google.comfa2aeee2013-07-15 13:29:13 +000048 void allowNear(bool nearAllowed) {
49 fAllowNear = nearAllowed;
50 }
51
caryclark@google.com07393ca2013-04-08 11:47:37 +000052 int cubic(const SkPoint a[4]) {
53 SkDCubic cubic;
54 cubic.set(a);
55 return intersect(cubic);
56 }
57
58 int cubicCubic(const SkPoint a[4], const SkPoint b[4]) {
59 SkDCubic aCubic;
60 aCubic.set(a);
61 SkDCubic bCubic;
62 bCubic.set(b);
63 return intersect(aCubic, bCubic);
64 }
65
66 int cubicHorizontal(const SkPoint a[4], SkScalar left, SkScalar right, SkScalar y,
67 bool flipped) {
68 SkDCubic cubic;
69 cubic.set(a);
70 return horizontal(cubic, left, right, y, flipped);
71 }
72
73 int cubicVertical(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
74 SkDCubic cubic;
75 cubic.set(a);
76 return vertical(cubic, top, bottom, x, flipped);
77 }
78
79 int cubicLine(const SkPoint a[4], const SkPoint b[2]) {
80 SkDCubic cubic;
81 cubic.set(a);
82 SkDLine line;
83 line.set(b);
84 return intersect(cubic, line);
85 }
86
87 int cubicQuad(const SkPoint a[4], const SkPoint b[3]) {
88 SkDCubic cubic;
89 cubic.set(a);
90 SkDQuad quad;
91 quad.set(b);
92 return intersect(cubic, quad);
93 }
94
caryclark@google.comfa2aeee2013-07-15 13:29:13 +000095 bool hasT(double t) const {
96 SkASSERT(t == 0 || t == 1);
97 return fUsed > 0 && (t == 0 ? fT[0][0] == 0 : fT[0][fUsed - 1] == 1);
98 }
99
caryclark@google.com07393ca2013-04-08 11:47:37 +0000100 int insertSwap(double one, double two, const SkDPoint& pt) {
101 if (fSwap) {
102 return insert(two, one, pt);
103 } else {
104 return insert(one, two, pt);
105 }
106 }
107
108 bool isCoincident(int index) {
109 return (fIsCoincident[0] & 1 << index) != 0;
110 }
111
112 int lineHorizontal(const SkPoint a[2], SkScalar left, SkScalar right, SkScalar y,
113 bool flipped) {
114 SkDLine line;
115 line.set(a);
116 return horizontal(line, left, right, y, flipped);
117 }
118
119 int lineVertical(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
120 SkDLine line;
121 line.set(a);
122 return vertical(line, top, bottom, x, flipped);
123 }
124
125 int lineLine(const SkPoint a[2], const SkPoint b[2]) {
126 SkDLine aLine, bLine;
127 aLine.set(a);
128 bLine.set(b);
129 return intersect(aLine, bLine);
130 }
131
132 const SkDPoint& pt(int index) const {
133 return fPt[index];
134 }
135
136 int quadHorizontal(const SkPoint a[3], SkScalar left, SkScalar right, SkScalar y,
137 bool flipped) {
138 SkDQuad quad;
139 quad.set(a);
140 return horizontal(quad, left, right, y, flipped);
141 }
142
143 int quadVertical(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
144 SkDQuad quad;
145 quad.set(a);
146 return vertical(quad, top, bottom, x, flipped);
147 }
148
149 int quadLine(const SkPoint a[3], const SkPoint b[2]) {
150 SkDQuad quad;
151 quad.set(a);
152 SkDLine line;
153 line.set(b);
154 return intersect(quad, line);
155 }
156
157 int quadQuad(const SkPoint a[3], const SkPoint b[3]) {
158 SkDQuad aQuad;
159 aQuad.set(a);
160 SkDQuad bQuad;
161 bQuad.set(b);
162 return intersect(aQuad, bQuad);
163 }
164
165 int quadRay(const SkPoint pts[3], const SkDLine& line);
166 void removeOne(int index);
167
168 // leaves flip, swap alone
169 void reset() {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000170 fAllowNear = true;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000171 fUsed = 0;
172 }
173
174 void swap() {
175 fSwap ^= true;
176 }
177
178 void swapPts();
179
180 bool swapped() const {
181 return fSwap;
182 }
183
184 int used() const {
185 return fUsed;
186 }
187
188 void downDepth() {
189 SkASSERT(--fDepth >= 0);
190 }
191
192 void upDepth() {
193 SkASSERT(++fDepth < 16);
194 }
195
196 static double Axial(const SkDQuad& , const SkDPoint& , bool vertical);
197 int coincidentUsed() const;
198 int cubicRay(const SkPoint pts[4], const SkDLine& line);
199 void flip();
200 int horizontal(const SkDLine&, double y);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000201 int horizontal(const SkDLine&, double left, double right, double y, bool flipped);
202 int horizontal(const SkDQuad&, double left, double right, double y, bool flipped);
203 int horizontal(const SkDQuad&, double left, double right, double y, double tRange[2]);
204 int horizontal(const SkDCubic&, double y, double tRange[3]);
205 int horizontal(const SkDCubic&, double left, double right, double y, bool flipped);
206 int horizontal(const SkDCubic&, double left, double right, double y, double tRange[3]);
207 // FIXME : does not respect swap
208 int insert(double one, double two, const SkDPoint& pt);
209 // start if index == 0 : end if index == 1
210 void insertCoincident(double one, double two, const SkDPoint& pt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000211 int intersect(const SkDLine&, const SkDLine&);
212 int intersect(const SkDQuad&, const SkDLine&);
213 int intersect(const SkDQuad&, const SkDQuad&);
214 int intersect(const SkDCubic&); // return true if cubic self-intersects
215 int intersect(const SkDCubic&, const SkDLine&);
216 int intersect(const SkDCubic&, const SkDQuad&);
217 int intersect(const SkDCubic&, const SkDCubic&);
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000218 int intersectRay(const SkDLine&, const SkDLine&);
219 int intersectRay(const SkDQuad&, const SkDLine&);
220 int intersectRay(const SkDCubic&, const SkDLine&);
221 static SkDPoint Line(const SkDLine&, const SkDLine&);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000222 void offset(int base, double start, double end);
223 void quickRemoveOne(int index, int replace);
224 static bool Test(const SkDLine& , const SkDLine&);
225 int vertical(const SkDLine&, double x);
226 int vertical(const SkDLine&, double top, double bottom, double x, bool flipped);
227 int vertical(const SkDQuad&, double top, double bottom, double x, bool flipped);
228 int vertical(const SkDCubic&, double top, double bottom, double x, bool flipped);
229 int verticalCubic(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
230 int verticalLine(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
231 int verticalQuad(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
232
233 int depth() const {
234#ifdef SK_DEBUG
235 return fDepth;
236#else
237 return 0;
238#endif
239 }
240
241private:
242 int computePoints(const SkDLine& line, int used);
243 // used by addCoincident to remove ordinary intersections in range
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000244 // void remove(double one, double two, const SkDPoint& startPt, const SkDPoint& endPt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000245
246 SkDPoint fPt[9];
247 double fT[2][9];
248 uint16_t fIsCoincident[2]; // bit arrays, one bit set for each coincident T
249 unsigned char fUsed;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000250 bool fAllowNear;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000251 bool fSwap;
252#ifdef SK_DEBUG
253 int fDepth;
254#endif
255};
256
257extern int (SkIntersections::*CurveRay[])(const SkPoint[], const SkDLine& );
258extern int (SkIntersections::*CurveVertical[])(const SkPoint[], SkScalar top, SkScalar bottom,
259 SkScalar x, bool flipped);
260
261#endif