1 /*
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
10 #include "SkIntersections.h"
11
12 #ifndef SK_RELEASE
13 #include "SkPath.h"
14 #endif
15
16 struct SkPathOpsBounds;
17
18 struct 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
28 void dump() const;
29
setSkOpCurve30 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
setSkOpCurve38 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 }
45
46 };
47
48 struct 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
67 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);
70 void dumpID(int ) const;
71 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* );
78 void setQuadBounds(const SkPoint curve[3], SkScalar ,
79 double s, double e, SkPathOpsBounds*);
80 };
81
82
83 extern SkDPoint (SkDCurve::* const Top[])(const SkPoint curve[], SkScalar cWeight,
84 double tStart, double tEnd, double* topT);
85
dline_xy_at_t(const SkPoint a[2],SkScalar,double t)86 static SkDPoint dline_xy_at_t(const SkPoint a[2], SkScalar , double t) {
87 SkDLine line;
88 line.set(a);
89 return line.ptAtT(t);
90 }
91
dquad_xy_at_t(const SkPoint a[3],SkScalar,double t)92 static SkDPoint dquad_xy_at_t(const SkPoint a[3], SkScalar , double t) {
93 SkDQuad quad;
94 quad.set(a);
95 return quad.ptAtT(t);
96 }
97
dconic_xy_at_t(const SkPoint a[3],SkScalar weight,double t)98 static 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
dcubic_xy_at_t(const SkPoint a[4],SkScalar,double t)104 static SkDPoint dcubic_xy_at_t(const SkPoint a[4], SkScalar , double t) {
105 SkDCubic cubic;
106 cubic.set(a);
107 return cubic.ptAtT(t);
108 }
109
110 static SkDPoint (* const CurveDPointAtT[])(const SkPoint[], SkScalar , double ) = {
111 nullptr,
112 dline_xy_at_t,
113 dquad_xy_at_t,
114 dconic_xy_at_t,
115 dcubic_xy_at_t
116 };
117
fline_xy_at_t(const SkPoint a[2],SkScalar weight,double t)118 static SkPoint fline_xy_at_t(const SkPoint a[2], SkScalar weight, double t) {
119 return dline_xy_at_t(a, weight, t).asSkPoint();
120 }
121
fquad_xy_at_t(const SkPoint a[3],SkScalar weight,double t)122 static SkPoint fquad_xy_at_t(const SkPoint a[3], SkScalar weight, double t) {
123 return dquad_xy_at_t(a, weight, t).asSkPoint();
124 }
125
fconic_xy_at_t(const SkPoint a[3],SkScalar weight,double t)126 static SkPoint fconic_xy_at_t(const SkPoint a[3], SkScalar weight, double t) {
127 return dconic_xy_at_t(a, weight, t).asSkPoint();
128 }
129
fcubic_xy_at_t(const SkPoint a[4],SkScalar weight,double t)130 static 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
134 static SkPoint (* const CurvePointAtT[])(const SkPoint[], SkScalar , double ) = {
135 nullptr,
136 fline_xy_at_t,
137 fquad_xy_at_t,
138 fconic_xy_at_t,
139 fcubic_xy_at_t
140 };
141
dline_dxdy_at_t(const SkPoint a[2],SkScalar,double)142 static SkDVector dline_dxdy_at_t(const SkPoint a[2], SkScalar , double ) {
143 SkDLine line;
144 line.set(a);
145 return line[1] - line[0];
146 }
147
dquad_dxdy_at_t(const SkPoint a[3],SkScalar,double t)148 static SkDVector dquad_dxdy_at_t(const SkPoint a[3], SkScalar , double t) {
149 SkDQuad quad;
150 quad.set(a);
151 return quad.dxdyAtT(t);
152 }
153
dconic_dxdy_at_t(const SkPoint a[3],SkScalar weight,double t)154 static 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
dcubic_dxdy_at_t(const SkPoint a[4],SkScalar,double t)160 static SkDVector dcubic_dxdy_at_t(const SkPoint a[4], SkScalar , double t) {
161 SkDCubic cubic;
162 cubic.set(a);
163 return cubic.dxdyAtT(t);
164 }
165
166 static SkDVector (* const CurveDSlopeAtT[])(const SkPoint[], SkScalar , double ) = {
167 nullptr,
168 dline_dxdy_at_t,
169 dquad_dxdy_at_t,
170 dconic_dxdy_at_t,
171 dcubic_dxdy_at_t
172 };
173
fline_dxdy_at_t(const SkPoint a[2],SkScalar,double)174 static SkVector fline_dxdy_at_t(const SkPoint a[2], SkScalar , double ) {
175 return a[1] - a[0];
176 }
177
fquad_dxdy_at_t(const SkPoint a[3],SkScalar weight,double t)178 static SkVector fquad_dxdy_at_t(const SkPoint a[3], SkScalar weight, double t) {
179 return dquad_dxdy_at_t(a, weight, t).asSkVector();
180 }
181
fconic_dxdy_at_t(const SkPoint a[3],SkScalar weight,double t)182 static SkVector fconic_dxdy_at_t(const SkPoint a[3], SkScalar weight, double t) {
183 return dconic_dxdy_at_t(a, weight, t).asSkVector();
184 }
185
fcubic_dxdy_at_t(const SkPoint a[4],SkScalar weight,double t)186 static 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
190 static SkVector (* const CurveSlopeAtT[])(const SkPoint[], SkScalar , double ) = {
191 nullptr,
192 fline_dxdy_at_t,
193 fquad_dxdy_at_t,
194 fconic_dxdy_at_t,
195 fcubic_dxdy_at_t
196 };
197
line_is_vertical(const SkPoint a[2],SkScalar,double startT,double endT)198 static bool line_is_vertical(const SkPoint a[2], SkScalar , double startT, double endT) {
199 SkDLine line;
200 line.set(a);
201 SkDPoint dst[2] = { line.ptAtT(startT), line.ptAtT(endT) };
202 return AlmostEqualUlps(dst[0].fX, dst[1].fX);
203 }
204
quad_is_vertical(const SkPoint a[3],SkScalar,double startT,double endT)205 static bool quad_is_vertical(const SkPoint a[3], SkScalar , double startT, double endT) {
206 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
conic_is_vertical(const SkPoint a[3],SkScalar weight,double startT,double endT)212 static 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
cubic_is_vertical(const SkPoint a[4],SkScalar,double startT,double endT)219 static bool cubic_is_vertical(const SkPoint a[4], SkScalar , double startT, double endT) {
220 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
227 static bool (* const CurveIsVertical[])(const SkPoint[], SkScalar , double , double) = {
228 nullptr,
229 line_is_vertical,
230 quad_is_vertical,
231 conic_is_vertical,
232 cubic_is_vertical
233 };
234
line_intersect_ray(const SkPoint a[2],SkScalar,const SkDLine & ray,SkIntersections * i)235 static void line_intersect_ray(const SkPoint a[2], SkScalar , const SkDLine& ray,
236 SkIntersections* i) {
237 SkDLine line;
238 line.set(a);
239 i->intersectRay(line, ray);
240 }
241
quad_intersect_ray(const SkPoint a[3],SkScalar,const SkDLine & ray,SkIntersections * i)242 static void quad_intersect_ray(const SkPoint a[3], SkScalar , const SkDLine& ray,
243 SkIntersections* i) {
244 SkDQuad quad;
245 quad.set(a);
246 i->intersectRay(quad, ray);
247 }
248
conic_intersect_ray(const SkPoint a[3],SkScalar weight,const SkDLine & ray,SkIntersections * i)249 static 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
cubic_intersect_ray(const SkPoint a[4],SkScalar,const SkDLine & ray,SkIntersections * i)256 static void cubic_intersect_ray(const SkPoint a[4], SkScalar , const SkDLine& ray,
257 SkIntersections* i) {
258 SkDCubic cubic;
259 cubic.set(a);
260 i->intersectRay(cubic, ray);
261 }
262
263 static void (* const CurveIntersectRay[])(const SkPoint[] , SkScalar , const SkDLine& ,
264 SkIntersections* ) = {
265 nullptr,
266 line_intersect_ray,
267 quad_intersect_ray,
268 conic_intersect_ray,
269 cubic_intersect_ray
270 };
271
line_intercept_h(const SkPoint a[2],SkScalar,SkScalar y,double * roots)272 static 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
line_intercept_v(const SkPoint a[2],SkScalar,SkScalar x,double * roots)278 static 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
quad_intercept_h(const SkPoint a[2],SkScalar,SkScalar y,double * roots)284 static 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
quad_intercept_v(const SkPoint a[2],SkScalar,SkScalar x,double * roots)289 static 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
conic_intercept_h(const SkPoint a[2],SkScalar w,SkScalar y,double * roots)294 static 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
conic_intercept_v(const SkPoint a[2],SkScalar w,SkScalar x,double * roots)299 static 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
cubic_intercept_h(const SkPoint a[3],SkScalar,SkScalar y,double * roots)304 static 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
cubic_intercept_v(const SkPoint a[3],SkScalar,SkScalar x,double * roots)309 static 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
314 static int (* const CurveIntercept[])(const SkPoint[] , SkScalar , SkScalar , double* ) = {
315 nullptr,
316 nullptr,
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
327 #endif
328