1 /**
2 * @file lv_matrix.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9
10 #include "lv_matrix.h"
11
12 #if LV_USE_MATRIX
13
14 #include "../stdlib/lv_string.h"
15 #include "lv_math.h"
16 #include <math.h>
17 /*********************
18 * DEFINES
19 *********************/
20 #ifndef M_PI
21 #define M_PI 3.1415926f
22 #endif
23
24 /**********************
25 * TYPEDEFS
26 **********************/
27
28 /**********************
29 * STATIC PROTOTYPES
30 **********************/
31
32 /**********************
33 * STATIC VARIABLES
34 **********************/
35
36 /**********************
37 * MACROS
38 **********************/
39
40 /**********************
41 * GLOBAL FUNCTIONS
42 **********************/
43
lv_matrix_identity(lv_matrix_t * matrix)44 void lv_matrix_identity(lv_matrix_t * matrix)
45 {
46 matrix->m[0][0] = 1.0f;
47 matrix->m[0][1] = 0.0f;
48 matrix->m[0][2] = 0.0f;
49 matrix->m[1][0] = 0.0f;
50 matrix->m[1][1] = 1.0f;
51 matrix->m[1][2] = 0.0f;
52 matrix->m[2][0] = 0.0f;
53 matrix->m[2][1] = 0.0f;
54 matrix->m[2][2] = 1.0f;
55 }
56
lv_matrix_translate(lv_matrix_t * matrix,float dx,float dy)57 void lv_matrix_translate(lv_matrix_t * matrix, float dx, float dy)
58 {
59 if(lv_matrix_is_identity_or_translation(matrix)) {
60 /*optimization for matrix translation.*/
61 matrix->m[0][2] += dx;
62 matrix->m[1][2] += dy;
63 return;
64 }
65
66 lv_matrix_t tlm = {{
67 {1.0f, 0.0f, dx},
68 {0.0f, 1.0f, dy},
69 {0.0f, 0.0f, 1.0f},
70 }
71 };
72
73 lv_matrix_multiply(matrix, &tlm);
74 }
75
lv_matrix_scale(lv_matrix_t * matrix,float scale_x,float scale_y)76 void lv_matrix_scale(lv_matrix_t * matrix, float scale_x, float scale_y)
77 {
78 lv_matrix_t scm = {{
79 {scale_x, 0.0f, 0.0f},
80 {0.0f, scale_y, 0.0f},
81 {0.0f, 0.0f, 1.0f},
82 }
83 };
84
85 lv_matrix_multiply(matrix, &scm);
86 }
87
lv_matrix_rotate(lv_matrix_t * matrix,float degree)88 void lv_matrix_rotate(lv_matrix_t * matrix, float degree)
89 {
90 float radian = degree / 180.0f * (float)M_PI;
91 float cos_r = cosf(radian);
92 float sin_r = sinf(radian);
93
94 lv_matrix_t rtm = {{
95 {cos_r, -sin_r, 0.0f},
96 {sin_r, cos_r, 0.0f},
97 {0.0f, 0.0f, 1.0f},
98 }
99 };
100
101 lv_matrix_multiply(matrix, &rtm);
102 }
103
lv_matrix_skew(lv_matrix_t * matrix,float skew_x,float skew_y)104 void lv_matrix_skew(lv_matrix_t * matrix, float skew_x, float skew_y)
105 {
106 float rskew_x = skew_x / 180.0f * (float)M_PI;
107 float rskew_y = skew_y / 180.0f * (float)M_PI;
108 float tan_x = tanf(rskew_x);
109 float tan_y = tanf(rskew_y);
110
111 lv_matrix_t skm = {{
112 {1.0f, tan_x, 0.0f},
113 {tan_y, 1.0f, 0.0f},
114 {0.0f, 0.0f, 1.0f},
115 }
116 };
117
118 lv_matrix_multiply(matrix, &skm);
119 }
120
lv_matrix_multiply(lv_matrix_t * matrix,const lv_matrix_t * mul)121 void lv_matrix_multiply(lv_matrix_t * matrix, const lv_matrix_t * mul)
122 {
123 /*TODO: use NEON to optimize this function on ARM architecture.*/
124 lv_matrix_t tmp;
125
126 for(int y = 0; y < 3; y++) {
127 for(int x = 0; x < 3; x++) {
128 tmp.m[y][x] = (matrix->m[y][0] * mul->m[0][x])
129 + (matrix->m[y][1] * mul->m[1][x])
130 + (matrix->m[y][2] * mul->m[2][x]);
131 }
132 }
133
134 lv_memcpy(matrix, &tmp, sizeof(lv_matrix_t));
135 }
136
lv_matrix_inverse(lv_matrix_t * matrix,const lv_matrix_t * m)137 bool lv_matrix_inverse(lv_matrix_t * matrix, const lv_matrix_t * m)
138 {
139 float det00, det01, det02;
140 float d;
141 bool is_affine;
142
143 /* Test for identity matrix. */
144 if(m == NULL) {
145 lv_matrix_identity(matrix);
146 return true;
147 }
148
149 det00 = (m->m[1][1] * m->m[2][2]) - (m->m[2][1] * m->m[1][2]);
150 det01 = (m->m[2][0] * m->m[1][2]) - (m->m[1][0] * m->m[2][2]);
151 det02 = (m->m[1][0] * m->m[2][1]) - (m->m[2][0] * m->m[1][1]);
152
153 /* Compute determinant. */
154 d = (m->m[0][0] * det00) + (m->m[0][1] * det01) + (m->m[0][2] * det02);
155
156 /* Return 0 if there is no inverse matrix. */
157 if(d == 0.0f)
158 return false;
159
160 /* Compute reciprocal. */
161 d = 1.0f / d;
162
163 /* Determine if the matrix is affine. */
164 is_affine = (m->m[2][0] == 0.0f) && (m->m[2][1] == 0.0f) && (m->m[2][2] == 1.0f);
165
166 matrix->m[0][0] = d * det00;
167 matrix->m[0][1] = d * ((m->m[2][1] * m->m[0][2]) - (m->m[0][1] * m->m[2][2]));
168 matrix->m[0][2] = d * ((m->m[0][1] * m->m[1][2]) - (m->m[1][1] * m->m[0][2]));
169 matrix->m[1][0] = d * det01;
170 matrix->m[1][1] = d * ((m->m[0][0] * m->m[2][2]) - (m->m[2][0] * m->m[0][2]));
171 matrix->m[1][2] = d * ((m->m[1][0] * m->m[0][2]) - (m->m[0][0] * m->m[1][2]));
172 matrix->m[2][0] = is_affine ? 0.0f : d * det02;
173 matrix->m[2][1] = is_affine ? 0.0f : d * ((m->m[2][0] * m->m[0][1]) - (m->m[0][0] * m->m[2][1]));
174 matrix->m[2][2] = is_affine ? 1.0f : d * ((m->m[0][0] * m->m[1][1]) - (m->m[1][0] * m->m[0][1]));
175
176 /* Success. */
177 return true;
178 }
179
lv_matrix_transform_precise_point(const lv_matrix_t * matrix,const lv_point_precise_t * point)180 lv_point_precise_t lv_matrix_transform_precise_point(const lv_matrix_t * matrix, const lv_point_precise_t * point)
181 {
182 lv_point_precise_t p;
183 p.x = (lv_value_precise_t)roundf(point->x * matrix->m[0][0] + point->y * matrix->m[0][1] + matrix->m[0][2]);
184 p.y = (lv_value_precise_t)roundf(point->x * matrix->m[1][0] + point->y * matrix->m[1][1] + matrix->m[1][2]);
185 return p;
186 }
187
lv_matrix_transform_area(const lv_matrix_t * matrix,const lv_area_t * area)188 lv_area_t lv_matrix_transform_area(const lv_matrix_t * matrix, const lv_area_t * area)
189 {
190 lv_area_t res;
191 lv_point_precise_t p[4] = {
192 {area->x1, area->y1},
193 {area->x1, area->y2},
194 {area->x2, area->y1},
195 {area->x2, area->y2},
196 };
197 p[0] = lv_matrix_transform_precise_point(matrix, &p[0]);
198 p[1] = lv_matrix_transform_precise_point(matrix, &p[1]);
199 p[2] = lv_matrix_transform_precise_point(matrix, &p[2]);
200 p[3] = lv_matrix_transform_precise_point(matrix, &p[3]);
201
202 res.x1 = (int32_t)(LV_MIN4(p[0].x, p[1].x, p[2].x, p[3].x));
203 res.x2 = (int32_t)(LV_MAX4(p[0].x, p[1].x, p[2].x, p[3].x));
204 res.y1 = (int32_t)(LV_MIN4(p[0].y, p[1].y, p[2].y, p[3].y));
205 res.y2 = (int32_t)(LV_MAX4(p[0].y, p[1].y, p[2].y, p[3].y));
206
207 return res;
208 }
209
lv_matrix_is_identity_or_translation(const lv_matrix_t * matrix)210 bool lv_matrix_is_identity_or_translation(const lv_matrix_t * matrix)
211 {
212 return (matrix->m[0][0] == 1.0f &&
213 matrix->m[0][1] == 0.0f &&
214 matrix->m[1][0] == 0.0f &&
215 matrix->m[1][1] == 1.0f &&
216 matrix->m[2][0] == 0.0f &&
217 matrix->m[2][1] == 0.0f &&
218 matrix->m[2][2] == 1.0f);
219 }
220
221 /**********************
222 * STATIC FUNCTIONS
223 **********************/
224
225 #endif /*LV_USE_MATRIX*/
226