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
13struct 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
21 bool collapsed() const {
22 return fPts.collapsed();
23 }
24
25 bool controlsInside() const {
26 return fPts.controlsInside();
27 }
28
29 void debugInit() {
30 fPts.debugInit();
31 fWeight = 0;
32 }
33
34 void debugSet(const SkDPoint* pts, SkScalar weight);
35
36 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
43 SkOpGlobalState* globalState() const { return fPts.globalState(); }
44#endif
45
46 static bool IsConic() { return true; }
47
48 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
58 static int AddValidTs(double s[], int realRoots, double* t) {
59 return SkDQuad::AddValidTs(s, realRoots, t);
60 }
61
62 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
69 bool hullIntersects(const SkDQuad& quad, bool* isLinear) const {
70 return fPts.hullIntersects(quad, isLinear);
71 }
72
73 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
79 bool isLinear(int startIndex, int endIndex) const {
80 return fPts.isLinear(startIndex, endIndex);
81 }
82
83 static int maxIntersections() { return kMaxIntersections; }
84
85 bool monotonicInX() const {
86 return fPts.monotonicInX();
87 }
88
89 bool monotonicInY() const {
90 return fPts.monotonicInY();
91 }
92
93 void otherPts(int oddMan, const SkDPoint* endPt[2]) const {
94 fPts.otherPts(oddMan, endPt);
95 }
96
97 static int pointCount() { return kPointCount; }
98 static int pointLast() { return kPointLast; }
99 SkDPoint ptAtT(double t) const;
100
101 static int RootsReal(double A, double B, double C, double t[2]) {
102 return SkDQuad::RootsReal(A, B, C, t);
103 }
104
105 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;
110 void subDivide(double t1, double t2, SkDConic* c) const { *c = this->subDivide(t1, t2); }
111
112 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
121 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
136class SkTConic : public SkTCurve {
137public:
138 SkDConic fConic;
139
140 SkTConic() {}
141
142 SkTConic(const SkDConic& c)
143 : fConic(c) {
144 }
145
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
151 bool collapsed() const override { return fConic.collapsed(); }
152 bool controlsInside() const override { return fConic.controlsInside(); }
153 void debugInit() override { return fConic.debugInit(); }
154#if DEBUG_T_SECT
155 void dumpID(int id) const override { return fConic.dumpID(id); }
156#endif
157 SkDVector dxdyAtT(double t) const override { return fConic.dxdyAtT(t); }
158#ifdef SK_DEBUG
159 SkOpGlobalState* globalState() const override { return fConic.globalState(); }
160#endif
161 bool hullIntersects(const SkDQuad& quad, bool* isLinear) const override;
162
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
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;
174 bool IsConic() const override { return true; }
175 SkTCurve* make(SkArenaAlloc& heap) const override { return heap.make<SkTConic>(); }
176
177 int maxIntersections() const override { return SkDConic::kMaxIntersections; }
178
179 void otherPts(int oddMan, const SkDPoint* endPt[2]) const override {
180 fConic.otherPts(oddMan, endPt);
181 }
182
183 int pointCount() const override { return SkDConic::kPointCount; }
184 int pointLast() const override { return SkDConic::kPointLast; }
185 SkDPoint ptAtT(double t) const override { return fConic.ptAtT(t); }
186 void setBounds(SkDRect* ) const override;
187
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