FCT
载入中...
搜索中...
未找到
VertexPath.h
浏览该文件的文档.
1//
2// Created by Administrator on 2025/5/4.
3//
4
5#ifndef VERTEXPATH_H
6#define VERTEXPATH_H
8namespace FCT {
9
10
11constexpr float VertexCommand_End = -1.0;
12constexpr float VertexCommand_MoveTo = 1.0;
13constexpr float VertexCommand_LineTo = 2.0;
14constexpr float VertexCommand_BezierCurveTo = 3.0;
15constexpr float VertexCommand_SetColor = 4.0;
16constexpr float VertexCommand_ArcTo = 6.0;
17constexpr float VertexCommand_SetTransform = 5.0;
18constexpr float VertexCommand_BeginPath = 7.0;
19constexpr float VertexCommand_EndPath = 8.0;
20class VertexPath : public RefCount
21{
22protected:
23 std::vector<float> m_commandQueue;
29
31 };
32
33 void updateBounds(const Vec2& point) {
34 m_dirty = true;
35 if (!m_hasPoints) {
36 m_minBounds = point;
37 m_maxBounds = point;
38 m_hasPoints = true;
39 } else {
40 m_minBounds.x = std::min(m_minBounds.x, point.x);
41 m_minBounds.y = std::min(m_minBounds.y, point.y);
42 m_maxBounds.x = std::max(m_maxBounds.x, point.x);
43 m_maxBounds.y = std::max(m_maxBounds.y, point.y);
44 }
45 }
46 void unwrapperArcTo(Vec2 center, float beginAngle, float endAngle, float q) {
48 m_commandQueue.push_back(center.x);
49 m_commandQueue.push_back(center.y);
50 m_commandQueue.push_back(beginAngle);
51 m_commandQueue.push_back(endAngle);
52 m_commandQueue.push_back(q);
53
54 float radius = m_currentPos.distance(center);
55 updateBounds(Vec2(center.x - 2 * radius, center.y - 2 * radius));
56 updateBounds(Vec2(center.x + 2 * radius, center.y + 2 * radius));
57 }
58 bool m_dirty;
59public:
61 {
62 m_dirty = false;
63 }
65 void end()
66 {
68 }
70 transform = Mat3();
71 clear();
72 }
73
74 void clear() {
75 m_commandQueue.clear();
76 m_hasPoints = false;
77 m_minBounds = Vec2(std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
78 m_maxBounds = Vec2(std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest());
79 }
80
81 void beginPath(float sign = 1.0f) {
83 m_commandQueue.push_back(sign);
84 }
85
86 void endPath() {
88 }
89
90 void moveTo(Vec2 to) {
92 m_commandQueue.push_back(to.x);
93 m_commandQueue.push_back(to.y);
94 m_currentPos = to;
95 m_pathStart = to;
96 updateBounds(to);
97 }
98
99 void lineTo(Vec2 to) {
101 m_commandQueue.push_back(to.x);
102 m_commandQueue.push_back(to.y);
103 m_currentPos = to;
104 updateBounds(to);
105 }
106
107 void fillRect(Vec2 pos, Vec2 size) {
108 moveTo(pos);
109 lineTo(Vec2(pos.x, pos.y + size.y));
110 lineTo(Vec2(pos.x + size.x, pos.y + size.y));
111 lineTo(Vec2(pos.x + size.x, pos.y));
112 lineTo(pos);
113 }
114 void arcTo(Vec2 center, float beginAngle, float endAngle)
115 {
116 beginAngle = fmod(beginAngle, 2 * M_PI);
117 endAngle = fmod(endAngle, 2 * M_PI);
118 if (beginAngle < 0)
119 {
120 beginAngle += 2 * M_PI;
121 if (endAngle)
122 {
123 endAngle += 2 * M_PI;
124 endAngle = fmod(endAngle, 2 * M_PI);
125 }
126 else
127 {
128 endAngle += 2 * M_PI;
129 }
130 }
131 if (endAngle < 0)
132 {
133 if (beginAngle)
134 {
135 beginAngle += 2 * M_PI;
136 beginAngle = fmod(beginAngle, 2 * M_PI);
137 }
138 else
139 {
140 beginAngle += 2 * M_PI;
141 }
142 endAngle += 2 * M_PI;
143 }
144
145 if (abs(endAngle - beginAngle) < 1e-6 || abs(endAngle - beginAngle) >= 2 * M_PI - 1e-6)
146 {
147 for (int q = 1; q <= 4; ++q)
148 {
149 unwrapperArcTo(center, (q - 1) * M_PI_2, q * M_PI_2, q);
150 }
151 return;
152 }
153
154 bool isClockwise = endAngle < beginAngle;
155
156 if (isClockwise)
157 {
158 if (endAngle > beginAngle)
159 endAngle -= 2 * M_PI;
160
161 for (int q = 4; q >= 1; --q)
162 {
163 float quadrantStart = q * M_PI_2;
164 float quadrantEnd = (q - 1) * M_PI_2;
165
166 if (beginAngle > quadrantEnd && endAngle < quadrantStart)
167 {
168 float arcStart = std::min(beginAngle, quadrantStart);
169 float arcEnd = std::max(endAngle, quadrantEnd);
170 unwrapperArcTo(center, arcStart, arcEnd, q);
171 }
172
173 if (endAngle >= quadrantEnd)
174 break;
175 }
176 }
177 else
178 {
179 if (endAngle < beginAngle)
180 endAngle += 2 * M_PI;
181
182 for (int q = 1; q <= 4; ++q)
183 {
184 float quadrantStart = (q - 1) * M_PI_2;
185 float quadrantEnd = q * M_PI_2;
186
187 if (beginAngle < quadrantEnd && endAngle > quadrantStart)
188 {
189 float arcStart = std::max(beginAngle, quadrantStart);
190 float arcEnd = std::min(endAngle, quadrantEnd);
191 unwrapperArcTo(center, arcStart, arcEnd, q);
192 }
193
194 if (endAngle <= quadrantEnd)
195 break;
196 }
197 }
198 }
199
200 void curveTo(Vec2 control, Vec2 to) {
202 m_commandQueue.push_back(control.x);
203 m_commandQueue.push_back(control.y);
204 m_commandQueue.push_back(to.x);
205 m_commandQueue.push_back(to.y);
206
208 updateBounds(control);
209 updateBounds(to);
210
211 m_currentPos = to;
212 }
213 void curveTo(Vec2 control1, Vec2 control2, Vec2 to) {
214 Vec2 start = m_currentPos;
215
216 Vec2 q1 = start + (control1 - start) * 2.0f / 3.0f;
217 Vec2 q2 = to + (control2 - to) * 2.0f / 3.0f;
218 Vec2 m = (q1 + q2) * 0.5f;
219
221 m_commandQueue.push_back(q1.x);
222 m_commandQueue.push_back(q1.y);
223 m_commandQueue.push_back(m.x);
224 m_commandQueue.push_back(m.y);
225
227 m_commandQueue.push_back(q2.x);
228 m_commandQueue.push_back(q2.y);
229 m_commandQueue.push_back(to.x);
230 m_commandQueue.push_back(to.y);
231
232 updateBounds(start);
233 updateBounds(control1);
234 updateBounds(control2);
235 updateBounds(to);
236
237 m_currentPos = to;
238 }
239
240 void circle(Vec2 center, float radius) {
241 moveTo(Vec2(center.x + radius, center.y));
242 arcTo(center, 0, 2 * M_PI);
243
244 updateBounds(Vec2(center.x - 2 * radius, center.y - 2 * radius));
245 updateBounds(Vec2(center.x + 2 * radius, center.y + 2 * radius));
246 }
247
250 m_commandQueue.push_back(color.x);
251 m_commandQueue.push_back(color.y);
252 m_commandQueue.push_back(color.z);
253 m_commandQueue.push_back(color.w);
254 }
255
258 for (int i = 0; i < 16; i++) {
259 m_commandQueue.push_back(transform.m[i]);
260 }
261 }
262
263 void closePath() {
265 }
266
268 if (!m_hasPoints) {
269 return Vec4(0, 0, 0, 0);
270 }
271 return Vec4(m_minBounds.x, m_minBounds.y,
274 }
275
276 const std::vector<float>& getCommandQueue() const {
277 return m_commandQueue;
278 }
279};
280}
281
282
283#endif //VERTEXPATH_H
void fillRect(Vec2 pos, Vec2 size)
Vec4 getBoundingRect() const
void curveTo(Vec2 control1, Vec2 control2, Vec2 to)
void circle(Vec2 center, float radius)
void setTransform(const Mat4 &transform)
void beginPath(float sign=1.0f)
void arcTo(Vec2 center, float beginAngle, float endAngle)
const std::vector< float > & getCommandQueue() const
void setColor(Vec4 color)
void curveTo(Vec2 control, Vec2 to)
std::vector< float > m_commandQueue
void lineTo(Vec2 to)
void unwrapperArcTo(Vec2 center, float beginAngle, float endAngle, float q)
void updateBounds(const Vec2 &point)
void moveTo(Vec2 to)
constexpr float VertexCommand_LineTo
constexpr float VertexCommand_ArcTo
constexpr float VertexCommand_MoveTo
constexpr float VertexCommand_EndPath
constexpr float VertexCommand_End
constexpr float VertexCommand_BezierCurveTo
constexpr float VertexCommand_SetColor
constexpr float VertexCommand_BeginPath
constexpr float VertexCommand_SetTransform
float x
定义 Vec.h:10
float y
定义 Vec.h:10