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