blob: 0186b3797d5101a0c045da08c7f6759e75094dc7 [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));
caryclarkdac1d172014-06-17 05:15:38 -070024 sk_bzero(fPt2, sizeof(fPt2));
caryclark@google.com07393ca2013-04-08 11:47:37 +000025 sk_bzero(fT, sizeof(fT));
26 sk_bzero(fIsCoincident, sizeof(fIsCoincident));
caryclarkdac1d172014-06-17 05:15:38 -070027 sk_bzero(fNearlySame, sizeof(fNearlySame));
caryclark@google.com07393ca2013-04-08 11:47:37 +000028 reset();
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000029 fMax = 0; // require that the caller set the max
caryclark@google.com07393ca2013-04-08 11:47:37 +000030 }
31
32 class TArray {
33 public:
34 explicit TArray(const double ts[9]) : fTArray(ts) {}
35 double operator[](int n) const {
36 return fTArray[n];
37 }
38 const double* fTArray;
39 };
40 TArray operator[](int n) const { return TArray(fT[n]); }
41
caryclark@google.comfa2aeee2013-07-15 13:29:13 +000042 void allowNear(bool nearAllowed) {
43 fAllowNear = nearAllowed;
44 }
45
caryclark@google.com07393ca2013-04-08 11:47:37 +000046 int cubic(const SkPoint a[4]) {
47 SkDCubic cubic;
48 cubic.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000049 fMax = 1; // self intersect
caryclark@google.com07393ca2013-04-08 11:47:37 +000050 return intersect(cubic);
51 }
52
53 int cubicCubic(const SkPoint a[4], const SkPoint b[4]) {
54 SkDCubic aCubic;
55 aCubic.set(a);
56 SkDCubic bCubic;
57 bCubic.set(b);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000058 fMax = 9;
caryclark@google.com07393ca2013-04-08 11:47:37 +000059 return intersect(aCubic, bCubic);
60 }
61
62 int cubicHorizontal(const SkPoint a[4], SkScalar left, SkScalar right, SkScalar y,
63 bool flipped) {
64 SkDCubic cubic;
65 cubic.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000066 fMax = 3;
caryclark@google.com07393ca2013-04-08 11:47:37 +000067 return horizontal(cubic, left, right, y, flipped);
68 }
69
70 int cubicVertical(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
71 SkDCubic cubic;
72 cubic.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000073 fMax = 3;
caryclark@google.com07393ca2013-04-08 11:47:37 +000074 return vertical(cubic, top, bottom, x, flipped);
75 }
76
77 int cubicLine(const SkPoint a[4], const SkPoint b[2]) {
78 SkDCubic cubic;
79 cubic.set(a);
80 SkDLine line;
81 line.set(b);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000082 fMax = 3;
caryclark@google.com07393ca2013-04-08 11:47:37 +000083 return intersect(cubic, line);
84 }
85
86 int cubicQuad(const SkPoint a[4], const SkPoint b[3]) {
87 SkDCubic cubic;
88 cubic.set(a);
89 SkDQuad quad;
90 quad.set(b);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000091 fMax = 6;
caryclark@google.com07393ca2013-04-08 11:47:37 +000092 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);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000116 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000117 return horizontal(line, left, right, y, flipped);
118 }
119
120 int lineVertical(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
121 SkDLine line;
122 line.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000123 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000124 return vertical(line, top, bottom, x, flipped);
125 }
126
127 int lineLine(const SkPoint a[2], const SkPoint b[2]) {
128 SkDLine aLine, bLine;
129 aLine.set(a);
130 bLine.set(b);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000131 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000132 return intersect(aLine, bLine);
133 }
134
caryclarkdac1d172014-06-17 05:15:38 -0700135 bool nearlySame(int index) const {
136 SkASSERT(index == 0 || index == 1);
137 return fNearlySame[index];
138 }
139
caryclark@google.com07393ca2013-04-08 11:47:37 +0000140 const SkDPoint& pt(int index) const {
141 return fPt[index];
142 }
143
caryclarkdac1d172014-06-17 05:15:38 -0700144 const SkDPoint& pt2(int index) const {
145 return fPt2[index];
146 }
147
caryclark@google.com07393ca2013-04-08 11:47:37 +0000148 int quadHorizontal(const SkPoint a[3], SkScalar left, SkScalar right, SkScalar y,
149 bool flipped) {
150 SkDQuad quad;
151 quad.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000152 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000153 return horizontal(quad, left, right, y, flipped);
154 }
155
156 int quadVertical(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
157 SkDQuad quad;
158 quad.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000159 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000160 return vertical(quad, top, bottom, x, flipped);
161 }
162
163 int quadLine(const SkPoint a[3], const SkPoint b[2]) {
164 SkDQuad quad;
165 quad.set(a);
166 SkDLine line;
167 line.set(b);
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +0000168 fMax = 3; // 2; permit small coincident segment + non-coincident intersection
caryclark@google.com07393ca2013-04-08 11:47:37 +0000169 return intersect(quad, line);
170 }
171
172 int quadQuad(const SkPoint a[3], const SkPoint b[3]) {
173 SkDQuad aQuad;
174 aQuad.set(a);
175 SkDQuad bQuad;
176 bQuad.set(b);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000177 fMax = 4;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000178 return intersect(aQuad, bQuad);
179 }
180
caryclarkdac1d172014-06-17 05:15:38 -0700181 // leaves swap, max alone
caryclark@google.com07393ca2013-04-08 11:47:37 +0000182 void reset() {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000183 fAllowNear = true;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000184 fUsed = 0;
185 }
186
caryclarkdac1d172014-06-17 05:15:38 -0700187 void set(bool swap, int tIndex, double t) {
188 fT[(int) swap][tIndex] = t;
189 }
190
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000191 void setMax(int max) {
192 fMax = max;
193 }
194
caryclark@google.com07393ca2013-04-08 11:47:37 +0000195 void swap() {
196 fSwap ^= true;
197 }
198
199 void swapPts();
200
201 bool swapped() const {
202 return fSwap;
203 }
204
205 int used() const {
206 return fUsed;
207 }
208
209 void downDepth() {
210 SkASSERT(--fDepth >= 0);
211 }
212
213 void upDepth() {
214 SkASSERT(++fDepth < 16);
215 }
216
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000217 void append(const SkIntersections& );
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000218 void cleanUpCoincidence();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000219 int coincidentUsed() const;
caryclarkdac1d172014-06-17 05:15:38 -0700220 void cubicInsert(double one, double two, const SkDPoint& pt, const SkDCubic& c1,
221 const SkDCubic& c2);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000222 int cubicRay(const SkPoint pts[4], const SkDLine& line);
223 void flip();
224 int horizontal(const SkDLine&, double y);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000225 int horizontal(const SkDLine&, double left, double right, double y, bool flipped);
226 int horizontal(const SkDQuad&, double left, double right, double y, bool flipped);
227 int horizontal(const SkDQuad&, double left, double right, double y, double tRange[2]);
228 int horizontal(const SkDCubic&, double y, double tRange[3]);
229 int horizontal(const SkDCubic&, double left, double right, double y, bool flipped);
230 int horizontal(const SkDCubic&, double left, double right, double y, double tRange[3]);
231 // FIXME : does not respect swap
232 int insert(double one, double two, const SkDPoint& pt);
caryclarkdac1d172014-06-17 05:15:38 -0700233 void insertNear(double one, double two, const SkDPoint& pt1, const SkDPoint& pt2);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000234 // start if index == 0 : end if index == 1
235 void insertCoincident(double one, double two, const SkDPoint& pt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000236 int intersect(const SkDLine&, const SkDLine&);
237 int intersect(const SkDQuad&, const SkDLine&);
238 int intersect(const SkDQuad&, const SkDQuad&);
239 int intersect(const SkDCubic&); // return true if cubic self-intersects
240 int intersect(const SkDCubic&, const SkDLine&);
241 int intersect(const SkDCubic&, const SkDQuad&);
242 int intersect(const SkDCubic&, const SkDCubic&);
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000243 int intersectRay(const SkDLine&, const SkDLine&);
244 int intersectRay(const SkDQuad&, const SkDLine&);
245 int intersectRay(const SkDCubic&, const SkDLine&);
246 static SkDPoint Line(const SkDLine&, const SkDLine&);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000247 int lineRay(const SkPoint pts[2], const SkDLine& line);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000248 void offset(int base, double start, double end);
249 void quickRemoveOne(int index, int replace);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000250 int quadRay(const SkPoint pts[3], const SkDLine& line);
251 void removeOne(int index);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000252 static bool Test(const SkDLine& , const SkDLine&);
253 int vertical(const SkDLine&, double x);
254 int vertical(const SkDLine&, double top, double bottom, double x, bool flipped);
255 int vertical(const SkDQuad&, double top, double bottom, double x, bool flipped);
256 int vertical(const SkDCubic&, double top, double bottom, double x, bool flipped);
257 int verticalCubic(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
258 int verticalLine(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
259 int verticalQuad(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
260
261 int depth() const {
262#ifdef SK_DEBUG
263 return fDepth;
264#else
265 return 0;
266#endif
267 }
268
269private:
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000270 bool cubicCheckCoincidence(const SkDCubic& c1, const SkDCubic& c2);
271 bool cubicExactEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2);
272 void cubicNearEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2, const SkDRect& );
273 void cleanUpParallelLines(bool parallel);
274 void computePoints(const SkDLine& line, int used);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000275
caryclark@google.com570863f2013-09-16 15:55:01 +0000276 SkDPoint fPt[9]; // FIXME: since scans store points as SkPoint, this should also
caryclarkdac1d172014-06-17 05:15:38 -0700277 SkDPoint fPt2[9]; // used by nearly same to store alternate intersection point
caryclark@google.com07393ca2013-04-08 11:47:37 +0000278 double fT[2][9];
caryclark@google.com570863f2013-09-16 15:55:01 +0000279 uint16_t fIsCoincident[2]; // bit set for each curve's coincident T
caryclarkdac1d172014-06-17 05:15:38 -0700280 bool fNearlySame[2]; // true if end points nearly match
caryclark@google.com07393ca2013-04-08 11:47:37 +0000281 unsigned char fUsed;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000282 unsigned char fMax;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000283 bool fAllowNear;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000284 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