1 /*
2 * Copyright (c) 2021 - 2024 the ThorVG project. All rights reserved.
3
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #include "../../lv_conf_internal.h"
24 #if LV_USE_THORVG_INTERNAL
25
26 #ifndef _TVG_MATH_H_
27 #define _TVG_MATH_H_
28
29 #define _USE_MATH_DEFINES
30
31 #include <float.h>
32 #include <cmath>
33 #include "tvgCommon.h"
34
35 namespace tvg
36 {
37
38 #define MATH_PI 3.14159265358979323846f
39 #define MATH_PI2 1.57079632679489661923f
40 #define FLOAT_EPSILON 1.0e-06f //1.192092896e-07f
41 #define PATH_KAPPA 0.552284f
42
43 /************************************************************************/
44 /* General functions */
45 /************************************************************************/
46
47 float atan2(float y, float x);
48
49
deg2rad(float degree)50 static inline float deg2rad(float degree)
51 {
52 return degree * (MATH_PI / 180.0f);
53 }
54
55
rad2deg(float radian)56 static inline float rad2deg(float radian)
57 {
58 return radian * (180.0f / MATH_PI);
59 }
60
61
zero(float a)62 static inline bool zero(float a)
63 {
64 return (fabsf(a) <= FLOAT_EPSILON) ? true : false;
65 }
66
67
equal(float a,float b)68 static inline bool equal(float a, float b)
69 {
70 return tvg::zero(a - b);
71 }
72
73
74 template <typename T>
clamp(T & v,const T & min,const T & max)75 static inline void clamp(T& v, const T& min, const T& max)
76 {
77 if (v < min) v = min;
78 else if (v > max) v = max;
79 }
80
81 /************************************************************************/
82 /* Matrix functions */
83 /************************************************************************/
84
85 void rotate(Matrix* m, float degree);
86 bool inverse(const Matrix* m, Matrix* out);
87 bool identity(const Matrix* m);
88 Matrix operator*(const Matrix& lhs, const Matrix& rhs);
89 bool operator==(const Matrix& lhs, const Matrix& rhs);
90
rightAngle(const Matrix & m)91 static inline bool rightAngle(const Matrix& m)
92 {
93 auto radian = fabsf(tvg::atan2(m.e21, m.e11));
94 if (radian < FLOAT_EPSILON || tvg::equal(radian, MATH_PI2) || tvg::equal(radian, MATH_PI)) return true;
95 return false;
96 }
97
98
skewed(const Matrix & m)99 static inline bool skewed(const Matrix& m)
100 {
101 return !tvg::zero(m.e21 + m.e12);
102 }
103
104
identity(Matrix * m)105 static inline void identity(Matrix* m)
106 {
107 m->e11 = 1.0f;
108 m->e12 = 0.0f;
109 m->e13 = 0.0f;
110 m->e21 = 0.0f;
111 m->e22 = 1.0f;
112 m->e23 = 0.0f;
113 m->e31 = 0.0f;
114 m->e32 = 0.0f;
115 m->e33 = 1.0f;
116 }
117
118
scale(Matrix * m,float sx,float sy)119 static inline void scale(Matrix* m, float sx, float sy)
120 {
121 m->e11 *= sx;
122 m->e22 *= sy;
123 }
124
125
scaleR(Matrix * m,float x,float y)126 static inline void scaleR(Matrix* m, float x, float y)
127 {
128 if (x != 1.0f) {
129 m->e11 *= x;
130 m->e21 *= x;
131 }
132 if (y != 1.0f) {
133 m->e22 *= y;
134 m->e12 *= y;
135 }
136 }
137
138
translate(Matrix * m,float x,float y)139 static inline void translate(Matrix* m, float x, float y)
140 {
141 m->e13 += x;
142 m->e23 += y;
143 }
144
145
translateR(Matrix * m,float x,float y)146 static inline void translateR(Matrix* m, float x, float y)
147 {
148 if (x == 0.0f && y == 0.0f) return;
149 m->e13 += (x * m->e11 + y * m->e12);
150 m->e23 += (x * m->e21 + y * m->e22);
151 }
152
153
154 static inline bool operator!=(const Matrix& lhs, const Matrix& rhs)
155 {
156 return !(lhs == rhs);
157 }
158
159
160 static inline void operator*=(Matrix& lhs, const Matrix& rhs)
161 {
162 lhs = lhs * rhs;
163 }
164
165
log(const Matrix & m)166 static inline void log(const Matrix& m)
167 {
168 TVGLOG("COMMON", "Matrix: [%f %f %f] [%f %f %f] [%f %f %f]", m.e11, m.e12, m.e13, m.e21, m.e22, m.e23, m.e31, m.e32, m.e33);
169 }
170
171
172 /************************************************************************/
173 /* Point functions */
174 /************************************************************************/
175
176 void operator*=(Point& pt, const Matrix& m);
177 Point operator*(const Point& pt, const Matrix& m);
178 Point normal(const Point& p1, const Point& p2);
179
cross(const Point & lhs,const Point & rhs)180 static inline float cross(const Point& lhs, const Point& rhs)
181 {
182 return lhs.x * rhs.y - rhs.x * lhs.y;
183 }
184
185
zero(const Point & p)186 static inline bool zero(const Point& p)
187 {
188 return tvg::zero(p.x) && tvg::zero(p.y);
189 }
190
191
length(const Point * a,const Point * b)192 static inline float length(const Point* a, const Point* b)
193 {
194 auto x = b->x - a->x;
195 auto y = b->y - a->y;
196
197 if (x < 0) x = -x;
198 if (y < 0) y = -y;
199
200 return (x > y) ? (x + 0.375f * y) : (y + 0.375f * x);
201 }
202
203
length(const Point & a)204 static inline float length(const Point& a)
205 {
206 return sqrtf(a.x * a.x + a.y * a.y);
207 }
208
209
210 static inline bool operator==(const Point& lhs, const Point& rhs)
211 {
212 return tvg::equal(lhs.x, rhs.x) && tvg::equal(lhs.y, rhs.y);
213 }
214
215
216 static inline bool operator!=(const Point& lhs, const Point& rhs)
217 {
218 return !(lhs == rhs);
219 }
220
221
222 static inline Point operator-(const Point& lhs, const Point& rhs)
223 {
224 return {lhs.x - rhs.x, lhs.y - rhs.y};
225 }
226
227
228 static inline Point operator+(const Point& lhs, const Point& rhs)
229 {
230 return {lhs.x + rhs.x, lhs.y + rhs.y};
231 }
232
233
234 static inline Point operator*(const Point& lhs, float rhs)
235 {
236 return {lhs.x * rhs, lhs.y * rhs};
237 }
238
239
240 static inline Point operator*(const float& lhs, const Point& rhs)
241 {
242 return {lhs * rhs.x, lhs * rhs.y};
243 }
244
245
246 static inline Point operator/(const Point& lhs, const float rhs)
247 {
248 return {lhs.x / rhs, lhs.y / rhs};
249 }
250
251
log(const Point & pt)252 static inline void log(const Point& pt)
253 {
254 TVGLOG("COMMON", "Point: [%f %f]", pt.x, pt.y);
255 }
256
257
258 /************************************************************************/
259 /* Line functions */
260 /************************************************************************/
261
262 struct Line
263 {
264 Point pt1;
265 Point pt2;
266
267 void split(float at, Line& left, Line& right) const;
268 float length() const;
269 };
270
271
272 /************************************************************************/
273 /* Bezier functions */
274 /************************************************************************/
275
276 struct Bezier
277 {
278 Point start;
279 Point ctrl1;
280 Point ctrl2;
281 Point end;
282
283 void split(float t, Bezier& left);
284 void split(Bezier& left, Bezier& right) const;
285 void split(float at, Bezier& left, Bezier& right) const;
286 float length() const;
287 float lengthApprox() const;
288 float at(float at, float length) const;
289 float atApprox(float at, float length) const;
290 Point at(float t) const;
291 float angle(float t) const;
292 };
293
294
295 /************************************************************************/
296 /* Interpolation functions */
297 /************************************************************************/
298
299 template <typename T>
lerp(const T & start,const T & end,float t)300 static inline T lerp(const T &start, const T &end, float t)
301 {
302 return static_cast<T>(start + (end - start) * t);
303 }
304
305 uint8_t lerp(const uint8_t &start, const uint8_t &end, float t);
306
307 }
308
309 #endif //_TVG_MATH_H_
310
311 #endif /* LV_USE_THORVG_INTERNAL */
312
313