1 /*
2  * Copyright 2015 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 
8 #ifndef SkPathOpsConic_DEFINED
9 #define SkPathOpsConic_DEFINED
10 
11 #include "src/pathops/SkPathOpsQuad.h"
12 
13 struct SkDConic {
14     static const int kPointCount = 3;
15     static const int kPointLast = kPointCount - 1;
16     static const int kMaxIntersections = 4;
17 
18     SkDQuad fPts;
19     SkScalar fWeight;
20 
collapsedSkDConic21     bool collapsed() const {
22         return fPts.collapsed();
23     }
24 
controlsInsideSkDConic25     bool controlsInside() const {
26         return fPts.controlsInside();
27     }
28 
debugInitSkDConic29     void debugInit() {
30         fPts.debugInit();
31         fWeight = 0;
32     }
33 
34     void debugSet(const SkDPoint* pts, SkScalar weight);
35 
flipSkDConic36     SkDConic flip() const {
37         SkDConic result = {{{fPts[2], fPts[1], fPts[0]}
38                 SkDEBUGPARAMS(fPts.fDebugGlobalState) }, fWeight};
39         return result;
40     }
41 
42 #ifdef SK_DEBUG
globalStateSkDConic43     SkOpGlobalState* globalState() const { return fPts.globalState(); }
44 #endif
45 
IsConicSkDConic46     static bool IsConic() { return true; }
47 
setSkDConic48     const SkDConic& set(const SkPoint pts[kPointCount], SkScalar weight
49             SkDEBUGPARAMS(SkOpGlobalState* state = nullptr)) {
50         fPts.set(pts  SkDEBUGPARAMS(state));
51         fWeight = weight;
52         return *this;
53     }
54 
55     const SkDPoint& operator[](int n) const { return fPts[n]; }
56     SkDPoint& operator[](int n) { return fPts[n]; }
57 
AddValidTsSkDConic58     static int AddValidTs(double s[], int realRoots, double* t) {
59         return SkDQuad::AddValidTs(s, realRoots, t);
60     }
61 
alignSkDConic62     void align(int endIndex, SkDPoint* dstPt) const {
63         fPts.align(endIndex, dstPt);
64     }
65 
66     SkDVector dxdyAtT(double t) const;
67     static int FindExtrema(const double src[], SkScalar weight, double tValue[1]);
68 
hullIntersectsSkDConic69     bool hullIntersects(const SkDQuad& quad, bool* isLinear) const {
70         return fPts.hullIntersects(quad, isLinear);
71     }
72 
hullIntersectsSkDConic73     bool hullIntersects(const SkDConic& conic, bool* isLinear) const {
74         return fPts.hullIntersects(conic.fPts, isLinear);
75     }
76 
77     bool hullIntersects(const SkDCubic& cubic, bool* isLinear) const;
78 
isLinearSkDConic79     bool isLinear(int startIndex, int endIndex) const {
80         return fPts.isLinear(startIndex, endIndex);
81     }
82 
maxIntersectionsSkDConic83     static int maxIntersections() { return kMaxIntersections; }
84 
monotonicInXSkDConic85     bool monotonicInX() const {
86         return fPts.monotonicInX();
87     }
88 
monotonicInYSkDConic89     bool monotonicInY() const {
90         return fPts.monotonicInY();
91     }
92 
otherPtsSkDConic93     void otherPts(int oddMan, const SkDPoint* endPt[2]) const {
94         fPts.otherPts(oddMan, endPt);
95     }
96 
pointCountSkDConic97     static int pointCount() { return kPointCount; }
pointLastSkDConic98     static int pointLast() { return kPointLast; }
99     SkDPoint ptAtT(double t) const;
100 
RootsRealSkDConic101     static int RootsReal(double A, double B, double C, double t[2]) {
102         return SkDQuad::RootsReal(A, B, C, t);
103     }
104 
RootsValidTSkDConic105     static int RootsValidT(const double A, const double B, const double C, double s[2]) {
106         return SkDQuad::RootsValidT(A, B, C, s);
107     }
108 
109     SkDConic subDivide(double t1, double t2) const;
subDivideSkDConic110     void subDivide(double t1, double t2, SkDConic* c) const { *c = this->subDivide(t1, t2); }
111 
SubDivideSkDConic112     static SkDConic SubDivide(const SkPoint a[kPointCount], SkScalar weight, double t1, double t2) {
113         SkDConic conic;
114         conic.set(a, weight);
115         return conic.subDivide(t1, t2);
116     }
117 
118     SkDPoint subDivide(const SkDPoint& a, const SkDPoint& c, double t1, double t2,
119             SkScalar* weight) const;
120 
SubDivideSkDConic121     static SkDPoint SubDivide(const SkPoint pts[kPointCount], SkScalar weight,
122                               const SkDPoint& a, const SkDPoint& c,
123                               double t1, double t2, SkScalar* newWeight) {
124         SkDConic conic;
125         conic.set(pts, weight);
126         return conic.subDivide(a, c, t1, t2, newWeight);
127     }
128 
129     // utilities callable by the user from the debugger when the implementation code is linked in
130     void dump() const;
131     void dumpID(int id) const;
132     void dumpInner() const;
133 
134 };
135 
136 class SkTConic : public SkTCurve {
137 public:
138     SkDConic fConic;
139 
SkTConic()140     SkTConic() {}
141 
SkTConic(const SkDConic & c)142     SkTConic(const SkDConic& c)
143         : fConic(c) {
144     }
145 
~SkTConic()146     ~SkTConic() override {}
147 
148     const SkDPoint& operator[](int n) const override { return fConic[n]; }
149     SkDPoint& operator[](int n) override { return fConic[n]; }
150 
collapsed()151     bool collapsed() const override { return fConic.collapsed(); }
controlsInside()152     bool controlsInside() const override { return fConic.controlsInside(); }
debugInit()153     void debugInit() override { return fConic.debugInit(); }
154 #if DEBUG_T_SECT
dumpID(int id)155     void dumpID(int id) const override { return fConic.dumpID(id); }
156 #endif
dxdyAtT(double t)157     SkDVector dxdyAtT(double t) const override { return fConic.dxdyAtT(t); }
158 #ifdef SK_DEBUG
globalState()159     SkOpGlobalState* globalState() const override { return fConic.globalState(); }
160 #endif
161     bool hullIntersects(const SkDQuad& quad, bool* isLinear) const override;
162 
hullIntersects(const SkDConic & conic,bool * isLinear)163     bool hullIntersects(const SkDConic& conic, bool* isLinear) const override {
164         return conic.hullIntersects(fConic, isLinear);
165     }
166 
167     bool hullIntersects(const SkDCubic& cubic, bool* isLinear) const override;
168 
hullIntersects(const SkTCurve & curve,bool * isLinear)169     bool hullIntersects(const SkTCurve& curve, bool* isLinear) const override {
170         return curve.hullIntersects(fConic, isLinear);
171     }
172 
173     int intersectRay(SkIntersections* i, const SkDLine& line) const override;
IsConic()174     bool IsConic() const override { return true; }
make(SkArenaAlloc & heap)175     SkTCurve* make(SkArenaAlloc& heap) const override { return heap.make<SkTConic>(); }
176 
maxIntersections()177     int maxIntersections() const override { return SkDConic::kMaxIntersections; }
178 
otherPts(int oddMan,const SkDPoint * endPt[2])179     void otherPts(int oddMan, const SkDPoint* endPt[2]) const override {
180         fConic.otherPts(oddMan, endPt);
181     }
182 
pointCount()183     int pointCount() const override { return SkDConic::kPointCount; }
pointLast()184     int pointLast() const override { return SkDConic::kPointLast; }
ptAtT(double t)185     SkDPoint ptAtT(double t) const override { return fConic.ptAtT(t); }
186     void setBounds(SkDRect* ) const override;
187 
subDivide(double t1,double t2,SkTCurve * curve)188     void subDivide(double t1, double t2, SkTCurve* curve) const override {
189         ((SkTConic*) curve)->fConic = fConic.subDivide(t1, t2);
190     }
191 };
192 
193 #endif
194