blob: 0e3fcd1173f8fa159f5c94b4d8055ef2f8d35d30 [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();
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000027 fMax = 0; // require that the caller set the max
caryclark@google.com07393ca2013-04-08 11:47:37 +000028 }
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));
44 fUsed = i.fUsed;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000045 fMax = i.fMax;
caryclark@google.comb3f09212013-04-17 15:49:16 +000046 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);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000057 fMax = 1; // self intersect
caryclark@google.com07393ca2013-04-08 11:47:37 +000058 return intersect(cubic);
59 }
60
61 int cubicCubic(const SkPoint a[4], const SkPoint b[4]) {
62 SkDCubic aCubic;
63 aCubic.set(a);
64 SkDCubic bCubic;
65 bCubic.set(b);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000066 fMax = 9;
caryclark@google.com07393ca2013-04-08 11:47:37 +000067 return intersect(aCubic, bCubic);
68 }
69
70 int cubicHorizontal(const SkPoint a[4], SkScalar left, SkScalar right, SkScalar y,
71 bool flipped) {
72 SkDCubic cubic;
73 cubic.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000074 fMax = 3;
caryclark@google.com07393ca2013-04-08 11:47:37 +000075 return horizontal(cubic, left, right, y, flipped);
76 }
77
78 int cubicVertical(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
79 SkDCubic cubic;
80 cubic.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000081 fMax = 3;
caryclark@google.com07393ca2013-04-08 11:47:37 +000082 return vertical(cubic, top, bottom, x, flipped);
83 }
84
85 int cubicLine(const SkPoint a[4], const SkPoint b[2]) {
86 SkDCubic cubic;
87 cubic.set(a);
88 SkDLine line;
89 line.set(b);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000090 fMax = 3;
caryclark@google.com07393ca2013-04-08 11:47:37 +000091 return intersect(cubic, line);
92 }
93
94 int cubicQuad(const SkPoint a[4], const SkPoint b[3]) {
95 SkDCubic cubic;
96 cubic.set(a);
97 SkDQuad quad;
98 quad.set(b);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000099 fMax = 6;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000100 return intersect(cubic, quad);
101 }
102
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000103 bool hasT(double t) const {
104 SkASSERT(t == 0 || t == 1);
105 return fUsed > 0 && (t == 0 ? fT[0][0] == 0 : fT[0][fUsed - 1] == 1);
106 }
107
caryclark@google.com07393ca2013-04-08 11:47:37 +0000108 int insertSwap(double one, double two, const SkDPoint& pt) {
109 if (fSwap) {
110 return insert(two, one, pt);
111 } else {
112 return insert(one, two, pt);
113 }
114 }
115
116 bool isCoincident(int index) {
117 return (fIsCoincident[0] & 1 << index) != 0;
118 }
119
120 int lineHorizontal(const SkPoint a[2], SkScalar left, SkScalar right, SkScalar y,
121 bool flipped) {
122 SkDLine line;
123 line.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000124 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000125 return horizontal(line, left, right, y, flipped);
126 }
127
128 int lineVertical(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
129 SkDLine line;
130 line.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000131 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000132 return vertical(line, top, bottom, x, flipped);
133 }
134
135 int lineLine(const SkPoint a[2], const SkPoint b[2]) {
136 SkDLine aLine, bLine;
137 aLine.set(a);
138 bLine.set(b);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000139 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000140 return intersect(aLine, bLine);
141 }
142
143 const SkDPoint& pt(int index) const {
144 return fPt[index];
145 }
146
147 int quadHorizontal(const SkPoint a[3], SkScalar left, SkScalar right, SkScalar y,
148 bool flipped) {
149 SkDQuad quad;
150 quad.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000151 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000152 return horizontal(quad, left, right, y, flipped);
153 }
154
155 int quadVertical(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) {
156 SkDQuad quad;
157 quad.set(a);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000158 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000159 return vertical(quad, top, bottom, x, flipped);
160 }
161
162 int quadLine(const SkPoint a[3], const SkPoint b[2]) {
163 SkDQuad quad;
164 quad.set(a);
165 SkDLine line;
166 line.set(b);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000167 fMax = 2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000168 return intersect(quad, line);
169 }
170
171 int quadQuad(const SkPoint a[3], const SkPoint b[3]) {
172 SkDQuad aQuad;
173 aQuad.set(a);
174 SkDQuad bQuad;
175 bQuad.set(b);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000176 fMax = 4;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000177 return intersect(aQuad, bQuad);
178 }
179
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000180 // leaves flip, swap, max alone
caryclark@google.com07393ca2013-04-08 11:47:37 +0000181 void reset() {
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000182 fAllowNear = true;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000183 fUsed = 0;
184 }
185
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000186 void setMax(int max) {
187 fMax = max;
188 }
189
caryclark@google.com07393ca2013-04-08 11:47:37 +0000190 void swap() {
191 fSwap ^= true;
192 }
193
194 void swapPts();
195
196 bool swapped() const {
197 return fSwap;
198 }
199
200 int used() const {
201 return fUsed;
202 }
203
204 void downDepth() {
205 SkASSERT(--fDepth >= 0);
206 }
207
208 void upDepth() {
209 SkASSERT(++fDepth < 16);
210 }
211
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000212 void append(const SkIntersections& );
caryclark@google.com07393ca2013-04-08 11:47:37 +0000213 static double Axial(const SkDQuad& , const SkDPoint& , bool vertical);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000214 void cleanUpCoincidence();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000215 int coincidentUsed() const;
216 int cubicRay(const SkPoint pts[4], const SkDLine& line);
217 void flip();
218 int horizontal(const SkDLine&, double y);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000219 int horizontal(const SkDLine&, double left, double right, double y, bool flipped);
220 int horizontal(const SkDQuad&, double left, double right, double y, bool flipped);
221 int horizontal(const SkDQuad&, double left, double right, double y, double tRange[2]);
222 int horizontal(const SkDCubic&, double y, double tRange[3]);
223 int horizontal(const SkDCubic&, double left, double right, double y, bool flipped);
224 int horizontal(const SkDCubic&, double left, double right, double y, double tRange[3]);
225 // FIXME : does not respect swap
226 int insert(double one, double two, const SkDPoint& pt);
caryclark@google.com570863f2013-09-16 15:55:01 +0000227 void insertNear(double one, double two, const SkDPoint& pt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000228 // start if index == 0 : end if index == 1
229 void insertCoincident(double one, double two, const SkDPoint& pt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000230 int intersect(const SkDLine&, const SkDLine&);
231 int intersect(const SkDQuad&, const SkDLine&);
232 int intersect(const SkDQuad&, const SkDQuad&);
233 int intersect(const SkDCubic&); // return true if cubic self-intersects
234 int intersect(const SkDCubic&, const SkDLine&);
235 int intersect(const SkDCubic&, const SkDQuad&);
236 int intersect(const SkDCubic&, const SkDCubic&);
caryclark@google.comcffbcc32013-06-04 17:59:42 +0000237 int intersectRay(const SkDLine&, const SkDLine&);
238 int intersectRay(const SkDQuad&, const SkDLine&);
239 int intersectRay(const SkDCubic&, const SkDLine&);
240 static SkDPoint Line(const SkDLine&, const SkDLine&);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000241 int lineRay(const SkPoint pts[2], const SkDLine& line);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000242 void offset(int base, double start, double end);
243 void quickRemoveOne(int index, int replace);
caryclark@google.coma2bbc6e2013-11-01 17:36:03 +0000244 int quadRay(const SkPoint pts[3], const SkDLine& line);
245 void removeOne(int index);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000246 static bool Test(const SkDLine& , const SkDLine&);
247 int vertical(const SkDLine&, double x);
248 int vertical(const SkDLine&, double top, double bottom, double x, bool flipped);
249 int vertical(const SkDQuad&, double top, double bottom, double x, bool flipped);
250 int vertical(const SkDCubic&, double top, double bottom, double x, bool flipped);
251 int verticalCubic(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
252 int verticalLine(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
253 int verticalQuad(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped);
254
255 int depth() const {
256#ifdef SK_DEBUG
257 return fDepth;
258#else
259 return 0;
260#endif
261 }
262
263private:
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000264 bool cubicCheckCoincidence(const SkDCubic& c1, const SkDCubic& c2);
265 bool cubicExactEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2);
266 void cubicNearEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2, const SkDRect& );
267 void cleanUpParallelLines(bool parallel);
268 void computePoints(const SkDLine& line, int used);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000269 // used by addCoincident to remove ordinary intersections in range
caryclark@google.com07e97fc2013-07-08 17:17:02 +0000270 // void remove(double one, double two, const SkDPoint& startPt, const SkDPoint& endPt);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000271
caryclark@google.com570863f2013-09-16 15:55:01 +0000272 SkDPoint fPt[9]; // FIXME: since scans store points as SkPoint, this should also
caryclark@google.com07393ca2013-04-08 11:47:37 +0000273 double fT[2][9];
caryclark@google.com570863f2013-09-16 15:55:01 +0000274 uint16_t fIsCoincident[2]; // bit set for each curve's coincident T
caryclark@google.com07393ca2013-04-08 11:47:37 +0000275 unsigned char fUsed;
caryclark@google.com7eaa53d2013-10-02 14:49:34 +0000276 unsigned char fMax;
caryclark@google.comfa2aeee2013-07-15 13:29:13 +0000277 bool fAllowNear;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000278 bool fSwap;
279#ifdef SK_DEBUG
280 int fDepth;
281#endif
282};
283
284extern int (SkIntersections::*CurveRay[])(const SkPoint[], const SkDLine& );
285extern int (SkIntersections::*CurveVertical[])(const SkPoint[], SkScalar top, SkScalar bottom,
286 SkScalar x, bool flipped);
287
288#endif