1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2012 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkPathOpsCurve_DEFINE
8*c8dee2aaSAndroid Build Coastguard Worker #define SkPathOpsCurve_DEFINE
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkIntersections.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsConic.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsCubic.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsLine.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsPoint.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsQuad.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsTypes.h"
22*c8dee2aaSAndroid Build Coastguard Worker
23*c8dee2aaSAndroid Build Coastguard Worker struct SkPathOpsBounds;
24*c8dee2aaSAndroid Build Coastguard Worker
25*c8dee2aaSAndroid Build Coastguard Worker struct SkOpCurve {
26*c8dee2aaSAndroid Build Coastguard Worker SkPoint fPts[4];
27*c8dee2aaSAndroid Build Coastguard Worker SkScalar fWeight;
SkDEBUGCODESkOpCurve28*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(SkPath::Verb fVerb;)
29*c8dee2aaSAndroid Build Coastguard Worker
30*c8dee2aaSAndroid Build Coastguard Worker const SkPoint& operator[](int n) const {
31*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(n >= 0 && n <= SkPathOpsVerbToPoints(fVerb));
32*c8dee2aaSAndroid Build Coastguard Worker return fPts[n];
33*c8dee2aaSAndroid Build Coastguard Worker }
34*c8dee2aaSAndroid Build Coastguard Worker
35*c8dee2aaSAndroid Build Coastguard Worker void dump() const;
36*c8dee2aaSAndroid Build Coastguard Worker
setSkOpCurve37*c8dee2aaSAndroid Build Coastguard Worker void set(const SkDQuad& quad) {
38*c8dee2aaSAndroid Build Coastguard Worker for (int index = 0; index < SkDQuad::kPointCount; ++index) {
39*c8dee2aaSAndroid Build Coastguard Worker fPts[index] = quad[index].asSkPoint();
40*c8dee2aaSAndroid Build Coastguard Worker }
41*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(fWeight = 1);
42*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(fVerb = SkPath::kQuad_Verb);
43*c8dee2aaSAndroid Build Coastguard Worker }
44*c8dee2aaSAndroid Build Coastguard Worker
setSkOpCurve45*c8dee2aaSAndroid Build Coastguard Worker void set(const SkDCubic& cubic) {
46*c8dee2aaSAndroid Build Coastguard Worker for (int index = 0; index < SkDCubic::kPointCount; ++index) {
47*c8dee2aaSAndroid Build Coastguard Worker fPts[index] = cubic[index].asSkPoint();
48*c8dee2aaSAndroid Build Coastguard Worker }
49*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(fWeight = 1);
50*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(fVerb = SkPath::kCubic_Verb);
51*c8dee2aaSAndroid Build Coastguard Worker }
52*c8dee2aaSAndroid Build Coastguard Worker
53*c8dee2aaSAndroid Build Coastguard Worker };
54*c8dee2aaSAndroid Build Coastguard Worker
55*c8dee2aaSAndroid Build Coastguard Worker struct SkDCurve {
56*c8dee2aaSAndroid Build Coastguard Worker union {
57*c8dee2aaSAndroid Build Coastguard Worker SkDLine fLine;
58*c8dee2aaSAndroid Build Coastguard Worker SkDQuad fQuad;
59*c8dee2aaSAndroid Build Coastguard Worker SkDConic fConic;
60*c8dee2aaSAndroid Build Coastguard Worker SkDCubic fCubic;
61*c8dee2aaSAndroid Build Coastguard Worker };
SkDEBUGCODESkDCurve62*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(SkPath::Verb fVerb;)
63*c8dee2aaSAndroid Build Coastguard Worker
64*c8dee2aaSAndroid Build Coastguard Worker const SkDPoint& operator[](int n) const {
65*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(n >= 0 && n <= SkPathOpsVerbToPoints(fVerb));
66*c8dee2aaSAndroid Build Coastguard Worker return fCubic[n];
67*c8dee2aaSAndroid Build Coastguard Worker }
68*c8dee2aaSAndroid Build Coastguard Worker
69*c8dee2aaSAndroid Build Coastguard Worker SkDPoint& operator[](int n) {
70*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(n >= 0 && n <= SkPathOpsVerbToPoints(fVerb));
71*c8dee2aaSAndroid Build Coastguard Worker return fCubic[n];
72*c8dee2aaSAndroid Build Coastguard Worker }
73*c8dee2aaSAndroid Build Coastguard Worker
74*c8dee2aaSAndroid Build Coastguard Worker SkDPoint conicTop(const SkPoint curve[3], SkScalar curveWeight,
75*c8dee2aaSAndroid Build Coastguard Worker double s, double e, double* topT);
76*c8dee2aaSAndroid Build Coastguard Worker SkDPoint cubicTop(const SkPoint curve[4], SkScalar , double s, double e, double* topT);
77*c8dee2aaSAndroid Build Coastguard Worker void dump() const;
78*c8dee2aaSAndroid Build Coastguard Worker void dumpID(int ) const;
79*c8dee2aaSAndroid Build Coastguard Worker SkDPoint lineTop(const SkPoint[2], SkScalar , double , double , double* topT);
80*c8dee2aaSAndroid Build Coastguard Worker double nearPoint(SkPath::Verb verb, const SkDPoint& xy, const SkDPoint& opp) const;
81*c8dee2aaSAndroid Build Coastguard Worker SkDPoint quadTop(const SkPoint curve[3], SkScalar , double s, double e, double* topT);
82*c8dee2aaSAndroid Build Coastguard Worker
83*c8dee2aaSAndroid Build Coastguard Worker void setConicBounds(const SkPoint curve[3], SkScalar curveWeight,
84*c8dee2aaSAndroid Build Coastguard Worker double s, double e, SkPathOpsBounds* );
85*c8dee2aaSAndroid Build Coastguard Worker void setCubicBounds(const SkPoint curve[4], SkScalar ,
86*c8dee2aaSAndroid Build Coastguard Worker double s, double e, SkPathOpsBounds* );
87*c8dee2aaSAndroid Build Coastguard Worker void setQuadBounds(const SkPoint curve[3], SkScalar ,
88*c8dee2aaSAndroid Build Coastguard Worker double s, double e, SkPathOpsBounds*);
89*c8dee2aaSAndroid Build Coastguard Worker };
90*c8dee2aaSAndroid Build Coastguard Worker
91*c8dee2aaSAndroid Build Coastguard Worker class SkDCurveSweep {
92*c8dee2aaSAndroid Build Coastguard Worker public:
isCurve()93*c8dee2aaSAndroid Build Coastguard Worker bool isCurve() const { return fIsCurve; }
isOrdered()94*c8dee2aaSAndroid Build Coastguard Worker bool isOrdered() const { return fOrdered; }
95*c8dee2aaSAndroid Build Coastguard Worker void setCurveHullSweep(SkPath::Verb verb);
96*c8dee2aaSAndroid Build Coastguard Worker
97*c8dee2aaSAndroid Build Coastguard Worker SkDCurve fCurve;
98*c8dee2aaSAndroid Build Coastguard Worker SkDVector fSweep[2];
99*c8dee2aaSAndroid Build Coastguard Worker private:
100*c8dee2aaSAndroid Build Coastguard Worker bool fIsCurve;
101*c8dee2aaSAndroid Build Coastguard Worker bool fOrdered; // cleared when a cubic's control point isn't between the sweep vectors
102*c8dee2aaSAndroid Build Coastguard Worker
103*c8dee2aaSAndroid Build Coastguard Worker };
104*c8dee2aaSAndroid Build Coastguard Worker
105*c8dee2aaSAndroid Build Coastguard Worker extern SkDPoint (SkDCurve::* const Top[])(const SkPoint curve[], SkScalar cWeight,
106*c8dee2aaSAndroid Build Coastguard Worker double tStart, double tEnd, double* topT);
107*c8dee2aaSAndroid Build Coastguard Worker
dline_xy_at_t(const SkPoint a[2],SkScalar,double t)108*c8dee2aaSAndroid Build Coastguard Worker static SkDPoint dline_xy_at_t(const SkPoint a[2], SkScalar , double t) {
109*c8dee2aaSAndroid Build Coastguard Worker SkDLine line;
110*c8dee2aaSAndroid Build Coastguard Worker line.set(a);
111*c8dee2aaSAndroid Build Coastguard Worker return line.ptAtT(t);
112*c8dee2aaSAndroid Build Coastguard Worker }
113*c8dee2aaSAndroid Build Coastguard Worker
dquad_xy_at_t(const SkPoint a[3],SkScalar,double t)114*c8dee2aaSAndroid Build Coastguard Worker static SkDPoint dquad_xy_at_t(const SkPoint a[3], SkScalar , double t) {
115*c8dee2aaSAndroid Build Coastguard Worker SkDQuad quad;
116*c8dee2aaSAndroid Build Coastguard Worker quad.set(a);
117*c8dee2aaSAndroid Build Coastguard Worker return quad.ptAtT(t);
118*c8dee2aaSAndroid Build Coastguard Worker }
119*c8dee2aaSAndroid Build Coastguard Worker
dconic_xy_at_t(const SkPoint a[3],SkScalar weight,double t)120*c8dee2aaSAndroid Build Coastguard Worker static SkDPoint dconic_xy_at_t(const SkPoint a[3], SkScalar weight, double t) {
121*c8dee2aaSAndroid Build Coastguard Worker SkDConic conic;
122*c8dee2aaSAndroid Build Coastguard Worker conic.set(a, weight);
123*c8dee2aaSAndroid Build Coastguard Worker return conic.ptAtT(t);
124*c8dee2aaSAndroid Build Coastguard Worker }
125*c8dee2aaSAndroid Build Coastguard Worker
dcubic_xy_at_t(const SkPoint a[4],SkScalar,double t)126*c8dee2aaSAndroid Build Coastguard Worker static SkDPoint dcubic_xy_at_t(const SkPoint a[4], SkScalar , double t) {
127*c8dee2aaSAndroid Build Coastguard Worker SkDCubic cubic;
128*c8dee2aaSAndroid Build Coastguard Worker cubic.set(a);
129*c8dee2aaSAndroid Build Coastguard Worker return cubic.ptAtT(t);
130*c8dee2aaSAndroid Build Coastguard Worker }
131*c8dee2aaSAndroid Build Coastguard Worker
132*c8dee2aaSAndroid Build Coastguard Worker static SkDPoint (* const CurveDPointAtT[])(const SkPoint[], SkScalar , double ) = {
133*c8dee2aaSAndroid Build Coastguard Worker nullptr,
134*c8dee2aaSAndroid Build Coastguard Worker dline_xy_at_t,
135*c8dee2aaSAndroid Build Coastguard Worker dquad_xy_at_t,
136*c8dee2aaSAndroid Build Coastguard Worker dconic_xy_at_t,
137*c8dee2aaSAndroid Build Coastguard Worker dcubic_xy_at_t
138*c8dee2aaSAndroid Build Coastguard Worker };
139*c8dee2aaSAndroid Build Coastguard Worker
ddline_xy_at_t(const SkDCurve & c,double t)140*c8dee2aaSAndroid Build Coastguard Worker static SkDPoint ddline_xy_at_t(const SkDCurve& c, double t) {
141*c8dee2aaSAndroid Build Coastguard Worker return c.fLine.ptAtT(t);
142*c8dee2aaSAndroid Build Coastguard Worker }
143*c8dee2aaSAndroid Build Coastguard Worker
ddquad_xy_at_t(const SkDCurve & c,double t)144*c8dee2aaSAndroid Build Coastguard Worker static SkDPoint ddquad_xy_at_t(const SkDCurve& c, double t) {
145*c8dee2aaSAndroid Build Coastguard Worker return c.fQuad.ptAtT(t);
146*c8dee2aaSAndroid Build Coastguard Worker }
147*c8dee2aaSAndroid Build Coastguard Worker
ddconic_xy_at_t(const SkDCurve & c,double t)148*c8dee2aaSAndroid Build Coastguard Worker static SkDPoint ddconic_xy_at_t(const SkDCurve& c, double t) {
149*c8dee2aaSAndroid Build Coastguard Worker return c.fConic.ptAtT(t);
150*c8dee2aaSAndroid Build Coastguard Worker }
151*c8dee2aaSAndroid Build Coastguard Worker
ddcubic_xy_at_t(const SkDCurve & c,double t)152*c8dee2aaSAndroid Build Coastguard Worker static SkDPoint ddcubic_xy_at_t(const SkDCurve& c, double t) {
153*c8dee2aaSAndroid Build Coastguard Worker return c.fCubic.ptAtT(t);
154*c8dee2aaSAndroid Build Coastguard Worker }
155*c8dee2aaSAndroid Build Coastguard Worker
156*c8dee2aaSAndroid Build Coastguard Worker static SkDPoint (* const CurveDDPointAtT[])(const SkDCurve& , double ) = {
157*c8dee2aaSAndroid Build Coastguard Worker nullptr,
158*c8dee2aaSAndroid Build Coastguard Worker ddline_xy_at_t,
159*c8dee2aaSAndroid Build Coastguard Worker ddquad_xy_at_t,
160*c8dee2aaSAndroid Build Coastguard Worker ddconic_xy_at_t,
161*c8dee2aaSAndroid Build Coastguard Worker ddcubic_xy_at_t
162*c8dee2aaSAndroid Build Coastguard Worker };
163*c8dee2aaSAndroid Build Coastguard Worker
fline_xy_at_t(const SkPoint a[2],SkScalar weight,double t)164*c8dee2aaSAndroid Build Coastguard Worker static SkPoint fline_xy_at_t(const SkPoint a[2], SkScalar weight, double t) {
165*c8dee2aaSAndroid Build Coastguard Worker return dline_xy_at_t(a, weight, t).asSkPoint();
166*c8dee2aaSAndroid Build Coastguard Worker }
167*c8dee2aaSAndroid Build Coastguard Worker
fquad_xy_at_t(const SkPoint a[3],SkScalar weight,double t)168*c8dee2aaSAndroid Build Coastguard Worker static SkPoint fquad_xy_at_t(const SkPoint a[3], SkScalar weight, double t) {
169*c8dee2aaSAndroid Build Coastguard Worker return dquad_xy_at_t(a, weight, t).asSkPoint();
170*c8dee2aaSAndroid Build Coastguard Worker }
171*c8dee2aaSAndroid Build Coastguard Worker
fconic_xy_at_t(const SkPoint a[3],SkScalar weight,double t)172*c8dee2aaSAndroid Build Coastguard Worker static SkPoint fconic_xy_at_t(const SkPoint a[3], SkScalar weight, double t) {
173*c8dee2aaSAndroid Build Coastguard Worker return dconic_xy_at_t(a, weight, t).asSkPoint();
174*c8dee2aaSAndroid Build Coastguard Worker }
175*c8dee2aaSAndroid Build Coastguard Worker
fcubic_xy_at_t(const SkPoint a[4],SkScalar weight,double t)176*c8dee2aaSAndroid Build Coastguard Worker static SkPoint fcubic_xy_at_t(const SkPoint a[4], SkScalar weight, double t) {
177*c8dee2aaSAndroid Build Coastguard Worker return dcubic_xy_at_t(a, weight, t).asSkPoint();
178*c8dee2aaSAndroid Build Coastguard Worker }
179*c8dee2aaSAndroid Build Coastguard Worker
180*c8dee2aaSAndroid Build Coastguard Worker static SkPoint (* const CurvePointAtT[])(const SkPoint[], SkScalar , double ) = {
181*c8dee2aaSAndroid Build Coastguard Worker nullptr,
182*c8dee2aaSAndroid Build Coastguard Worker fline_xy_at_t,
183*c8dee2aaSAndroid Build Coastguard Worker fquad_xy_at_t,
184*c8dee2aaSAndroid Build Coastguard Worker fconic_xy_at_t,
185*c8dee2aaSAndroid Build Coastguard Worker fcubic_xy_at_t
186*c8dee2aaSAndroid Build Coastguard Worker };
187*c8dee2aaSAndroid Build Coastguard Worker
dline_dxdy_at_t(const SkPoint a[2],SkScalar,double)188*c8dee2aaSAndroid Build Coastguard Worker static SkDVector dline_dxdy_at_t(const SkPoint a[2], SkScalar , double ) {
189*c8dee2aaSAndroid Build Coastguard Worker SkDLine line;
190*c8dee2aaSAndroid Build Coastguard Worker line.set(a);
191*c8dee2aaSAndroid Build Coastguard Worker return line[1] - line[0];
192*c8dee2aaSAndroid Build Coastguard Worker }
193*c8dee2aaSAndroid Build Coastguard Worker
dquad_dxdy_at_t(const SkPoint a[3],SkScalar,double t)194*c8dee2aaSAndroid Build Coastguard Worker static SkDVector dquad_dxdy_at_t(const SkPoint a[3], SkScalar , double t) {
195*c8dee2aaSAndroid Build Coastguard Worker SkDQuad quad;
196*c8dee2aaSAndroid Build Coastguard Worker quad.set(a);
197*c8dee2aaSAndroid Build Coastguard Worker return quad.dxdyAtT(t);
198*c8dee2aaSAndroid Build Coastguard Worker }
199*c8dee2aaSAndroid Build Coastguard Worker
dconic_dxdy_at_t(const SkPoint a[3],SkScalar weight,double t)200*c8dee2aaSAndroid Build Coastguard Worker static SkDVector dconic_dxdy_at_t(const SkPoint a[3], SkScalar weight, double t) {
201*c8dee2aaSAndroid Build Coastguard Worker SkDConic conic;
202*c8dee2aaSAndroid Build Coastguard Worker conic.set(a, weight);
203*c8dee2aaSAndroid Build Coastguard Worker return conic.dxdyAtT(t);
204*c8dee2aaSAndroid Build Coastguard Worker }
205*c8dee2aaSAndroid Build Coastguard Worker
dcubic_dxdy_at_t(const SkPoint a[4],SkScalar,double t)206*c8dee2aaSAndroid Build Coastguard Worker static SkDVector dcubic_dxdy_at_t(const SkPoint a[4], SkScalar , double t) {
207*c8dee2aaSAndroid Build Coastguard Worker SkDCubic cubic;
208*c8dee2aaSAndroid Build Coastguard Worker cubic.set(a);
209*c8dee2aaSAndroid Build Coastguard Worker return cubic.dxdyAtT(t);
210*c8dee2aaSAndroid Build Coastguard Worker }
211*c8dee2aaSAndroid Build Coastguard Worker
212*c8dee2aaSAndroid Build Coastguard Worker static SkDVector (* const CurveDSlopeAtT[])(const SkPoint[], SkScalar , double ) = {
213*c8dee2aaSAndroid Build Coastguard Worker nullptr,
214*c8dee2aaSAndroid Build Coastguard Worker dline_dxdy_at_t,
215*c8dee2aaSAndroid Build Coastguard Worker dquad_dxdy_at_t,
216*c8dee2aaSAndroid Build Coastguard Worker dconic_dxdy_at_t,
217*c8dee2aaSAndroid Build Coastguard Worker dcubic_dxdy_at_t
218*c8dee2aaSAndroid Build Coastguard Worker };
219*c8dee2aaSAndroid Build Coastguard Worker
ddline_dxdy_at_t(const SkDCurve & c,double)220*c8dee2aaSAndroid Build Coastguard Worker static SkDVector ddline_dxdy_at_t(const SkDCurve& c, double ) {
221*c8dee2aaSAndroid Build Coastguard Worker return c.fLine.fPts[1] - c.fLine.fPts[0];
222*c8dee2aaSAndroid Build Coastguard Worker }
223*c8dee2aaSAndroid Build Coastguard Worker
ddquad_dxdy_at_t(const SkDCurve & c,double t)224*c8dee2aaSAndroid Build Coastguard Worker static SkDVector ddquad_dxdy_at_t(const SkDCurve& c, double t) {
225*c8dee2aaSAndroid Build Coastguard Worker return c.fQuad.dxdyAtT(t);
226*c8dee2aaSAndroid Build Coastguard Worker }
227*c8dee2aaSAndroid Build Coastguard Worker
ddconic_dxdy_at_t(const SkDCurve & c,double t)228*c8dee2aaSAndroid Build Coastguard Worker static SkDVector ddconic_dxdy_at_t(const SkDCurve& c, double t) {
229*c8dee2aaSAndroid Build Coastguard Worker return c.fConic.dxdyAtT(t);
230*c8dee2aaSAndroid Build Coastguard Worker }
231*c8dee2aaSAndroid Build Coastguard Worker
ddcubic_dxdy_at_t(const SkDCurve & c,double t)232*c8dee2aaSAndroid Build Coastguard Worker static SkDVector ddcubic_dxdy_at_t(const SkDCurve& c, double t) {
233*c8dee2aaSAndroid Build Coastguard Worker return c.fCubic.dxdyAtT(t);
234*c8dee2aaSAndroid Build Coastguard Worker }
235*c8dee2aaSAndroid Build Coastguard Worker
236*c8dee2aaSAndroid Build Coastguard Worker static SkDVector (* const CurveDDSlopeAtT[])(const SkDCurve& , double ) = {
237*c8dee2aaSAndroid Build Coastguard Worker nullptr,
238*c8dee2aaSAndroid Build Coastguard Worker ddline_dxdy_at_t,
239*c8dee2aaSAndroid Build Coastguard Worker ddquad_dxdy_at_t,
240*c8dee2aaSAndroid Build Coastguard Worker ddconic_dxdy_at_t,
241*c8dee2aaSAndroid Build Coastguard Worker ddcubic_dxdy_at_t
242*c8dee2aaSAndroid Build Coastguard Worker };
243*c8dee2aaSAndroid Build Coastguard Worker
fline_dxdy_at_t(const SkPoint a[2],SkScalar,double)244*c8dee2aaSAndroid Build Coastguard Worker static SkVector fline_dxdy_at_t(const SkPoint a[2], SkScalar , double ) {
245*c8dee2aaSAndroid Build Coastguard Worker return a[1] - a[0];
246*c8dee2aaSAndroid Build Coastguard Worker }
247*c8dee2aaSAndroid Build Coastguard Worker
fquad_dxdy_at_t(const SkPoint a[3],SkScalar weight,double t)248*c8dee2aaSAndroid Build Coastguard Worker static SkVector fquad_dxdy_at_t(const SkPoint a[3], SkScalar weight, double t) {
249*c8dee2aaSAndroid Build Coastguard Worker return dquad_dxdy_at_t(a, weight, t).asSkVector();
250*c8dee2aaSAndroid Build Coastguard Worker }
251*c8dee2aaSAndroid Build Coastguard Worker
fconic_dxdy_at_t(const SkPoint a[3],SkScalar weight,double t)252*c8dee2aaSAndroid Build Coastguard Worker static SkVector fconic_dxdy_at_t(const SkPoint a[3], SkScalar weight, double t) {
253*c8dee2aaSAndroid Build Coastguard Worker return dconic_dxdy_at_t(a, weight, t).asSkVector();
254*c8dee2aaSAndroid Build Coastguard Worker }
255*c8dee2aaSAndroid Build Coastguard Worker
fcubic_dxdy_at_t(const SkPoint a[4],SkScalar weight,double t)256*c8dee2aaSAndroid Build Coastguard Worker static SkVector fcubic_dxdy_at_t(const SkPoint a[4], SkScalar weight, double t) {
257*c8dee2aaSAndroid Build Coastguard Worker return dcubic_dxdy_at_t(a, weight, t).asSkVector();
258*c8dee2aaSAndroid Build Coastguard Worker }
259*c8dee2aaSAndroid Build Coastguard Worker
260*c8dee2aaSAndroid Build Coastguard Worker static SkVector (* const CurveSlopeAtT[])(const SkPoint[], SkScalar , double ) = {
261*c8dee2aaSAndroid Build Coastguard Worker nullptr,
262*c8dee2aaSAndroid Build Coastguard Worker fline_dxdy_at_t,
263*c8dee2aaSAndroid Build Coastguard Worker fquad_dxdy_at_t,
264*c8dee2aaSAndroid Build Coastguard Worker fconic_dxdy_at_t,
265*c8dee2aaSAndroid Build Coastguard Worker fcubic_dxdy_at_t
266*c8dee2aaSAndroid Build Coastguard Worker };
267*c8dee2aaSAndroid Build Coastguard Worker
line_is_vertical(const SkPoint a[2],SkScalar,double startT,double endT)268*c8dee2aaSAndroid Build Coastguard Worker static bool line_is_vertical(const SkPoint a[2], SkScalar , double startT, double endT) {
269*c8dee2aaSAndroid Build Coastguard Worker SkDLine line;
270*c8dee2aaSAndroid Build Coastguard Worker line.set(a);
271*c8dee2aaSAndroid Build Coastguard Worker SkDPoint dst[2] = { line.ptAtT(startT), line.ptAtT(endT) };
272*c8dee2aaSAndroid Build Coastguard Worker return AlmostEqualUlps(dst[0].fX, dst[1].fX);
273*c8dee2aaSAndroid Build Coastguard Worker }
274*c8dee2aaSAndroid Build Coastguard Worker
quad_is_vertical(const SkPoint a[3],SkScalar,double startT,double endT)275*c8dee2aaSAndroid Build Coastguard Worker static bool quad_is_vertical(const SkPoint a[3], SkScalar , double startT, double endT) {
276*c8dee2aaSAndroid Build Coastguard Worker SkDQuad quad;
277*c8dee2aaSAndroid Build Coastguard Worker quad.set(a);
278*c8dee2aaSAndroid Build Coastguard Worker SkDQuad dst = quad.subDivide(startT, endT);
279*c8dee2aaSAndroid Build Coastguard Worker return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX);
280*c8dee2aaSAndroid Build Coastguard Worker }
281*c8dee2aaSAndroid Build Coastguard Worker
conic_is_vertical(const SkPoint a[3],SkScalar weight,double startT,double endT)282*c8dee2aaSAndroid Build Coastguard Worker static bool conic_is_vertical(const SkPoint a[3], SkScalar weight, double startT, double endT) {
283*c8dee2aaSAndroid Build Coastguard Worker SkDConic conic;
284*c8dee2aaSAndroid Build Coastguard Worker conic.set(a, weight);
285*c8dee2aaSAndroid Build Coastguard Worker SkDConic dst = conic.subDivide(startT, endT);
286*c8dee2aaSAndroid Build Coastguard Worker return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX);
287*c8dee2aaSAndroid Build Coastguard Worker }
288*c8dee2aaSAndroid Build Coastguard Worker
cubic_is_vertical(const SkPoint a[4],SkScalar,double startT,double endT)289*c8dee2aaSAndroid Build Coastguard Worker static bool cubic_is_vertical(const SkPoint a[4], SkScalar , double startT, double endT) {
290*c8dee2aaSAndroid Build Coastguard Worker SkDCubic cubic;
291*c8dee2aaSAndroid Build Coastguard Worker cubic.set(a);
292*c8dee2aaSAndroid Build Coastguard Worker SkDCubic dst = cubic.subDivide(startT, endT);
293*c8dee2aaSAndroid Build Coastguard Worker return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX)
294*c8dee2aaSAndroid Build Coastguard Worker && AlmostEqualUlps(dst[2].fX, dst[3].fX);
295*c8dee2aaSAndroid Build Coastguard Worker }
296*c8dee2aaSAndroid Build Coastguard Worker
297*c8dee2aaSAndroid Build Coastguard Worker static bool (* const CurveIsVertical[])(const SkPoint[], SkScalar , double , double) = {
298*c8dee2aaSAndroid Build Coastguard Worker nullptr,
299*c8dee2aaSAndroid Build Coastguard Worker line_is_vertical,
300*c8dee2aaSAndroid Build Coastguard Worker quad_is_vertical,
301*c8dee2aaSAndroid Build Coastguard Worker conic_is_vertical,
302*c8dee2aaSAndroid Build Coastguard Worker cubic_is_vertical
303*c8dee2aaSAndroid Build Coastguard Worker };
304*c8dee2aaSAndroid Build Coastguard Worker
line_intersect_ray(const SkPoint a[2],SkScalar,const SkDLine & ray,SkIntersections * i)305*c8dee2aaSAndroid Build Coastguard Worker static void line_intersect_ray(const SkPoint a[2], SkScalar , const SkDLine& ray,
306*c8dee2aaSAndroid Build Coastguard Worker SkIntersections* i) {
307*c8dee2aaSAndroid Build Coastguard Worker SkDLine line;
308*c8dee2aaSAndroid Build Coastguard Worker line.set(a);
309*c8dee2aaSAndroid Build Coastguard Worker i->intersectRay(line, ray);
310*c8dee2aaSAndroid Build Coastguard Worker }
311*c8dee2aaSAndroid Build Coastguard Worker
quad_intersect_ray(const SkPoint a[3],SkScalar,const SkDLine & ray,SkIntersections * i)312*c8dee2aaSAndroid Build Coastguard Worker static void quad_intersect_ray(const SkPoint a[3], SkScalar , const SkDLine& ray,
313*c8dee2aaSAndroid Build Coastguard Worker SkIntersections* i) {
314*c8dee2aaSAndroid Build Coastguard Worker SkDQuad quad;
315*c8dee2aaSAndroid Build Coastguard Worker quad.set(a);
316*c8dee2aaSAndroid Build Coastguard Worker i->intersectRay(quad, ray);
317*c8dee2aaSAndroid Build Coastguard Worker }
318*c8dee2aaSAndroid Build Coastguard Worker
conic_intersect_ray(const SkPoint a[3],SkScalar weight,const SkDLine & ray,SkIntersections * i)319*c8dee2aaSAndroid Build Coastguard Worker static void conic_intersect_ray(const SkPoint a[3], SkScalar weight, const SkDLine& ray,
320*c8dee2aaSAndroid Build Coastguard Worker SkIntersections* i) {
321*c8dee2aaSAndroid Build Coastguard Worker SkDConic conic;
322*c8dee2aaSAndroid Build Coastguard Worker conic.set(a, weight);
323*c8dee2aaSAndroid Build Coastguard Worker i->intersectRay(conic, ray);
324*c8dee2aaSAndroid Build Coastguard Worker }
325*c8dee2aaSAndroid Build Coastguard Worker
cubic_intersect_ray(const SkPoint a[4],SkScalar,const SkDLine & ray,SkIntersections * i)326*c8dee2aaSAndroid Build Coastguard Worker static void cubic_intersect_ray(const SkPoint a[4], SkScalar , const SkDLine& ray,
327*c8dee2aaSAndroid Build Coastguard Worker SkIntersections* i) {
328*c8dee2aaSAndroid Build Coastguard Worker SkDCubic cubic;
329*c8dee2aaSAndroid Build Coastguard Worker cubic.set(a);
330*c8dee2aaSAndroid Build Coastguard Worker i->intersectRay(cubic, ray);
331*c8dee2aaSAndroid Build Coastguard Worker }
332*c8dee2aaSAndroid Build Coastguard Worker
333*c8dee2aaSAndroid Build Coastguard Worker static void (* const CurveIntersectRay[])(const SkPoint[] , SkScalar , const SkDLine& ,
334*c8dee2aaSAndroid Build Coastguard Worker SkIntersections* ) = {
335*c8dee2aaSAndroid Build Coastguard Worker nullptr,
336*c8dee2aaSAndroid Build Coastguard Worker line_intersect_ray,
337*c8dee2aaSAndroid Build Coastguard Worker quad_intersect_ray,
338*c8dee2aaSAndroid Build Coastguard Worker conic_intersect_ray,
339*c8dee2aaSAndroid Build Coastguard Worker cubic_intersect_ray
340*c8dee2aaSAndroid Build Coastguard Worker };
341*c8dee2aaSAndroid Build Coastguard Worker
dline_intersect_ray(const SkDCurve & c,const SkDLine & ray,SkIntersections * i)342*c8dee2aaSAndroid Build Coastguard Worker static void dline_intersect_ray(const SkDCurve& c, const SkDLine& ray, SkIntersections* i) {
343*c8dee2aaSAndroid Build Coastguard Worker i->intersectRay(c.fLine, ray);
344*c8dee2aaSAndroid Build Coastguard Worker }
345*c8dee2aaSAndroid Build Coastguard Worker
dquad_intersect_ray(const SkDCurve & c,const SkDLine & ray,SkIntersections * i)346*c8dee2aaSAndroid Build Coastguard Worker static void dquad_intersect_ray(const SkDCurve& c, const SkDLine& ray, SkIntersections* i) {
347*c8dee2aaSAndroid Build Coastguard Worker i->intersectRay(c.fQuad, ray);
348*c8dee2aaSAndroid Build Coastguard Worker }
349*c8dee2aaSAndroid Build Coastguard Worker
dconic_intersect_ray(const SkDCurve & c,const SkDLine & ray,SkIntersections * i)350*c8dee2aaSAndroid Build Coastguard Worker static void dconic_intersect_ray(const SkDCurve& c, const SkDLine& ray, SkIntersections* i) {
351*c8dee2aaSAndroid Build Coastguard Worker i->intersectRay(c.fConic, ray);
352*c8dee2aaSAndroid Build Coastguard Worker }
353*c8dee2aaSAndroid Build Coastguard Worker
dcubic_intersect_ray(const SkDCurve & c,const SkDLine & ray,SkIntersections * i)354*c8dee2aaSAndroid Build Coastguard Worker static void dcubic_intersect_ray(const SkDCurve& c, const SkDLine& ray, SkIntersections* i) {
355*c8dee2aaSAndroid Build Coastguard Worker i->intersectRay(c.fCubic, ray);
356*c8dee2aaSAndroid Build Coastguard Worker }
357*c8dee2aaSAndroid Build Coastguard Worker
358*c8dee2aaSAndroid Build Coastguard Worker static void (* const CurveDIntersectRay[])(const SkDCurve& , const SkDLine& , SkIntersections* ) = {
359*c8dee2aaSAndroid Build Coastguard Worker nullptr,
360*c8dee2aaSAndroid Build Coastguard Worker dline_intersect_ray,
361*c8dee2aaSAndroid Build Coastguard Worker dquad_intersect_ray,
362*c8dee2aaSAndroid Build Coastguard Worker dconic_intersect_ray,
363*c8dee2aaSAndroid Build Coastguard Worker dcubic_intersect_ray
364*c8dee2aaSAndroid Build Coastguard Worker };
365*c8dee2aaSAndroid Build Coastguard Worker
line_intercept_h(const SkPoint a[2],SkScalar,SkScalar y,double * roots)366*c8dee2aaSAndroid Build Coastguard Worker static int line_intercept_h(const SkPoint a[2], SkScalar , SkScalar y, double* roots) {
367*c8dee2aaSAndroid Build Coastguard Worker if (a[0].fY == a[1].fY) {
368*c8dee2aaSAndroid Build Coastguard Worker return false;
369*c8dee2aaSAndroid Build Coastguard Worker }
370*c8dee2aaSAndroid Build Coastguard Worker SkDLine line;
371*c8dee2aaSAndroid Build Coastguard Worker roots[0] = SkIntersections::HorizontalIntercept(line.set(a), y);
372*c8dee2aaSAndroid Build Coastguard Worker return between(0, roots[0], 1);
373*c8dee2aaSAndroid Build Coastguard Worker }
374*c8dee2aaSAndroid Build Coastguard Worker
line_intercept_v(const SkPoint a[2],SkScalar,SkScalar x,double * roots)375*c8dee2aaSAndroid Build Coastguard Worker static int line_intercept_v(const SkPoint a[2], SkScalar , SkScalar x, double* roots) {
376*c8dee2aaSAndroid Build Coastguard Worker if (a[0].fX == a[1].fX) {
377*c8dee2aaSAndroid Build Coastguard Worker return false;
378*c8dee2aaSAndroid Build Coastguard Worker }
379*c8dee2aaSAndroid Build Coastguard Worker SkDLine line;
380*c8dee2aaSAndroid Build Coastguard Worker roots[0] = SkIntersections::VerticalIntercept(line.set(a), x);
381*c8dee2aaSAndroid Build Coastguard Worker return between(0, roots[0], 1);
382*c8dee2aaSAndroid Build Coastguard Worker }
383*c8dee2aaSAndroid Build Coastguard Worker
quad_intercept_h(const SkPoint a[2],SkScalar,SkScalar y,double * roots)384*c8dee2aaSAndroid Build Coastguard Worker static int quad_intercept_h(const SkPoint a[2], SkScalar , SkScalar y, double* roots) {
385*c8dee2aaSAndroid Build Coastguard Worker SkDQuad quad;
386*c8dee2aaSAndroid Build Coastguard Worker return SkIntersections::HorizontalIntercept(quad.set(a), y, roots);
387*c8dee2aaSAndroid Build Coastguard Worker }
388*c8dee2aaSAndroid Build Coastguard Worker
quad_intercept_v(const SkPoint a[2],SkScalar,SkScalar x,double * roots)389*c8dee2aaSAndroid Build Coastguard Worker static int quad_intercept_v(const SkPoint a[2], SkScalar , SkScalar x, double* roots) {
390*c8dee2aaSAndroid Build Coastguard Worker SkDQuad quad;
391*c8dee2aaSAndroid Build Coastguard Worker return SkIntersections::VerticalIntercept(quad.set(a), x, roots);
392*c8dee2aaSAndroid Build Coastguard Worker }
393*c8dee2aaSAndroid Build Coastguard Worker
conic_intercept_h(const SkPoint a[2],SkScalar w,SkScalar y,double * roots)394*c8dee2aaSAndroid Build Coastguard Worker static int conic_intercept_h(const SkPoint a[2], SkScalar w, SkScalar y, double* roots) {
395*c8dee2aaSAndroid Build Coastguard Worker SkDConic conic;
396*c8dee2aaSAndroid Build Coastguard Worker return SkIntersections::HorizontalIntercept(conic.set(a, w), y, roots);
397*c8dee2aaSAndroid Build Coastguard Worker }
398*c8dee2aaSAndroid Build Coastguard Worker
conic_intercept_v(const SkPoint a[2],SkScalar w,SkScalar x,double * roots)399*c8dee2aaSAndroid Build Coastguard Worker static int conic_intercept_v(const SkPoint a[2], SkScalar w, SkScalar x, double* roots) {
400*c8dee2aaSAndroid Build Coastguard Worker SkDConic conic;
401*c8dee2aaSAndroid Build Coastguard Worker return SkIntersections::VerticalIntercept(conic.set(a, w), x, roots);
402*c8dee2aaSAndroid Build Coastguard Worker }
403*c8dee2aaSAndroid Build Coastguard Worker
cubic_intercept_h(const SkPoint a[3],SkScalar,SkScalar y,double * roots)404*c8dee2aaSAndroid Build Coastguard Worker static int cubic_intercept_h(const SkPoint a[3], SkScalar , SkScalar y, double* roots) {
405*c8dee2aaSAndroid Build Coastguard Worker SkDCubic cubic;
406*c8dee2aaSAndroid Build Coastguard Worker return cubic.set(a).horizontalIntersect(y, roots);
407*c8dee2aaSAndroid Build Coastguard Worker }
408*c8dee2aaSAndroid Build Coastguard Worker
cubic_intercept_v(const SkPoint a[3],SkScalar,SkScalar x,double * roots)409*c8dee2aaSAndroid Build Coastguard Worker static int cubic_intercept_v(const SkPoint a[3], SkScalar , SkScalar x, double* roots) {
410*c8dee2aaSAndroid Build Coastguard Worker SkDCubic cubic;
411*c8dee2aaSAndroid Build Coastguard Worker return cubic.set(a).verticalIntersect(x, roots);
412*c8dee2aaSAndroid Build Coastguard Worker }
413*c8dee2aaSAndroid Build Coastguard Worker
414*c8dee2aaSAndroid Build Coastguard Worker static int (* const CurveIntercept[])(const SkPoint[] , SkScalar , SkScalar , double* ) = {
415*c8dee2aaSAndroid Build Coastguard Worker nullptr,
416*c8dee2aaSAndroid Build Coastguard Worker nullptr,
417*c8dee2aaSAndroid Build Coastguard Worker line_intercept_h,
418*c8dee2aaSAndroid Build Coastguard Worker line_intercept_v,
419*c8dee2aaSAndroid Build Coastguard Worker quad_intercept_h,
420*c8dee2aaSAndroid Build Coastguard Worker quad_intercept_v,
421*c8dee2aaSAndroid Build Coastguard Worker conic_intercept_h,
422*c8dee2aaSAndroid Build Coastguard Worker conic_intercept_v,
423*c8dee2aaSAndroid Build Coastguard Worker cubic_intercept_h,
424*c8dee2aaSAndroid Build Coastguard Worker cubic_intercept_v,
425*c8dee2aaSAndroid Build Coastguard Worker };
426*c8dee2aaSAndroid Build Coastguard Worker
427*c8dee2aaSAndroid Build Coastguard Worker #endif
428