blob: 389098d84e67136dff4160f9d2635879e7fc4c71 [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));
caryclark@google.com570863f2013-09-16 15:55:01 +000026 sk_bzero(&fIsNear, sizeof(fIsNear));
caryclark@google.com07393ca2013-04-08 11:47:37 +000027 reset();
28 }
29
30 class TArray {
31 public:
32 explicit TArray(const double ts[9]) : fTArray(ts) {}
33 double operator[](int n) const {
34 return fTArray[n];
35 }
36 const double* fTArray;
37 };
38 TArray operator[](int n) const { return TArray(fT[n]); }
39
caryclark@google.comb3f09212013-04-17 15:49:16 +000040 void set(const SkIntersections& i) {
41 memcpy(fPt, i.fPt, sizeof(fPt));
42 memcpy(fT, i.fT, sizeof(fT));
43 memcpy(fIsCoincident, i.fIsCoincident, sizeof(fIsCoincident));
caryclark@google.com570863f2013-09-16 15:55:01 +000044 memcpy(&fIsNear, &i.fIsNear, sizeof(fIsNear));
caryclark@google.comb3f09212013-04-17 15:49:16 +000045 fUsed = i.fUsed;
46 fSwap = i.fSwap;
47 SkDEBUGCODE(fDepth = i.fDepth);
48 }
49
caryclark@google.comfa2aeee2013-07-15 13:29:13 +000050 void allowNear(bool nearAllowed) {
51 fAllowNear = nearAllowed;
52 }
53
caryclark@google.com07393ca2013-04-08 11:47:37 +000054 int cubic(const SkPoint a[4]) {
55 SkDCubic cubic;
56 cubic.set(a);
57 return intersect(cubic);
58 }
59
60 int cubicCubic(const SkPoint a[4], const SkPoint b[4]) {
61 SkDCubic aCubic;
62 aCubic.set(a);
63 SkDCubic bCubic;
64 bCubic.set(b);
65 return intersect(aCubic, bCubic);
66 }
67
68 int cubicHorizontal(const SkPoint a[4], SkScalar left, SkScalar right, SkScalar y,
69 bool flipped) {
70 SkDCubic cubic;
71 cubic.set(a);
72 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);
78 return vertical(cubic, top, bottom, x, flipped);
79 }
80
81 int cubicLine(const SkPoint a[4], const SkPoint b[2]) {
82 SkDCubic cubic;
83 cubic.set(a);
84 SkDLine line;
85 line.set(b);
86 return intersect(cubic, line);
87 }
88
89 int cubicQuad(const SkPoint a[4], const SkPoint b[3]) {
90 SkDCubic cubic;
91 cubic.set(a);
92 SkDQuad quad;
93 quad.set(b);
94 return intersect(cubic, quad);
95 }
96
caryclark@google.comfa2aeee2013-07-15 13:29:13 +000097 bool hasT(double t) const {
98 SkASSERT(t == 0 || t == 1);
99 return fUsed > 0 && (t == 0 ? fT[0][0] == 0 : fT[0][fUsed - 1] == 1);
100 }
101
caryclark@google.com07393ca2013-04-08 11:47:37 +0000102 int insertSwap(double one, double two, const SkDPoint& pt) {
103 if (fSwap) {
104 return insert(two, one, pt);
105 } else {
106 return insert(one, two, pt);
107 }
108 }
109
110 bool isCoincident(int index) {
111 return (fIsCoincident[0] & 1 << index) != 0;
112 }
113
caryclark@google.com570863f2013-09-16 15:55:01 +0000114 bool isNear(int index) {
115 return (fIsNear & 1 << index) != 0;
116 }
117
caryclark@google.com07393ca2013-04-08 11:47:37 +0000118 int lineHorizontal(const SkPoint a[2], SkScalar left, SkScalar right, SkScalar y,
119 bool flipped) {
120 SkDLine line;
121 line.set(a);
122 return horizontal(line, left, right, y, flipped);
123 }
124
125 int lineVertical(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
126 SkDLine line;
127 line.set(a);
128 return vertical(line, top, bottom, x, flipped);
129 }
130
131 int lineLine(const SkPoint a[2], const SkPoint b[2]) {
132 SkDLine aLine, bLine;
133 aLine.set(a);
134 bLine.set(b);
135 return intersect(aLine, bLine);
136 }
137
138 const SkDPoint& pt(int index) const {
139 return fPt[index];
140 }
141
142 int quadHorizontal(const SkPoint a[3], SkScalar left, SkScalar right, SkScalar y,
143 bool flipped) {
144 SkDQuad quad;
145 quad.set(a);
146 return horizontal(quad, left, right, y, flipped);
147 }
148
149 int quadVertical(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
150 SkDQuad quad;
151 quad.set(a);
152 return vertical(quad, top, bottom, x, flipped);
153 }
154
155 int quadLine(const SkPoint a[3], const SkPoint b[2]) {
156 SkDQuad quad;
157 quad.set(a);
158 SkDLine line;
159 line.set(b);
160 return intersect(quad, line);
161 }
162
163 int quadQuad(const SkPoint a[3], const SkPoint b[3]) {
164 SkDQuad aQuad;
165 aQuad.set(a);
166 SkDQuad bQuad;
167 bQuad.set(b);
168 return intersect(aQuad, bQuad);
169 }
170
171 int quadRay(const SkPoint pts[3], const SkDLine& line);
172 void removeOne(int index);
173
174 // leaves flip, swap alone
175 void reset() {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000176 fAllowNear = true;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000177 fUsed = 0;
178 }
179
180 void swap() {
181 fSwap ^= true;
182 }
183
184 void swapPts();
185
186 bool swapped() const {
187 return fSwap;
188 }
189
190 int used() const {
191 return fUsed;
192 }
193
194 void downDepth() {
195 SkASSERT(--fDepth >= 0);
196 }
197
198 void upDepth() {
199 SkASSERT(++fDepth < 16);
200 }
201
202 static double Axial(const SkDQuad& , const SkDPoint& , bool vertical);
203 int coincidentUsed() const;
204 int cubicRay(const SkPoint pts[4], const SkDLine& line);
205 void flip();
206 int horizontal(const SkDLine&, double y);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000207 int horizontal(const SkDLine&, double left, double right, double y, bool flipped);
208 int horizontal(const SkDQuad&, double left, double right, double y, bool flipped);
209 int horizontal(const SkDQuad&, double left, double right, double y, double tRange[2]);
210 int horizontal(const SkDCubic&, double y, double tRange[3]);
211 int horizontal(const SkDCubic&, double left, double right, double y, bool flipped);
212 int horizontal(const SkDCubic&, double left, double right, double y, double tRange[3]);
213 // FIXME : does not respect swap
214 int insert(double one, double two, const SkDPoint& pt);
caryclark@google.com570863f2013-09-16 15:55:01 +0000215 void insertNear(double one, double two, const SkDPoint& pt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000216 // start if index == 0 : end if index == 1
217 void insertCoincident(double one, double two, const SkDPoint& pt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000218 int intersect(const SkDLine&, const SkDLine&);
219 int intersect(const SkDQuad&, const SkDLine&);
220 int intersect(const SkDQuad&, const SkDQuad&);
221 int intersect(const SkDCubic&); // return true if cubic self-intersects
222 int intersect(const SkDCubic&, const SkDLine&);
223 int intersect(const SkDCubic&, const SkDQuad&);
224 int intersect(const SkDCubic&, const SkDCubic&);
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000225 int intersectRay(const SkDLine&, const SkDLine&);
226 int intersectRay(const SkDQuad&, const SkDLine&);
227 int intersectRay(const SkDCubic&, const SkDLine&);
228 static SkDPoint Line(const SkDLine&, const SkDLine&);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000229 void offset(int base, double start, double end);
230 void quickRemoveOne(int index, int replace);
231 static bool Test(const SkDLine& , const SkDLine&);
232 int vertical(const SkDLine&, double x);
233 int vertical(const SkDLine&, double top, double bottom, double x, bool flipped);
234 int vertical(const SkDQuad&, double top, double bottom, double x, bool flipped);
235 int vertical(const SkDCubic&, double top, double bottom, double x, bool flipped);
236 int verticalCubic(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
237 int verticalLine(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
238 int verticalQuad(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
239
240 int depth() const {
241#ifdef SK_DEBUG
242 return fDepth;
243#else
244 return 0;
245#endif
246 }
247
248private:
249 int computePoints(const SkDLine& line, int used);
250 // used by addCoincident to remove ordinary intersections in range
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000251 // void remove(double one, double two, const SkDPoint& startPt, const SkDPoint& endPt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000252
caryclark@google.com570863f2013-09-16 15:55:01 +0000253 SkDPoint fPt[9]; // FIXME: since scans store points as SkPoint, this should also
caryclark@google.com07393ca2013-04-08 11:47:37 +0000254 double fT[2][9];
caryclark@google.com570863f2013-09-16 15:55:01 +0000255 uint16_t fIsCoincident[2]; // bit set for each curve's coincident T
256 uint16_t fIsNear; // bit set for each T if 2nd curve's point is near but not equal to 1st
caryclark@google.com07393ca2013-04-08 11:47:37 +0000257 unsigned char fUsed;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000258 bool fAllowNear;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000259 bool fSwap;
260#ifdef SK_DEBUG
261 int fDepth;
262#endif
263};
264
265extern int (SkIntersections::*CurveRay[])(const SkPoint[], const SkDLine& );
266extern int (SkIntersections::*CurveVertical[])(const SkPoint[], SkScalar top, SkScalar bottom,
267 SkScalar x, bool flipped);
268
269#endif