xref: /aosp_15_r20/external/skia/src/pathops/SkPathOpsCubic.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkPathOpsCubic_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define SkPathOpsCubic_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker 
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 "include/private/base/SkMalloc.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkArenaAlloc.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsDebug.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsPoint.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/pathops/SkPathOpsTCurve.h"
20*c8dee2aaSAndroid Build Coastguard Worker 
21*c8dee2aaSAndroid Build Coastguard Worker class SkIntersections;
22*c8dee2aaSAndroid Build Coastguard Worker class SkOpGlobalState;
23*c8dee2aaSAndroid Build Coastguard Worker struct SkDConic;
24*c8dee2aaSAndroid Build Coastguard Worker struct SkDCubicPair;
25*c8dee2aaSAndroid Build Coastguard Worker struct SkDLine;
26*c8dee2aaSAndroid Build Coastguard Worker struct SkDQuad;
27*c8dee2aaSAndroid Build Coastguard Worker struct SkDRect;
28*c8dee2aaSAndroid Build Coastguard Worker 
29*c8dee2aaSAndroid Build Coastguard Worker struct SkDCubic {
30*c8dee2aaSAndroid Build Coastguard Worker     static const int kPointCount = 4;
31*c8dee2aaSAndroid Build Coastguard Worker     static const int kPointLast = kPointCount - 1;
32*c8dee2aaSAndroid Build Coastguard Worker     static const int kMaxIntersections = 9;
33*c8dee2aaSAndroid Build Coastguard Worker 
34*c8dee2aaSAndroid Build Coastguard Worker     enum SearchAxis {
35*c8dee2aaSAndroid Build Coastguard Worker         kXAxis,
36*c8dee2aaSAndroid Build Coastguard Worker         kYAxis
37*c8dee2aaSAndroid Build Coastguard Worker     };
38*c8dee2aaSAndroid Build Coastguard Worker 
collapsedSkDCubic39*c8dee2aaSAndroid Build Coastguard Worker     bool collapsed() const {
40*c8dee2aaSAndroid Build Coastguard Worker         return fPts[0].approximatelyEqual(fPts[1]) && fPts[0].approximatelyEqual(fPts[2])
41*c8dee2aaSAndroid Build Coastguard Worker                 && fPts[0].approximatelyEqual(fPts[3]);
42*c8dee2aaSAndroid Build Coastguard Worker     }
43*c8dee2aaSAndroid Build Coastguard Worker 
controlsInsideSkDCubic44*c8dee2aaSAndroid Build Coastguard Worker     bool controlsInside() const {
45*c8dee2aaSAndroid Build Coastguard Worker         SkDVector v01 = fPts[0] - fPts[1];
46*c8dee2aaSAndroid Build Coastguard Worker         SkDVector v02 = fPts[0] - fPts[2];
47*c8dee2aaSAndroid Build Coastguard Worker         SkDVector v03 = fPts[0] - fPts[3];
48*c8dee2aaSAndroid Build Coastguard Worker         SkDVector v13 = fPts[1] - fPts[3];
49*c8dee2aaSAndroid Build Coastguard Worker         SkDVector v23 = fPts[2] - fPts[3];
50*c8dee2aaSAndroid Build Coastguard Worker         return v03.dot(v01) > 0 && v03.dot(v02) > 0 && v03.dot(v13) > 0 && v03.dot(v23) > 0;
51*c8dee2aaSAndroid Build Coastguard Worker     }
52*c8dee2aaSAndroid Build Coastguard Worker 
IsConicSkDCubic53*c8dee2aaSAndroid Build Coastguard Worker     static bool IsConic() { return false; }
54*c8dee2aaSAndroid Build Coastguard Worker 
55*c8dee2aaSAndroid Build Coastguard Worker     const SkDPoint& operator[](int n) const { SkASSERT(n >= 0 && n < kPointCount); return fPts[n]; }
56*c8dee2aaSAndroid Build Coastguard Worker     SkDPoint& operator[](int n) { SkASSERT(n >= 0 && n < kPointCount); return fPts[n]; }
57*c8dee2aaSAndroid Build Coastguard Worker 
58*c8dee2aaSAndroid Build Coastguard Worker     void align(int endIndex, int ctrlIndex, SkDPoint* dstPt) const;
59*c8dee2aaSAndroid Build Coastguard Worker     double binarySearch(double min, double max, double axisIntercept, SearchAxis xAxis) const;
60*c8dee2aaSAndroid Build Coastguard Worker     double calcPrecision() const;
61*c8dee2aaSAndroid Build Coastguard Worker     SkDCubicPair chopAt(double t) const;
62*c8dee2aaSAndroid Build Coastguard Worker     static void Coefficients(const double* cubic, double* A, double* B, double* C, double* D);
63*c8dee2aaSAndroid Build Coastguard Worker     static int ComplexBreak(const SkPoint pts[4], SkScalar* t);
64*c8dee2aaSAndroid Build Coastguard Worker     int convexHull(char order[kPointCount]) const;
65*c8dee2aaSAndroid Build Coastguard Worker 
debugInitSkDCubic66*c8dee2aaSAndroid Build Coastguard Worker     void debugInit() {
67*c8dee2aaSAndroid Build Coastguard Worker         sk_bzero(fPts, sizeof(fPts));
68*c8dee2aaSAndroid Build Coastguard Worker     }
69*c8dee2aaSAndroid Build Coastguard Worker 
70*c8dee2aaSAndroid Build Coastguard Worker     void debugSet(const SkDPoint* pts);
71*c8dee2aaSAndroid Build Coastguard Worker 
72*c8dee2aaSAndroid Build Coastguard Worker     void dump() const;  // callable from the debugger when the implementation code is linked in
73*c8dee2aaSAndroid Build Coastguard Worker     void dumpID(int id) const;
74*c8dee2aaSAndroid Build Coastguard Worker     void dumpInner() const;
75*c8dee2aaSAndroid Build Coastguard Worker     SkDVector dxdyAtT(double t) const;
76*c8dee2aaSAndroid Build Coastguard Worker     bool endsAreExtremaInXOrY() const;
77*c8dee2aaSAndroid Build Coastguard Worker     static int FindExtrema(const double src[], double tValue[2]);
78*c8dee2aaSAndroid Build Coastguard Worker     int findInflections(double tValues[2]) const;
79*c8dee2aaSAndroid Build Coastguard Worker 
FindInflectionsSkDCubic80*c8dee2aaSAndroid Build Coastguard Worker     static int FindInflections(const SkPoint a[kPointCount], double tValues[2]) {
81*c8dee2aaSAndroid Build Coastguard Worker         SkDCubic cubic;
82*c8dee2aaSAndroid Build Coastguard Worker         return cubic.set(a).findInflections(tValues);
83*c8dee2aaSAndroid Build Coastguard Worker     }
84*c8dee2aaSAndroid Build Coastguard Worker 
85*c8dee2aaSAndroid Build Coastguard Worker     int findMaxCurvature(double tValues[]) const;
86*c8dee2aaSAndroid Build Coastguard Worker 
87*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
globalStateSkDCubic88*c8dee2aaSAndroid Build Coastguard Worker     SkOpGlobalState* globalState() const { return fDebugGlobalState; }
89*c8dee2aaSAndroid Build Coastguard Worker #endif
90*c8dee2aaSAndroid Build Coastguard Worker 
91*c8dee2aaSAndroid Build Coastguard Worker     bool hullIntersects(const SkDCubic& c2, bool* isLinear) const;
92*c8dee2aaSAndroid Build Coastguard Worker     bool hullIntersects(const SkDConic& c, bool* isLinear) const;
93*c8dee2aaSAndroid Build Coastguard Worker     bool hullIntersects(const SkDQuad& c2, bool* isLinear) const;
94*c8dee2aaSAndroid Build Coastguard Worker     bool hullIntersects(const SkDPoint* pts, int ptCount, bool* isLinear) const;
95*c8dee2aaSAndroid Build Coastguard Worker     bool isLinear(int startIndex, int endIndex) const;
maxIntersectionsSkDCubic96*c8dee2aaSAndroid Build Coastguard Worker     static int maxIntersections() { return kMaxIntersections; }
97*c8dee2aaSAndroid Build Coastguard Worker     bool monotonicInX() const;
98*c8dee2aaSAndroid Build Coastguard Worker     bool monotonicInY() const;
99*c8dee2aaSAndroid Build Coastguard Worker     void otherPts(int index, const SkDPoint* o1Pts[kPointCount - 1]) const;
pointCountSkDCubic100*c8dee2aaSAndroid Build Coastguard Worker     static int pointCount() { return kPointCount; }
pointLastSkDCubic101*c8dee2aaSAndroid Build Coastguard Worker     static int pointLast() { return kPointLast; }
102*c8dee2aaSAndroid Build Coastguard Worker     SkDPoint ptAtT(double t) const;
103*c8dee2aaSAndroid Build Coastguard Worker     static int RootsReal(double A, double B, double C, double D, double t[3]);
104*c8dee2aaSAndroid Build Coastguard Worker     static int RootsValidT(const double A, const double B, const double C, double D, double s[3]);
105*c8dee2aaSAndroid Build Coastguard Worker 
106*c8dee2aaSAndroid Build Coastguard Worker     int searchRoots(double extremes[6], int extrema, double axisIntercept,
107*c8dee2aaSAndroid Build Coastguard Worker                     SearchAxis xAxis, double* validRoots) const;
108*c8dee2aaSAndroid Build Coastguard Worker 
109*c8dee2aaSAndroid Build Coastguard Worker     bool toFloatPoints(SkPoint* ) const;
110*c8dee2aaSAndroid Build Coastguard Worker     /**
111*c8dee2aaSAndroid Build Coastguard Worker      *  Return the number of valid roots (0 < root < 1) for this cubic intersecting the
112*c8dee2aaSAndroid Build Coastguard Worker      *  specified horizontal line.
113*c8dee2aaSAndroid Build Coastguard Worker      */
114*c8dee2aaSAndroid Build Coastguard Worker     int horizontalIntersect(double yIntercept, double roots[3]) const;
115*c8dee2aaSAndroid Build Coastguard Worker     /**
116*c8dee2aaSAndroid Build Coastguard Worker      *  Return the number of valid roots (0 < root < 1) for this cubic intersecting the
117*c8dee2aaSAndroid Build Coastguard Worker      *  specified vertical line.
118*c8dee2aaSAndroid Build Coastguard Worker      */
119*c8dee2aaSAndroid Build Coastguard Worker     int verticalIntersect(double xIntercept, double roots[3]) const;
120*c8dee2aaSAndroid Build Coastguard Worker 
121*c8dee2aaSAndroid Build Coastguard Worker // add debug only global pointer so asserts can be skipped by fuzzers
setSkDCubic122*c8dee2aaSAndroid Build Coastguard Worker     const SkDCubic& set(const SkPoint pts[kPointCount]
123*c8dee2aaSAndroid Build Coastguard Worker             SkDEBUGPARAMS(SkOpGlobalState* state = nullptr)) {
124*c8dee2aaSAndroid Build Coastguard Worker         fPts[0] = pts[0];
125*c8dee2aaSAndroid Build Coastguard Worker         fPts[1] = pts[1];
126*c8dee2aaSAndroid Build Coastguard Worker         fPts[2] = pts[2];
127*c8dee2aaSAndroid Build Coastguard Worker         fPts[3] = pts[3];
128*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(fDebugGlobalState = state);
129*c8dee2aaSAndroid Build Coastguard Worker         return *this;
130*c8dee2aaSAndroid Build Coastguard Worker     }
131*c8dee2aaSAndroid Build Coastguard Worker 
132*c8dee2aaSAndroid Build Coastguard Worker     SkDCubic subDivide(double t1, double t2) const;
subDivideSkDCubic133*c8dee2aaSAndroid Build Coastguard Worker     void subDivide(double t1, double t2, SkDCubic* c) const { *c = this->subDivide(t1, t2); }
134*c8dee2aaSAndroid Build Coastguard Worker 
SubDivideSkDCubic135*c8dee2aaSAndroid Build Coastguard Worker     static SkDCubic SubDivide(const SkPoint a[kPointCount], double t1, double t2) {
136*c8dee2aaSAndroid Build Coastguard Worker         SkDCubic cubic;
137*c8dee2aaSAndroid Build Coastguard Worker         return cubic.set(a).subDivide(t1, t2);
138*c8dee2aaSAndroid Build Coastguard Worker     }
139*c8dee2aaSAndroid Build Coastguard Worker 
140*c8dee2aaSAndroid Build Coastguard Worker     void subDivide(const SkDPoint& a, const SkDPoint& d, double t1, double t2, SkDPoint p[2]) const;
141*c8dee2aaSAndroid Build Coastguard Worker 
SubDivideSkDCubic142*c8dee2aaSAndroid Build Coastguard Worker     static void SubDivide(const SkPoint pts[kPointCount], const SkDPoint& a, const SkDPoint& d, double t1,
143*c8dee2aaSAndroid Build Coastguard Worker                           double t2, SkDPoint p[2]) {
144*c8dee2aaSAndroid Build Coastguard Worker         SkDCubic cubic;
145*c8dee2aaSAndroid Build Coastguard Worker         cubic.set(pts).subDivide(a, d, t1, t2, p);
146*c8dee2aaSAndroid Build Coastguard Worker     }
147*c8dee2aaSAndroid Build Coastguard Worker 
148*c8dee2aaSAndroid Build Coastguard Worker     double top(const SkDCubic& dCurve, double startT, double endT, SkDPoint*topPt) const;
149*c8dee2aaSAndroid Build Coastguard Worker     SkDQuad toQuad() const;
150*c8dee2aaSAndroid Build Coastguard Worker 
151*c8dee2aaSAndroid Build Coastguard Worker     static const int gPrecisionUnit;
152*c8dee2aaSAndroid Build Coastguard Worker     SkDPoint fPts[kPointCount];
153*c8dee2aaSAndroid Build Coastguard Worker     SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState;)
154*c8dee2aaSAndroid Build Coastguard Worker };
155*c8dee2aaSAndroid Build Coastguard Worker 
156*c8dee2aaSAndroid Build Coastguard Worker /* Given the set [0, 1, 2, 3], and two of the four members, compute an XOR mask
157*c8dee2aaSAndroid Build Coastguard Worker    that computes the other two. Note that:
158*c8dee2aaSAndroid Build Coastguard Worker 
159*c8dee2aaSAndroid Build Coastguard Worker    one ^ two == 3 for (0, 3), (1, 2)
160*c8dee2aaSAndroid Build Coastguard Worker    one ^ two <  3 for (0, 1), (0, 2), (1, 3), (2, 3)
161*c8dee2aaSAndroid Build Coastguard Worker    3 - (one ^ two) is either 0, 1, or 2
162*c8dee2aaSAndroid Build Coastguard Worker    1 >> (3 - (one ^ two)) is either 0 or 1
163*c8dee2aaSAndroid Build Coastguard Worker thus:
164*c8dee2aaSAndroid Build Coastguard Worker    returned == 2 for (0, 3), (1, 2)
165*c8dee2aaSAndroid Build Coastguard Worker    returned == 3 for (0, 1), (0, 2), (1, 3), (2, 3)
166*c8dee2aaSAndroid Build Coastguard Worker given that:
167*c8dee2aaSAndroid Build Coastguard Worker    (0, 3) ^ 2 -> (2, 1)  (1, 2) ^ 2 -> (3, 0)
168*c8dee2aaSAndroid Build Coastguard Worker    (0, 1) ^ 3 -> (3, 2)  (0, 2) ^ 3 -> (3, 1)  (1, 3) ^ 3 -> (2, 0)  (2, 3) ^ 3 -> (1, 0)
169*c8dee2aaSAndroid Build Coastguard Worker */
other_two(int one,int two)170*c8dee2aaSAndroid Build Coastguard Worker inline int other_two(int one, int two) {
171*c8dee2aaSAndroid Build Coastguard Worker     return 1 >> (3 - (one ^ two)) ^ 3;
172*c8dee2aaSAndroid Build Coastguard Worker }
173*c8dee2aaSAndroid Build Coastguard Worker 
174*c8dee2aaSAndroid Build Coastguard Worker struct SkDCubicPair {
firstSkDCubicPair175*c8dee2aaSAndroid Build Coastguard Worker     SkDCubic first() const {
176*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
177*c8dee2aaSAndroid Build Coastguard Worker         SkDCubic result;
178*c8dee2aaSAndroid Build Coastguard Worker         result.debugSet(&pts[0]);
179*c8dee2aaSAndroid Build Coastguard Worker         return result;
180*c8dee2aaSAndroid Build Coastguard Worker #else
181*c8dee2aaSAndroid Build Coastguard Worker         return (const SkDCubic&) pts[0];
182*c8dee2aaSAndroid Build Coastguard Worker #endif
183*c8dee2aaSAndroid Build Coastguard Worker     }
secondSkDCubicPair184*c8dee2aaSAndroid Build Coastguard Worker     SkDCubic second() const {
185*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
186*c8dee2aaSAndroid Build Coastguard Worker         SkDCubic result;
187*c8dee2aaSAndroid Build Coastguard Worker         result.debugSet(&pts[3]);
188*c8dee2aaSAndroid Build Coastguard Worker         return result;
189*c8dee2aaSAndroid Build Coastguard Worker #else
190*c8dee2aaSAndroid Build Coastguard Worker         return (const SkDCubic&) pts[3];
191*c8dee2aaSAndroid Build Coastguard Worker #endif
192*c8dee2aaSAndroid Build Coastguard Worker     }
193*c8dee2aaSAndroid Build Coastguard Worker     SkDPoint pts[7];
194*c8dee2aaSAndroid Build Coastguard Worker };
195*c8dee2aaSAndroid Build Coastguard Worker 
196*c8dee2aaSAndroid Build Coastguard Worker class SkTCubic : public SkTCurve {
197*c8dee2aaSAndroid Build Coastguard Worker public:
198*c8dee2aaSAndroid Build Coastguard Worker     SkDCubic fCubic;
199*c8dee2aaSAndroid Build Coastguard Worker 
SkTCubic()200*c8dee2aaSAndroid Build Coastguard Worker     SkTCubic() {}
201*c8dee2aaSAndroid Build Coastguard Worker 
SkTCubic(const SkDCubic & c)202*c8dee2aaSAndroid Build Coastguard Worker     SkTCubic(const SkDCubic& c)
203*c8dee2aaSAndroid Build Coastguard Worker         : fCubic(c) {
204*c8dee2aaSAndroid Build Coastguard Worker     }
205*c8dee2aaSAndroid Build Coastguard Worker 
~SkTCubic()206*c8dee2aaSAndroid Build Coastguard Worker     ~SkTCubic() override {}
207*c8dee2aaSAndroid Build Coastguard Worker 
208*c8dee2aaSAndroid Build Coastguard Worker     const SkDPoint& operator[](int n) const override { return fCubic[n]; }
209*c8dee2aaSAndroid Build Coastguard Worker     SkDPoint& operator[](int n) override { return fCubic[n]; }
210*c8dee2aaSAndroid Build Coastguard Worker 
collapsed()211*c8dee2aaSAndroid Build Coastguard Worker     bool collapsed() const override { return fCubic.collapsed(); }
controlsInside()212*c8dee2aaSAndroid Build Coastguard Worker     bool controlsInside() const override { return fCubic.controlsInside(); }
debugInit()213*c8dee2aaSAndroid Build Coastguard Worker     void debugInit() override { return fCubic.debugInit(); }
214*c8dee2aaSAndroid Build Coastguard Worker #if DEBUG_T_SECT
dumpID(int id)215*c8dee2aaSAndroid Build Coastguard Worker     void dumpID(int id) const override { return fCubic.dumpID(id); }
216*c8dee2aaSAndroid Build Coastguard Worker #endif
dxdyAtT(double t)217*c8dee2aaSAndroid Build Coastguard Worker     SkDVector dxdyAtT(double t) const override { return fCubic.dxdyAtT(t); }
218*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
globalState()219*c8dee2aaSAndroid Build Coastguard Worker     SkOpGlobalState* globalState() const override { return fCubic.globalState(); }
220*c8dee2aaSAndroid Build Coastguard Worker #endif
221*c8dee2aaSAndroid Build Coastguard Worker     bool hullIntersects(const SkDQuad& quad, bool* isLinear) const override;
222*c8dee2aaSAndroid Build Coastguard Worker     bool hullIntersects(const SkDConic& conic, bool* isLinear) const override;
223*c8dee2aaSAndroid Build Coastguard Worker 
hullIntersects(const SkDCubic & cubic,bool * isLinear)224*c8dee2aaSAndroid Build Coastguard Worker     bool hullIntersects(const SkDCubic& cubic, bool* isLinear) const override {
225*c8dee2aaSAndroid Build Coastguard Worker         return cubic.hullIntersects(fCubic, isLinear);
226*c8dee2aaSAndroid Build Coastguard Worker     }
227*c8dee2aaSAndroid Build Coastguard Worker 
hullIntersects(const SkTCurve & curve,bool * isLinear)228*c8dee2aaSAndroid Build Coastguard Worker     bool hullIntersects(const SkTCurve& curve, bool* isLinear) const override {
229*c8dee2aaSAndroid Build Coastguard Worker         return curve.hullIntersects(fCubic, isLinear);
230*c8dee2aaSAndroid Build Coastguard Worker     }
231*c8dee2aaSAndroid Build Coastguard Worker 
232*c8dee2aaSAndroid Build Coastguard Worker     int intersectRay(SkIntersections* i, const SkDLine& line) const override;
IsConic()233*c8dee2aaSAndroid Build Coastguard Worker     bool IsConic() const override { return false; }
make(SkArenaAlloc & heap)234*c8dee2aaSAndroid Build Coastguard Worker     SkTCurve* make(SkArenaAlloc& heap) const override { return heap.make<SkTCubic>(); }
235*c8dee2aaSAndroid Build Coastguard Worker 
maxIntersections()236*c8dee2aaSAndroid Build Coastguard Worker     int maxIntersections() const override { return SkDCubic::kMaxIntersections; }
237*c8dee2aaSAndroid Build Coastguard Worker 
otherPts(int oddMan,const SkDPoint * endPt[2])238*c8dee2aaSAndroid Build Coastguard Worker     void otherPts(int oddMan, const SkDPoint* endPt[2]) const override {
239*c8dee2aaSAndroid Build Coastguard Worker         fCubic.otherPts(oddMan, endPt);
240*c8dee2aaSAndroid Build Coastguard Worker     }
241*c8dee2aaSAndroid Build Coastguard Worker 
pointCount()242*c8dee2aaSAndroid Build Coastguard Worker     int pointCount() const override { return SkDCubic::kPointCount; }
pointLast()243*c8dee2aaSAndroid Build Coastguard Worker     int pointLast() const override { return SkDCubic::kPointLast; }
ptAtT(double t)244*c8dee2aaSAndroid Build Coastguard Worker     SkDPoint ptAtT(double t) const override { return fCubic.ptAtT(t); }
245*c8dee2aaSAndroid Build Coastguard Worker     void setBounds(SkDRect* ) const override;
246*c8dee2aaSAndroid Build Coastguard Worker 
subDivide(double t1,double t2,SkTCurve * curve)247*c8dee2aaSAndroid Build Coastguard Worker     void subDivide(double t1, double t2, SkTCurve* curve) const override {
248*c8dee2aaSAndroid Build Coastguard Worker         ((SkTCubic*) curve)->fCubic = fCubic.subDivide(t1, t2);
249*c8dee2aaSAndroid Build Coastguard Worker     }
250*c8dee2aaSAndroid Build Coastguard Worker };
251*c8dee2aaSAndroid Build Coastguard Worker 
252*c8dee2aaSAndroid Build Coastguard Worker #endif
253