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 | |
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 | |
136 | class SkTConic : public SkTCurve { |
137 | public: |
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 | |