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