blob: dc9cec97e46c569a6aa76b47f7d012942fbbd37a [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
caryclark55888e42016-07-18 10:01:36 -070067 SkDPoint conicTop(const SkPoint curve[3], SkScalar curveWeight,
caryclarkaec25102015-04-29 08:28:30 -070068 double s, double e, double* topT);
69 SkDPoint cubicTop(const SkPoint curve[4], SkScalar , double s, double e, double* topT);
caryclark55888e42016-07-18 10:01:36 -070070 void dump() const;
caryclark1049f122015-04-20 08:31:59 -070071 void dumpID(int ) const;
caryclarkaec25102015-04-29 08:28:30 -070072 SkDPoint lineTop(const SkPoint[2], SkScalar , double , double , double* topT);
caryclark55888e42016-07-18 10:01:36 -070073 double nearPoint(SkPath::Verb verb, const SkDPoint& xy, const SkDPoint& opp) const;
74 void offset(SkPath::Verb verb, const SkDVector& );
caryclarkaec25102015-04-29 08:28:30 -070075 SkDPoint quadTop(const SkPoint curve[3], SkScalar , double s, double e, double* topT);
76
caryclark55888e42016-07-18 10:01:36 -070077 void setConicBounds(const SkPoint curve[3], SkScalar curveWeight,
caryclarkaec25102015-04-29 08:28:30 -070078 double s, double e, SkPathOpsBounds* );
79 void setCubicBounds(const SkPoint curve[4], SkScalar ,
80 double s, double e, SkPathOpsBounds* );
caryclarkaec25102015-04-29 08:28:30 -070081 void setQuadBounds(const SkPoint curve[3], SkScalar ,
82 double s, double e, SkPathOpsBounds*);
caryclark1049f122015-04-20 08:31:59 -070083};
84
caryclarkaec25102015-04-29 08:28:30 -070085
caryclarkaec25102015-04-29 08:28:30 -070086extern SkDPoint (SkDCurve::* const Top[])(const SkPoint curve[], SkScalar cWeight,
87 double tStart, double tEnd, double* topT);
88
caryclark1049f122015-04-20 08:31:59 -070089static SkDPoint dline_xy_at_t(const SkPoint a[2], SkScalar , double t) {
caryclark@google.com07393ca2013-04-08 11:47:37 +000090 SkDLine line;
91 line.set(a);
caryclark@google.com4fdbb222013-07-23 15:27:41 +000092 return line.ptAtT(t);
caryclark@google.com07393ca2013-04-08 11:47:37 +000093}
94
caryclark1049f122015-04-20 08:31:59 -070095static SkDPoint dquad_xy_at_t(const SkPoint a[3], SkScalar , double t) {
caryclark@google.com07393ca2013-04-08 11:47:37 +000096 SkDQuad quad;
97 quad.set(a);
caryclark@google.com4fdbb222013-07-23 15:27:41 +000098 return quad.ptAtT(t);
caryclark@google.com07393ca2013-04-08 11:47:37 +000099}
100
caryclark1049f122015-04-20 08:31:59 -0700101static SkDPoint dconic_xy_at_t(const SkPoint a[3], SkScalar weight, double t) {
102 SkDConic conic;
103 conic.set(a, weight);
104 return conic.ptAtT(t);
105}
106
107static SkDPoint dcubic_xy_at_t(const SkPoint a[4], SkScalar , double t) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000108 SkDCubic cubic;
109 cubic.set(a);
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000110 return cubic.ptAtT(t);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000111}
112
caryclark1049f122015-04-20 08:31:59 -0700113static SkDPoint (* const CurveDPointAtT[])(const SkPoint[], SkScalar , double ) = {
halcanary96fcdcc2015-08-27 07:41:13 -0700114 nullptr,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000115 dline_xy_at_t,
116 dquad_xy_at_t,
caryclark1049f122015-04-20 08:31:59 -0700117 dconic_xy_at_t,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000118 dcubic_xy_at_t
119};
120
caryclark55888e42016-07-18 10:01:36 -0700121static SkDPoint ddline_xy_at_t(const SkDCurve& c, double t) {
122 return c.fLine.ptAtT(t);
123}
124
125static SkDPoint ddquad_xy_at_t(const SkDCurve& c, double t) {
126 return c.fQuad.ptAtT(t);
127}
128
129static SkDPoint ddconic_xy_at_t(const SkDCurve& c, double t) {
130 return c.fConic.ptAtT(t);
131}
132
133static SkDPoint ddcubic_xy_at_t(const SkDCurve& c, double t) {
134 return c.fCubic.ptAtT(t);
135}
136
137static SkDPoint (* const CurveDDPointAtT[])(const SkDCurve& , double ) = {
138 nullptr,
139 ddline_xy_at_t,
140 ddquad_xy_at_t,
141 ddconic_xy_at_t,
142 ddcubic_xy_at_t
143};
144
caryclark1049f122015-04-20 08:31:59 -0700145static SkPoint fline_xy_at_t(const SkPoint a[2], SkScalar weight, double t) {
146 return dline_xy_at_t(a, weight, t).asSkPoint();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000147}
148
caryclark1049f122015-04-20 08:31:59 -0700149static SkPoint fquad_xy_at_t(const SkPoint a[3], SkScalar weight, double t) {
150 return dquad_xy_at_t(a, weight, t).asSkPoint();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000151}
152
caryclark1049f122015-04-20 08:31:59 -0700153static SkPoint fconic_xy_at_t(const SkPoint a[3], SkScalar weight, double t) {
154 return dconic_xy_at_t(a, weight, t).asSkPoint();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000155}
156
caryclark1049f122015-04-20 08:31:59 -0700157static SkPoint fcubic_xy_at_t(const SkPoint a[4], SkScalar weight, double t) {
158 return dcubic_xy_at_t(a, weight, t).asSkPoint();
159}
160
161static SkPoint (* const CurvePointAtT[])(const SkPoint[], SkScalar , double ) = {
halcanary96fcdcc2015-08-27 07:41:13 -0700162 nullptr,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000163 fline_xy_at_t,
164 fquad_xy_at_t,
caryclark1049f122015-04-20 08:31:59 -0700165 fconic_xy_at_t,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000166 fcubic_xy_at_t
167};
168
caryclark1049f122015-04-20 08:31:59 -0700169static SkDVector dline_dxdy_at_t(const SkPoint a[2], SkScalar , double ) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000170 SkDLine line;
171 line.set(a);
172 return line[1] - line[0];
173}
174
caryclark1049f122015-04-20 08:31:59 -0700175static SkDVector dquad_dxdy_at_t(const SkPoint a[3], SkScalar , double t) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000176 SkDQuad quad;
177 quad.set(a);
178 return quad.dxdyAtT(t);
179}
180
caryclark1049f122015-04-20 08:31:59 -0700181static SkDVector dconic_dxdy_at_t(const SkPoint a[3], SkScalar weight, double t) {
182 SkDConic conic;
183 conic.set(a, weight);
184 return conic.dxdyAtT(t);
185}
186
187static SkDVector dcubic_dxdy_at_t(const SkPoint a[4], SkScalar , double t) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000188 SkDCubic cubic;
189 cubic.set(a);
190 return cubic.dxdyAtT(t);
191}
192
caryclark1049f122015-04-20 08:31:59 -0700193static SkDVector (* const CurveDSlopeAtT[])(const SkPoint[], SkScalar , double ) = {
halcanary96fcdcc2015-08-27 07:41:13 -0700194 nullptr,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000195 dline_dxdy_at_t,
196 dquad_dxdy_at_t,
caryclark1049f122015-04-20 08:31:59 -0700197 dconic_dxdy_at_t,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000198 dcubic_dxdy_at_t
199};
200
caryclark55888e42016-07-18 10:01:36 -0700201static SkDVector ddline_dxdy_at_t(const SkDCurve& c, double ) {
202 return c.fLine.fPts[1] - c.fLine.fPts[0];
203}
204
205static SkDVector ddquad_dxdy_at_t(const SkDCurve& c, double t) {
206 return c.fQuad.dxdyAtT(t);
207}
208
209static SkDVector ddconic_dxdy_at_t(const SkDCurve& c, double t) {
210 return c.fConic.dxdyAtT(t);
211}
212
213static SkDVector ddcubic_dxdy_at_t(const SkDCurve& c, double t) {
214 return c.fCubic.dxdyAtT(t);
215}
216
217static SkDVector (* const CurveDDSlopeAtT[])(const SkDCurve& , double ) = {
218 nullptr,
219 ddline_dxdy_at_t,
220 ddquad_dxdy_at_t,
221 ddconic_dxdy_at_t,
222 ddcubic_dxdy_at_t
223};
224
caryclark1049f122015-04-20 08:31:59 -0700225static SkVector fline_dxdy_at_t(const SkPoint a[2], SkScalar , double ) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000226 return a[1] - a[0];
227}
228
caryclark1049f122015-04-20 08:31:59 -0700229static SkVector fquad_dxdy_at_t(const SkPoint a[3], SkScalar weight, double t) {
230 return dquad_dxdy_at_t(a, weight, t).asSkVector();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000231}
232
caryclark1049f122015-04-20 08:31:59 -0700233static SkVector fconic_dxdy_at_t(const SkPoint a[3], SkScalar weight, double t) {
234 return dconic_dxdy_at_t(a, weight, t).asSkVector();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000235}
236
caryclark1049f122015-04-20 08:31:59 -0700237static SkVector fcubic_dxdy_at_t(const SkPoint a[4], SkScalar weight, double t) {
238 return dcubic_dxdy_at_t(a, weight, t).asSkVector();
239}
240
241static SkVector (* const CurveSlopeAtT[])(const SkPoint[], SkScalar , double ) = {
halcanary96fcdcc2015-08-27 07:41:13 -0700242 nullptr,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000243 fline_dxdy_at_t,
244 fquad_dxdy_at_t,
caryclark1049f122015-04-20 08:31:59 -0700245 fconic_dxdy_at_t,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000246 fcubic_dxdy_at_t
247};
248
caryclark1049f122015-04-20 08:31:59 -0700249static bool line_is_vertical(const SkPoint a[2], SkScalar , double startT, double endT) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000250 SkDLine line;
251 line.set(a);
caryclark@google.com4fdbb222013-07-23 15:27:41 +0000252 SkDPoint dst[2] = { line.ptAtT(startT), line.ptAtT(endT) };
caryclark@google.com07393ca2013-04-08 11:47:37 +0000253 return AlmostEqualUlps(dst[0].fX, dst[1].fX);
254}
255
caryclark1049f122015-04-20 08:31:59 -0700256static bool quad_is_vertical(const SkPoint a[3], SkScalar , double startT, double endT) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000257 SkDQuad quad;
258 quad.set(a);
259 SkDQuad dst = quad.subDivide(startT, endT);
260 return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX);
261}
262
caryclark1049f122015-04-20 08:31:59 -0700263static bool conic_is_vertical(const SkPoint a[3], SkScalar weight, double startT, double endT) {
264 SkDConic conic;
265 conic.set(a, weight);
266 SkDConic dst = conic.subDivide(startT, endT);
267 return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX);
268}
269
270static bool cubic_is_vertical(const SkPoint a[4], SkScalar , double startT, double endT) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000271 SkDCubic cubic;
272 cubic.set(a);
273 SkDCubic dst = cubic.subDivide(startT, endT);
274 return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX)
275 && AlmostEqualUlps(dst[2].fX, dst[3].fX);
276}
277
caryclark1049f122015-04-20 08:31:59 -0700278static bool (* const CurveIsVertical[])(const SkPoint[], SkScalar , double , double) = {
halcanary96fcdcc2015-08-27 07:41:13 -0700279 nullptr,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000280 line_is_vertical,
281 quad_is_vertical,
caryclark1049f122015-04-20 08:31:59 -0700282 conic_is_vertical,
caryclark@google.com07393ca2013-04-08 11:47:37 +0000283 cubic_is_vertical
284};
285
caryclark1049f122015-04-20 08:31:59 -0700286static void line_intersect_ray(const SkPoint a[2], SkScalar , const SkDLine& ray,
287 SkIntersections* i) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000288 SkDLine line;
289 line.set(a);
290 i->intersectRay(line, ray);
291}
292
caryclark1049f122015-04-20 08:31:59 -0700293static void quad_intersect_ray(const SkPoint a[3], SkScalar , const SkDLine& ray,
294 SkIntersections* i) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000295 SkDQuad quad;
296 quad.set(a);
297 i->intersectRay(quad, ray);
298}
299
caryclark1049f122015-04-20 08:31:59 -0700300static void conic_intersect_ray(const SkPoint a[3], SkScalar weight, const SkDLine& ray,
301 SkIntersections* i) {
302 SkDConic conic;
303 conic.set(a, weight);
304 i->intersectRay(conic, ray);
305}
306
307static void cubic_intersect_ray(const SkPoint a[4], SkScalar , const SkDLine& ray,
308 SkIntersections* i) {
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000309 SkDCubic cubic;
310 cubic.set(a);
311 i->intersectRay(cubic, ray);
312}
313
caryclark1049f122015-04-20 08:31:59 -0700314static void (* const CurveIntersectRay[])(const SkPoint[] , SkScalar , const SkDLine& ,
315 SkIntersections* ) = {
halcanary96fcdcc2015-08-27 07:41:13 -0700316 nullptr,
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000317 line_intersect_ray,
318 quad_intersect_ray,
caryclark1049f122015-04-20 08:31:59 -0700319 conic_intersect_ray,
commit-bot@chromium.org4431e772014-04-14 17:08:59 +0000320 cubic_intersect_ray
321};
322
caryclark55888e42016-07-18 10:01:36 -0700323static void dline_intersect_ray(const SkDCurve& c, const SkDLine& ray, SkIntersections* i) {
324 i->intersectRay(c.fLine, ray);
325}
326
327static void dquad_intersect_ray(const SkDCurve& c, const SkDLine& ray, SkIntersections* i) {
328 i->intersectRay(c.fQuad, ray);
329}
330
331static void dconic_intersect_ray(const SkDCurve& c, const SkDLine& ray, SkIntersections* i) {
332 i->intersectRay(c.fConic, ray);
333}
334
335static void dcubic_intersect_ray(const SkDCurve& c, const SkDLine& ray, SkIntersections* i) {
336 i->intersectRay(c.fCubic, ray);
337}
338
339static void (* const CurveDIntersectRay[])(const SkDCurve& , const SkDLine& , SkIntersections* ) = {
340 nullptr,
341 dline_intersect_ray,
342 dquad_intersect_ray,
343 dconic_intersect_ray,
344 dcubic_intersect_ray
345};
346
caryclark624637c2015-05-11 07:21:27 -0700347static int line_intercept_h(const SkPoint a[2], SkScalar , SkScalar y, double* roots) {
348 SkDLine line;
349 roots[0] = SkIntersections::HorizontalIntercept(line.set(a), y);
350 return between(0, roots[0], 1);
351}
352
353static int line_intercept_v(const SkPoint a[2], SkScalar , SkScalar x, double* roots) {
354 SkDLine line;
355 roots[0] = SkIntersections::VerticalIntercept(line.set(a), x);
356 return between(0, roots[0], 1);
357}
358
359static int quad_intercept_h(const SkPoint a[2], SkScalar , SkScalar y, double* roots) {
360 SkDQuad quad;
361 return SkIntersections::HorizontalIntercept(quad.set(a), y, roots);
362}
363
364static int quad_intercept_v(const SkPoint a[2], SkScalar , SkScalar x, double* roots) {
365 SkDQuad quad;
366 return SkIntersections::VerticalIntercept(quad.set(a), x, roots);
367}
368
369static int conic_intercept_h(const SkPoint a[2], SkScalar w, SkScalar y, double* roots) {
370 SkDConic conic;
371 return SkIntersections::HorizontalIntercept(conic.set(a, w), y, roots);
372}
373
374static int conic_intercept_v(const SkPoint a[2], SkScalar w, SkScalar x, double* roots) {
375 SkDConic conic;
376 return SkIntersections::VerticalIntercept(conic.set(a, w), x, roots);
377}
378
379static int cubic_intercept_h(const SkPoint a[3], SkScalar , SkScalar y, double* roots) {
380 SkDCubic cubic;
381 return cubic.set(a).horizontalIntersect(y, roots);
382}
383
384static int cubic_intercept_v(const SkPoint a[3], SkScalar , SkScalar x, double* roots) {
385 SkDCubic cubic;
386 return cubic.set(a).verticalIntersect(x, roots);
387}
388
389static int (* const CurveIntercept[])(const SkPoint[] , SkScalar , SkScalar , double* ) = {
halcanary96fcdcc2015-08-27 07:41:13 -0700390 nullptr,
391 nullptr,
caryclark624637c2015-05-11 07:21:27 -0700392 line_intercept_h,
393 line_intercept_v,
394 quad_intercept_h,
395 quad_intercept_v,
396 conic_intercept_h,
397 conic_intercept_v,
398 cubic_intercept_h,
399 cubic_intercept_v,
400};
401
caryclark@google.com07393ca2013-04-08 11:47:37 +0000402#endif