blob: a1bde512db075a813facec448336968e0ca646c3 [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)
caryclark65f55312014-11-13 06:58:52 -080019 , fFlatMeasure(false)
caryclark@google.com07393ca2013-04-08 11:47:37 +000020#ifdef SK_DEBUG
21 , fDepth(0)
22#endif
23 {
24 sk_bzero(fPt, sizeof(fPt));
caryclarkdac1d172014-06-17 05:15:38 -070025 sk_bzero(fPt2, sizeof(fPt2));
caryclark@google.com07393ca2013-04-08 11:47:37 +000026 sk_bzero(fT, sizeof(fT));
27 sk_bzero(fIsCoincident, sizeof(fIsCoincident));
caryclarkdac1d172014-06-17 05:15:38 -070028 sk_bzero(fNearlySame, sizeof(fNearlySame));
caryclark@google.com07393ca2013-04-08 11:47:37 +000029 reset();
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000030 fMax = 0; // require that the caller set the max
caryclark@google.com07393ca2013-04-08 11:47:37 +000031 }
32
33 class TArray {
34 public:
35 explicit TArray(const double ts[9]) : fTArray(ts) {}
36 double operator[](int n) const {
37 return fTArray[n];
38 }
39 const double* fTArray;
40 };
41 TArray operator[](int n) const { return TArray(fT[n]); }
42
caryclark65f55312014-11-13 06:58:52 -080043 void allowFlatMeasure(bool flatAllowed) {
44 fFlatMeasure = flatAllowed;
45 }
46
caryclark@google.comfa2aeee2013-07-15 13:29:13 +000047 void allowNear(bool nearAllowed) {
48 fAllowNear = nearAllowed;
49 }
50
caryclark@google.com07393ca2013-04-08 11:47:37 +000051 int cubic(const SkPoint a[4]) {
52 SkDCubic cubic;
53 cubic.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000054 fMax = 1; // self intersect
caryclark@google.com07393ca2013-04-08 11:47:37 +000055 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);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000063 fMax = 9;
caryclark@google.com07393ca2013-04-08 11:47:37 +000064 return intersect(aCubic, bCubic);
65 }
66
67 int cubicHorizontal(const SkPoint a[4], SkScalar left, SkScalar right, SkScalar y,
68 bool flipped) {
69 SkDCubic cubic;
70 cubic.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000071 fMax = 3;
caryclark@google.com07393ca2013-04-08 11:47:37 +000072 return horizontal(cubic, left, right, y, flipped);
73 }
74
75 int cubicVertical(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
76 SkDCubic cubic;
77 cubic.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000078 fMax = 3;
caryclark@google.com07393ca2013-04-08 11:47:37 +000079 return vertical(cubic, top, bottom, x, flipped);
80 }
81
82 int cubicLine(const SkPoint a[4], const SkPoint b[2]) {
83 SkDCubic cubic;
84 cubic.set(a);
85 SkDLine line;
86 line.set(b);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000087 fMax = 3;
caryclark@google.com07393ca2013-04-08 11:47:37 +000088 return intersect(cubic, line);
89 }
90
91 int cubicQuad(const SkPoint a[4], const SkPoint b[3]) {
92 SkDCubic cubic;
93 cubic.set(a);
94 SkDQuad quad;
95 quad.set(b);
caryclark65f55312014-11-13 06:58:52 -080096 fMax = 7;
caryclark@google.com07393ca2013-04-08 11:47:37 +000097 return intersect(cubic, quad);
98 }
99
caryclark65f55312014-11-13 06:58:52 -0800100 bool flatMeasure() const {
101 return fFlatMeasure;
102 }
103
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000104 bool hasT(double t) const {
105 SkASSERT(t == 0 || t == 1);
106 return fUsed > 0 && (t == 0 ? fT[0][0] == 0 : fT[0][fUsed - 1] == 1);
107 }
108
caryclark@google.com07393ca2013-04-08 11:47:37 +0000109 int insertSwap(double one, double two, const SkDPoint& pt) {
110 if (fSwap) {
111 return insert(two, one, pt);
112 } else {
113 return insert(one, two, pt);
114 }
115 }
116
117 bool isCoincident(int index) {
118 return (fIsCoincident[0] & 1 << index) != 0;
119 }
120
121 int lineHorizontal(const SkPoint a[2], SkScalar left, SkScalar right, SkScalar y,
122 bool flipped) {
123 SkDLine line;
124 line.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000125 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000126 return horizontal(line, left, right, y, flipped);
127 }
128
129 int lineVertical(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
130 SkDLine line;
131 line.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000132 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000133 return vertical(line, top, bottom, x, flipped);
134 }
135
136 int lineLine(const SkPoint a[2], const SkPoint b[2]) {
137 SkDLine aLine, bLine;
138 aLine.set(a);
139 bLine.set(b);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000140 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000141 return intersect(aLine, bLine);
142 }
143
caryclarkdac1d172014-06-17 05:15:38 -0700144 bool nearlySame(int index) const {
145 SkASSERT(index == 0 || index == 1);
146 return fNearlySame[index];
147 }
148
caryclark@google.com07393ca2013-04-08 11:47:37 +0000149 const SkDPoint& pt(int index) const {
150 return fPt[index];
151 }
152
caryclarkdac1d172014-06-17 05:15:38 -0700153 const SkDPoint& pt2(int index) const {
154 return fPt2[index];
155 }
156
caryclark@google.com07393ca2013-04-08 11:47:37 +0000157 int quadHorizontal(const SkPoint a[3], SkScalar left, SkScalar right, SkScalar y,
158 bool flipped) {
159 SkDQuad quad;
160 quad.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000161 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000162 return horizontal(quad, left, right, y, flipped);
163 }
164
165 int quadVertical(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
166 SkDQuad quad;
167 quad.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000168 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000169 return vertical(quad, top, bottom, x, flipped);
170 }
171
172 int quadLine(const SkPoint a[3], const SkPoint b[2]) {
173 SkDQuad quad;
174 quad.set(a);
175 SkDLine line;
176 line.set(b);
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000177 fMax = 3; // 2; permit small coincident segment + non-coincident intersection
caryclark@google.com07393ca2013-04-08 11:47:37 +0000178 return intersect(quad, line);
179 }
180
181 int quadQuad(const SkPoint a[3], const SkPoint b[3]) {
182 SkDQuad aQuad;
183 aQuad.set(a);
184 SkDQuad bQuad;
185 bQuad.set(b);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000186 fMax = 4;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000187 return intersect(aQuad, bQuad);
188 }
189
caryclarkdac1d172014-06-17 05:15:38 -0700190 // leaves swap, max alone
caryclark@google.com07393ca2013-04-08 11:47:37 +0000191 void reset() {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000192 fAllowNear = true;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000193 fUsed = 0;
194 }
195
caryclarkdac1d172014-06-17 05:15:38 -0700196 void set(bool swap, int tIndex, double t) {
197 fT[(int) swap][tIndex] = t;
198 }
199
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000200 void setMax(int max) {
201 fMax = max;
202 }
203
caryclark@google.com07393ca2013-04-08 11:47:37 +0000204 void swap() {
205 fSwap ^= true;
206 }
207
208 void swapPts();
209
210 bool swapped() const {
211 return fSwap;
212 }
caryclark65f55312014-11-13 06:58:52 -0800213
caryclark@google.com07393ca2013-04-08 11:47:37 +0000214 int used() const {
215 return fUsed;
216 }
217
218 void downDepth() {
219 SkASSERT(--fDepth >= 0);
220 }
221
222 void upDepth() {
223 SkASSERT(++fDepth < 16);
224 }
225
caryclark65f55312014-11-13 06:58:52 -0800226 void alignQuadPts(const SkPoint a[3], const SkPoint b[3]);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000227 void append(const SkIntersections& );
caryclark65f55312014-11-13 06:58:52 -0800228 int cleanUpCoincidence();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000229 int coincidentUsed() const;
caryclarkdac1d172014-06-17 05:15:38 -0700230 void cubicInsert(double one, double two, const SkDPoint& pt, const SkDCubic& c1,
231 const SkDCubic& c2);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000232 int cubicRay(const SkPoint pts[4], const SkDLine& line);
233 void flip();
234 int horizontal(const SkDLine&, double y);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000235 int horizontal(const SkDLine&, double left, double right, double y, bool flipped);
236 int horizontal(const SkDQuad&, double left, double right, double y, bool flipped);
237 int horizontal(const SkDQuad&, double left, double right, double y, double tRange[2]);
238 int horizontal(const SkDCubic&, double y, double tRange[3]);
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 // FIXME : does not respect swap
242 int insert(double one, double two, const SkDPoint& pt);
caryclarkdac1d172014-06-17 05:15:38 -0700243 void insertNear(double one, double two, const SkDPoint& pt1, const SkDPoint& pt2);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000244 // start if index == 0 : end if index == 1
245 void insertCoincident(double one, double two, const SkDPoint& pt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000246 int intersect(const SkDLine&, const SkDLine&);
247 int intersect(const SkDQuad&, const SkDLine&);
248 int intersect(const SkDQuad&, const SkDQuad&);
249 int intersect(const SkDCubic&); // return true if cubic self-intersects
250 int intersect(const SkDCubic&, const SkDLine&);
251 int intersect(const SkDCubic&, const SkDQuad&);
252 int intersect(const SkDCubic&, const SkDCubic&);
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000253 int intersectRay(const SkDLine&, const SkDLine&);
254 int intersectRay(const SkDQuad&, const SkDLine&);
255 int intersectRay(const SkDCubic&, const SkDLine&);
256 static SkDPoint Line(const SkDLine&, const SkDLine&);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000257 int lineRay(const SkPoint pts[2], const SkDLine& line);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000258 void offset(int base, double start, double end);
259 void quickRemoveOne(int index, int replace);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000260 int quadRay(const SkPoint pts[3], const SkDLine& line);
261 void removeOne(int index);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000262 static bool Test(const SkDLine& , const SkDLine&);
263 int vertical(const SkDLine&, double x);
264 int vertical(const SkDLine&, double top, double bottom, double x, bool flipped);
265 int vertical(const SkDQuad&, double top, double bottom, double x, bool flipped);
266 int vertical(const SkDCubic&, double top, double bottom, double x, bool flipped);
267 int verticalCubic(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
268 int verticalLine(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
269 int verticalQuad(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
270
271 int depth() const {
272#ifdef SK_DEBUG
273 return fDepth;
274#else
275 return 0;
276#endif
277 }
278
279private:
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000280 bool cubicCheckCoincidence(const SkDCubic& c1, const SkDCubic& c2);
281 bool cubicExactEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2);
282 void cubicNearEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2, const SkDRect& );
283 void cleanUpParallelLines(bool parallel);
284 void computePoints(const SkDLine& line, int used);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000285
caryclark@google.com570863f2013-09-16 15:55:01 +0000286 SkDPoint fPt[9]; // FIXME: since scans store points as SkPoint, this should also
caryclarkdac1d172014-06-17 05:15:38 -0700287 SkDPoint fPt2[9]; // used by nearly same to store alternate intersection point
caryclark@google.com07393ca2013-04-08 11:47:37 +0000288 double fT[2][9];
caryclark@google.com570863f2013-09-16 15:55:01 +0000289 uint16_t fIsCoincident[2]; // bit set for each curve's coincident T
caryclarkdac1d172014-06-17 05:15:38 -0700290 bool fNearlySame[2]; // true if end points nearly match
caryclark@google.com07393ca2013-04-08 11:47:37 +0000291 unsigned char fUsed;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000292 unsigned char fMax;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000293 bool fAllowNear;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000294 bool fSwap;
caryclark65f55312014-11-13 06:58:52 -0800295 bool fFlatMeasure; // backwards-compatibility when cubics uses quad intersection
caryclark@google.com07393ca2013-04-08 11:47:37 +0000296#ifdef SK_DEBUG
297 int fDepth;
298#endif
299};
300
caryclark2e403812014-08-25 06:53:04 -0700301extern int (SkIntersections::* const CurveRay[])(const SkPoint[], const SkDLine& );
302extern int (SkIntersections::* const CurveVertical[])(const SkPoint[], SkScalar top, SkScalar bottom,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000303 SkScalar x, bool flipped);
304
305#endif