blob: c830e66d4d6f23729b689bd9bc84d8031bf6453b [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 SkPathOpsCurve_DEFINE
8#define SkPathOpsCurve_DEFINE
9
commit-bot@chromium.org4431e772014-04-14 17:08:59 +000010#include "SkIntersections.h"
caryclark@google.com07393ca2013-04-08 11:47:37 +000011
caryclark1049f122015-04-20 08:31:59 -070012#ifndef SK_RELEASE
13#include "SkPath.h"
14#endif
15
caryclarkaec25102015-04-29 08:28:30 -070016struct SkPathOpsBounds;
17
caryclark1049f122015-04-20 08:31:59 -070018struct SkOpCurve {
19 SkPoint fPts[4];
20 SkScalar fWeight;
21 SkDEBUGCODE(SkPath::Verb fVerb);
22
23 const SkPoint& operator[](int n) const {
24 SkASSERT(n >= 0 && n <= SkPathOpsVerbToPoints(fVerb));
25 return fPts[n];
26 }
27
caryclark03b03ca2015-04-23 09:13:37 -070028 void dump() const;
29
30 void set(const SkDQuad& quad) {
31 for (int index = 0; index < SkDQuad::kPointCount; ++index) {
32 fPts[index] = quad[index].asSkPoint();
33 }
34 SkDEBUGCODE(fWeight = 1);
35 SkDEBUGCODE(fVerb = SkPath::kQuad_Verb);
36 }
37
caryclark1049f122015-04-20 08:31:59 -070038 void set(const SkDCubic& cubic) {
39 for (int index = 0; index < SkDCubic::kPointCount; ++index) {
40 fPts[index] = cubic[index].asSkPoint();
41 }
42 SkDEBUGCODE(fWeight = 1);
43 SkDEBUGCODE(fVerb = SkPath::kCubic_Verb);
44 }
caryclarkaec25102015-04-29 08:28:30 -070045
caryclark1049f122015-04-20 08:31:59 -070046};
47
48struct SkDCurve {
49 union {
50 SkDLine fLine;
51 SkDQuad fQuad;
52 SkDConic fConic;
53 SkDCubic fCubic;
54 };
55 SkDEBUGCODE(SkPath::Verb fVerb);
56
57 const SkDPoint& operator[](int n) const {
58 SkASSERT(n >= 0 && n <= SkPathOpsVerbToPoints(fVerb));
59 return fCubic[n];
60 }
61
62 SkDPoint& operator[](int n) {
63 SkASSERT(n >= 0 && n <= SkPathOpsVerbToPoints(fVerb));
64 return fCubic[n];
65 }
66
caryclarkaec25102015-04-29 08:28:30 -070067 SkDPoint conicTop(const SkPoint curve[3], SkScalar curveWeight,
68 double s, double e, double* topT);
69 SkDPoint cubicTop(const SkPoint curve[4], SkScalar , double s, double e, double* topT);
caryclark1049f122015-04-20 08:31:59 -070070 void dumpID(int ) const;
caryclarkaec25102015-04-29 08:28:30 -070071 SkDPoint lineTop(const SkPoint[2], SkScalar , double , double , double* topT);
72 SkDPoint quadTop(const SkPoint curve[3], SkScalar , double s, double e, double* topT);
73
74 void setConicBounds(const SkPoint curve[3], SkScalar curveWeight,
75 double s, double e, SkPathOpsBounds* );
76 void setCubicBounds(const SkPoint curve[4], SkScalar ,
77 double s, double e, SkPathOpsBounds* );
caryclarkaec25102015-04-29 08:28:30 -070078 void setQuadBounds(const SkPoint curve[3], SkScalar ,
79 double s, double e, SkPathOpsBounds*);
caryclark1049f122015-04-20 08:31:59 -070080};
81
caryclarkaec25102015-04-29 08:28:30 -070082
caryclarkaec25102015-04-29 08:28:30 -070083extern SkDPoint (SkDCurve::* const Top[])(const SkPoint curve[], SkScalar cWeight,
84 double tStart, double tEnd, double* topT);
85
caryclark1049f122015-04-20 08:31:59 -070086static SkDPoint dline_xy_at_t(const SkPoint a[2], SkScalar , double t) {
caryclark@google.com07393ca2013-04-08 11:47:37 +000087 SkDLine line;
88 line.set(a);
caryclark@google.com4fdbb222013-07-23 15:27:41 +000089 return line.ptAtT(t);
caryclark@google.com07393ca2013-04-08 11:47:37 +000090}
91
caryclark1049f122015-04-20 08:31:59 -070092static SkDPoint dquad_xy_at_t(const SkPoint a[3], SkScalar , double t) {
caryclark@google.com07393ca2013-04-08 11:47:37 +000093 SkDQuad quad;
94 quad.set(a);
caryclark@google.com4fdbb222013-07-23 15:27:41 +000095 return quad.ptAtT(t);
caryclark@google.com07393ca2013-04-08 11:47:37 +000096}
97
caryclark1049f122015-04-20 08:31:59 -070098static SkDPoint dconic_xy_at_t(const SkPoint a[3], SkScalar weight, double t) {
99 SkDConic conic;
100 conic.set(a, weight);
101 return conic.ptAtT(t);
102}
103
104static SkDPoint dcubic_xy_at_t(const SkPoint a[4], SkScalar , double t) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000105 SkDCubic cubic;
106 cubic.set(a);
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000107 return cubic.ptAtT(t);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000108}
109
caryclark1049f122015-04-20 08:31:59 -0700110static SkDPoint (* const CurveDPointAtT[])(const SkPoint[], SkScalar , double ) = {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000111 NULL,
112 dline_xy_at_t,
113 dquad_xy_at_t,
caryclark1049f122015-04-20 08:31:59 -0700114 dconic_xy_at_t,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000115 dcubic_xy_at_t
116};
117
caryclark1049f122015-04-20 08:31:59 -0700118static SkPoint fline_xy_at_t(const SkPoint a[2], SkScalar weight, double t) {
119 return dline_xy_at_t(a, weight, t).asSkPoint();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000120}
121
caryclark1049f122015-04-20 08:31:59 -0700122static SkPoint fquad_xy_at_t(const SkPoint a[3], SkScalar weight, double t) {
123 return dquad_xy_at_t(a, weight, t).asSkPoint();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000124}
125
caryclark1049f122015-04-20 08:31:59 -0700126static SkPoint fconic_xy_at_t(const SkPoint a[3], SkScalar weight, double t) {
127 return dconic_xy_at_t(a, weight, t).asSkPoint();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000128}
129
caryclark1049f122015-04-20 08:31:59 -0700130static SkPoint fcubic_xy_at_t(const SkPoint a[4], SkScalar weight, double t) {
131 return dcubic_xy_at_t(a, weight, t).asSkPoint();
132}
133
134static SkPoint (* const CurvePointAtT[])(const SkPoint[], SkScalar , double ) = {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000135 NULL,
136 fline_xy_at_t,
137 fquad_xy_at_t,
caryclark1049f122015-04-20 08:31:59 -0700138 fconic_xy_at_t,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000139 fcubic_xy_at_t
140};
141
caryclark1049f122015-04-20 08:31:59 -0700142static SkDVector dline_dxdy_at_t(const SkPoint a[2], SkScalar , double ) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000143 SkDLine line;
144 line.set(a);
145 return line[1] - line[0];
146}
147
caryclark1049f122015-04-20 08:31:59 -0700148static SkDVector dquad_dxdy_at_t(const SkPoint a[3], SkScalar , double t) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000149 SkDQuad quad;
150 quad.set(a);
151 return quad.dxdyAtT(t);
152}
153
caryclark1049f122015-04-20 08:31:59 -0700154static SkDVector dconic_dxdy_at_t(const SkPoint a[3], SkScalar weight, double t) {
155 SkDConic conic;
156 conic.set(a, weight);
157 return conic.dxdyAtT(t);
158}
159
160static SkDVector dcubic_dxdy_at_t(const SkPoint a[4], SkScalar , double t) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000161 SkDCubic cubic;
162 cubic.set(a);
163 return cubic.dxdyAtT(t);
164}
165
caryclark1049f122015-04-20 08:31:59 -0700166static SkDVector (* const CurveDSlopeAtT[])(const SkPoint[], SkScalar , double ) = {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000167 NULL,
168 dline_dxdy_at_t,
169 dquad_dxdy_at_t,
caryclark1049f122015-04-20 08:31:59 -0700170 dconic_dxdy_at_t,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000171 dcubic_dxdy_at_t
172};
173
caryclark1049f122015-04-20 08:31:59 -0700174static SkVector fline_dxdy_at_t(const SkPoint a[2], SkScalar , double ) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000175 return a[1] - a[0];
176}
177
caryclark1049f122015-04-20 08:31:59 -0700178static SkVector fquad_dxdy_at_t(const SkPoint a[3], SkScalar weight, double t) {
179 return dquad_dxdy_at_t(a, weight, t).asSkVector();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000180}
181
caryclark1049f122015-04-20 08:31:59 -0700182static SkVector fconic_dxdy_at_t(const SkPoint a[3], SkScalar weight, double t) {
183 return dconic_dxdy_at_t(a, weight, t).asSkVector();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000184}
185
caryclark1049f122015-04-20 08:31:59 -0700186static SkVector fcubic_dxdy_at_t(const SkPoint a[4], SkScalar weight, double t) {
187 return dcubic_dxdy_at_t(a, weight, t).asSkVector();
188}
189
190static SkVector (* const CurveSlopeAtT[])(const SkPoint[], SkScalar , double ) = {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000191 NULL,
192 fline_dxdy_at_t,
193 fquad_dxdy_at_t,
caryclark1049f122015-04-20 08:31:59 -0700194 fconic_dxdy_at_t,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000195 fcubic_dxdy_at_t
196};
197
caryclark1049f122015-04-20 08:31:59 -0700198static bool line_is_vertical(const SkPoint a[2], SkScalar , double startT, double endT) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000199 SkDLine line;
200 line.set(a);
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000201 SkDPoint dst[2] = { line.ptAtT(startT), line.ptAtT(endT) };
caryclark@google.com07393ca2013-04-08 11:47:37 +0000202 return AlmostEqualUlps(dst[0].fX, dst[1].fX);
203}
204
caryclark1049f122015-04-20 08:31:59 -0700205static bool quad_is_vertical(const SkPoint a[3], SkScalar , double startT, double endT) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000206 SkDQuad quad;
207 quad.set(a);
208 SkDQuad dst = quad.subDivide(startT, endT);
209 return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX);
210}
211
caryclark1049f122015-04-20 08:31:59 -0700212static bool conic_is_vertical(const SkPoint a[3], SkScalar weight, double startT, double endT) {
213 SkDConic conic;
214 conic.set(a, weight);
215 SkDConic dst = conic.subDivide(startT, endT);
216 return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX);
217}
218
219static bool cubic_is_vertical(const SkPoint a[4], SkScalar , double startT, double endT) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000220 SkDCubic cubic;
221 cubic.set(a);
222 SkDCubic dst = cubic.subDivide(startT, endT);
223 return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX)
224 && AlmostEqualUlps(dst[2].fX, dst[3].fX);
225}
226
caryclark1049f122015-04-20 08:31:59 -0700227static bool (* const CurveIsVertical[])(const SkPoint[], SkScalar , double , double) = {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000228 NULL,
229 line_is_vertical,
230 quad_is_vertical,
caryclark1049f122015-04-20 08:31:59 -0700231 conic_is_vertical,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000232 cubic_is_vertical
233};
234
caryclark1049f122015-04-20 08:31:59 -0700235static void line_intersect_ray(const SkPoint a[2], SkScalar , const SkDLine& ray,
236 SkIntersections* i) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000237 SkDLine line;
238 line.set(a);
239 i->intersectRay(line, ray);
240}
241
caryclark1049f122015-04-20 08:31:59 -0700242static void quad_intersect_ray(const SkPoint a[3], SkScalar , const SkDLine& ray,
243 SkIntersections* i) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000244 SkDQuad quad;
245 quad.set(a);
246 i->intersectRay(quad, ray);
247}
248
caryclark1049f122015-04-20 08:31:59 -0700249static void conic_intersect_ray(const SkPoint a[3], SkScalar weight, const SkDLine& ray,
250 SkIntersections* i) {
251 SkDConic conic;
252 conic.set(a, weight);
253 i->intersectRay(conic, ray);
254}
255
256static void cubic_intersect_ray(const SkPoint a[4], SkScalar , const SkDLine& ray,
257 SkIntersections* i) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000258 SkDCubic cubic;
259 cubic.set(a);
260 i->intersectRay(cubic, ray);
261}
262
caryclark1049f122015-04-20 08:31:59 -0700263static void (* const CurveIntersectRay[])(const SkPoint[] , SkScalar , const SkDLine& ,
264 SkIntersections* ) = {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000265 NULL,
266 line_intersect_ray,
267 quad_intersect_ray,
caryclark1049f122015-04-20 08:31:59 -0700268 conic_intersect_ray,
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000269 cubic_intersect_ray
270};
271
caryclark624637c2015-05-11 07:21:27 -0700272static int line_intercept_h(const SkPoint a[2], SkScalar , SkScalar y, double* roots) {
273 SkDLine line;
274 roots[0] = SkIntersections::HorizontalIntercept(line.set(a), y);
275 return between(0, roots[0], 1);
276}
277
278static int line_intercept_v(const SkPoint a[2], SkScalar , SkScalar x, double* roots) {
279 SkDLine line;
280 roots[0] = SkIntersections::VerticalIntercept(line.set(a), x);
281 return between(0, roots[0], 1);
282}
283
284static int quad_intercept_h(const SkPoint a[2], SkScalar , SkScalar y, double* roots) {
285 SkDQuad quad;
286 return SkIntersections::HorizontalIntercept(quad.set(a), y, roots);
287}
288
289static int quad_intercept_v(const SkPoint a[2], SkScalar , SkScalar x, double* roots) {
290 SkDQuad quad;
291 return SkIntersections::VerticalIntercept(quad.set(a), x, roots);
292}
293
294static int conic_intercept_h(const SkPoint a[2], SkScalar w, SkScalar y, double* roots) {
295 SkDConic conic;
296 return SkIntersections::HorizontalIntercept(conic.set(a, w), y, roots);
297}
298
299static int conic_intercept_v(const SkPoint a[2], SkScalar w, SkScalar x, double* roots) {
300 SkDConic conic;
301 return SkIntersections::VerticalIntercept(conic.set(a, w), x, roots);
302}
303
304static int cubic_intercept_h(const SkPoint a[3], SkScalar , SkScalar y, double* roots) {
305 SkDCubic cubic;
306 return cubic.set(a).horizontalIntersect(y, roots);
307}
308
309static int cubic_intercept_v(const SkPoint a[3], SkScalar , SkScalar x, double* roots) {
310 SkDCubic cubic;
311 return cubic.set(a).verticalIntersect(x, roots);
312}
313
314static int (* const CurveIntercept[])(const SkPoint[] , SkScalar , SkScalar , double* ) = {
315 NULL,
316 NULL,
317 line_intercept_h,
318 line_intercept_v,
319 quad_intercept_h,
320 quad_intercept_v,
321 conic_intercept_h,
322 conic_intercept_v,
323 cubic_intercept_h,
324 cubic_intercept_v,
325};
326
caryclark@google.com07393ca2013-04-08 11:47:37 +0000327#endif