NovaSVG 0.10.0
A header-only SVG library
Loading...
Searching...
No Matches
matrix.h
Go to the documentation of this file.
1#pragma once
2
3#include "utils.h"
4
5namespace novasvg {
6namespace render {
7
8NOVASVG_INLINE void matrix_init(matrix_t* matrix, float a, float b, float c, float d, float e, float f)
9{
10 matrix->a = a; matrix->b = b;
11 matrix->c = c; matrix->d = d;
12 matrix->e = e; matrix->f = f;
13}
14
19
21{
22 matrix_init(matrix, 1, 0, 0, 1, tx, ty);
23}
24
26{
27 matrix_init(matrix, sx, 0, 0, sy, 0, 0);
28}
29
31{
32 float c = cosf(angle);
33 float s = sinf(angle);
34 matrix_init(matrix, c, s, -s, c, 0, 0);
35}
36
37NOVASVG_INLINE void matrix_init_shear(matrix_t* matrix, float shx, float shy)
38{
39 matrix_init(matrix, 1, tanf(shy), tanf(shx), 1, 0, 0);
40}
41
43{
44 matrix_t m;
45 matrix_init_translate(&m, tx, ty);
47}
48
49NOVASVG_INLINE void matrix_scale(matrix_t* matrix, float sx, float sy)
50{
51 matrix_t m;
52 matrix_init_scale(&m, sx, sy);
54}
55
57{
58 matrix_t m;
59 matrix_init_rotate(&m, angle);
61}
62
63NOVASVG_INLINE void matrix_shear(matrix_t* matrix, float shx, float shy)
64{
65 matrix_t m;
66 matrix_init_shear(&m, shx, shy);
68}
69
71{
72 float a = left->a * right->a + left->b * right->c;
73 float b = left->a * right->b + left->b * right->d;
74 float c = left->c * right->a + left->d * right->c;
75 float d = left->c * right->b + left->d * right->d;
76 float e = left->e * right->a + left->f * right->c + right->e;
77 float f = left->e * right->b + left->f * right->d + right->f;
78 matrix_init(matrix, a, b, c, d, e, f);
79}
80
82{
83 float det = (matrix->a * matrix->d - matrix->b * matrix->c);
84 if(det == 0.f)
85 return false;
86 if(inverse) {
87 float inv_det = 1.f / det;
88 float a = matrix->a * inv_det;
89 float b = matrix->b * inv_det;
90 float c = matrix->c * inv_det;
91 float d = matrix->d * inv_det;
92 float e = (matrix->c * matrix->f - matrix->d * matrix->e) * inv_det;
93 float f = (matrix->b * matrix->e - matrix->a * matrix->f) * inv_det;
94 matrix_init(inverse, d, -b, -c, a, e, f);
95 }
96
97 return true;
98}
99
100NOVASVG_INLINE void matrix_map(const matrix_t* matrix, float x, float y, float* xx, float* yy)
101{
102 *xx = x * matrix->a + y * matrix->c + matrix->e;
103 *yy = x * matrix->b + y * matrix->d + matrix->f;
104}
105
107{
108 matrix_map(matrix, src->x, src->y, &dst->x, &dst->y);
109}
110
111NOVASVG_INLINE void matrix_map_points(const matrix_t* matrix, const point_t* src, point_t* dst, int count)
112{
113 for(int i = 0; i < count; ++i) {
114 matrix_map_point(matrix, &src[i], &dst[i]);
115 }
116}
117
119{
120 point_t p[4];
121 p[0].x = src->x;
122 p[0].y = src->y;
123 p[1].x = src->x + src->w;
124 p[1].y = src->y;
125 p[2].x = src->x + src->w;
126 p[2].y = src->y + src->h;
127 p[3].x = src->x;
128 p[3].y = src->y + src->h;
129 matrix_map_points(matrix, p, p, 4);
130
131 float l = p[0].x;
132 float t = p[0].y;
133 float r = p[0].x;
134 float b = p[0].y;
135
136 for(int i = 1; i < 4; i++) {
137 if(p[i].x < l) l = p[i].x;
138 if(p[i].x > r) r = p[i].x;
139 if(p[i].y < t) t = p[i].y;
140 if(p[i].y > b) b = p[i].y;
141 }
142
143 dst->x = l;
144 dst->y = t;
145 dst->w = r - l;
146 dst->h = b - t;
147}
148
149NOVASVG_INLINE int parse_matrix_parameters(const char** begin, const char* end, float values[6], int required, int optional)
150{
151 if(!skip_ws_and_delim(begin, end, '('))
152 return 0;
153 int count = 0;
154 int max_count = required + optional;
155 bool has_trailing_comma = false;
156 for(; count < max_count; ++count) {
157 if(!parse_number(begin, end, values + count))
158 break;
159 skip_css_unit(begin, end, values + count);
160 skip_ws_or_comma(begin, end, &has_trailing_comma);
161 }
162
163 if(!has_trailing_comma && (count == required || count == max_count)
164 && skip_delim(begin, end, ')')) {
165 return count;
166 }
167
168 return 0;
169}
170
171NOVASVG_INLINE bool matrix_parse(matrix_t* matrix, const char* data, int length)
172{
173 float values[6];
175 if(length == -1)
176 length = strlen(data);
177 const char* it = data;
178 const char* end = it + length;
179 bool has_trailing_comma = false;
180 skip_ws(&it, end);
181 while(it < end) {
182 if(skip_string(&it, end, "matrix")) {
183 int count = parse_matrix_parameters(&it, end, values, 6, 0);
184 if(count == 0)
185 return false;
186 matrix_t m = { values[0], values[1], values[2], values[3], values[4], values[5] };
188 } else if(skip_string(&it, end, "translate")) {
189 int count = parse_matrix_parameters(&it, end, values, 1, 1);
190 if(count == 0)
191 return false;
192 if(count == 1) {
193 matrix_translate(matrix, values[0], 0);
194 } else {
195 matrix_translate(matrix, values[0], values[1]);
196 }
197 } else if(skip_string(&it, end, "scale")) {
198 int count = parse_matrix_parameters(&it, end, values, 1, 1);
199 if(count == 0)
200 return false;
201 if(count == 1) {
202 matrix_scale(matrix, values[0], values[0]);
203 } else {
204 matrix_scale(matrix, values[0], values[1]);
205 }
206 } else if(skip_string(&it, end, "rotate")) {
207 int count = parse_matrix_parameters(&it, end, values, 1, 2);
208 if(count == 0)
209 return false;
210 if(count == 3)
211 matrix_translate(matrix, values[1], values[2]);
213 if(count == 3) {
214 matrix_translate(matrix, -values[1], -values[2]);
215 }
216 } else if(skip_string(&it, end, "skewX")) {
217 int count = parse_matrix_parameters(&it, end, values, 1, 0);
218 if(count == 0)
219 return false;
220 matrix_shear(matrix, NOVASVG_DEG2RAD(values[0]), 0);
221 } else if(skip_string(&it, end, "skewY")) {
222 int count = parse_matrix_parameters(&it, end, values, 1, 0);
223 if(count == 0)
224 return false;
225 matrix_shear(matrix, 0, NOVASVG_DEG2RAD(values[0]));
226 } else {
227 return false;
228 }
229
230 skip_ws_or_comma(&it, end, &has_trailing_comma);
231 }
232
233 return !has_trailing_comma;
234}
235
236
237} // namespace render
238} // namespace novasvg
NOVASVG_INLINE void matrix_map_point(const matrix_t *matrix, const point_t *src, point_t *dst)
Transforms the src point using matrix and stores the result in dst.
Definition matrix.h:106
NOVASVG_INLINE void matrix_map(const matrix_t *matrix, float x, float y, float *xx, float *yy)
Transforms the point (x, y) using matrix and stores the result in (xx, yy).
Definition matrix.h:100
NOVASVG_INLINE bool parse_number(const char **begin, const char *end, float *number)
Definition utils.h:88
NOVASVG_INLINE bool skip_ws_or_comma(const char **begin, const char *end, bool *has_comma)
Definition utils.h:222
NOVASVG_INLINE void matrix_map_points(const matrix_t *matrix, const point_t *src, point_t *dst, int count)
Transforms an array of src points using matrix and stores the results in dst.
Definition matrix.h:111
NOVASVG_INLINE void matrix_init_rotate(matrix_t *matrix, float angle)
Initializes a 2D transformation matrix for rotation.
Definition matrix.h:30
NOVASVG_INLINE bool skip_ws_and_delim(const char **begin, const char *end, char delim)
Definition utils.h:183
NOVASVG_INLINE void matrix_init_identity(matrix_t *matrix)
Initializes a 2D transformation matrix to the identity matrix.
Definition matrix.h:15
NOVASVG_INLINE bool matrix_parse(matrix_t *matrix, const char *data, int length)
Parses an SVG transform string into a matrix.
Definition matrix.h:171
NOVASVG_INLINE bool skip_delim(const char **begin, const char *end, const char delim)
Definition utils.h:147
NOVASVG_INLINE bool skip_string(const char **begin, const char *end, const char *data)
Definition utils.h:158
NOVASVG_INLINE bool skip_ws(const char **begin, const char *end)
Definition utils.h:174
NOVASVG_INLINE void matrix_shear(matrix_t *matrix, float shx, float shy)
Shears the matrix by factors shx and shy.
Definition matrix.h:63
NOVASVG_INLINE void matrix_init_scale(matrix_t *matrix, float sx, float sy)
Initializes a 2D transformation matrix for scaling.
Definition matrix.h:25
NOVASVG_INLINE bool matrix_invert(const matrix_t *matrix, matrix_t *inverse)
Calculates the inverse of matrix and stores it in inverse.
Definition matrix.h:81
NOVASVG_INLINE int parse_matrix_parameters(const char **begin, const char *end, float values[6], int required, int optional)
Definition matrix.h:149
NOVASVG_INLINE void skip_css_unit(const char **begin, const char *end, float *number)
Definition utils.h:236
NOVASVG_INLINE void matrix_scale(matrix_t *matrix, float sx, float sy)
Scales the matrix by factors sx and sy
Definition matrix.h:49
NOVASVG_INLINE void matrix_init_shear(matrix_t *matrix, float shx, float shy)
Initializes a 2D transformation matrix for shearing.
Definition matrix.h:37
NOVASVG_INLINE void matrix_multiply(matrix_t *matrix, const matrix_t *left, const matrix_t *right)
Multiplies left and right matrices and stores the result in matrix.
Definition matrix.h:70
NOVASVG_INLINE void matrix_rotate(matrix_t *matrix, float angle)
Rotates the matrix by the specified angle (in radians).
Definition matrix.h:56
NOVASVG_INLINE void matrix_init(matrix_t *matrix, float a, float b, float c, float d, float e, float f)
Initializes a 2D transformation matrix.
Definition matrix.h:8
NOVASVG_INLINE void matrix_init_translate(matrix_t *matrix, float tx, float ty)
Initializes a 2D transformation matrix for translation.
Definition matrix.h:20
NOVASVG_INLINE void matrix_translate(matrix_t *matrix, float tx, float ty)
Adds a translation with offsets tx and ty to the matrix.
Definition matrix.h:42
NOVASVG_INLINE void matrix_map_rect(const matrix_t *matrix, const rect_t *src, rect_t *dst)
Transforms the src rectangle using matrix and stores the result in dst.
Definition matrix.h:118
Main namespace for the NovaSVG library.
Definition bitmap.h:23
#define NOVASVG_INLINE
Definition novasvg.h:42
#define NOVASVG_DEG2RAD(x)
Definition render.h:108
A structure representing a 2D transformation matrix.
Definition render.h:138
float d
The vertical scaling factor.
Definition render.h:142
float c
The horizontal shearing factor.
Definition render.h:141
float f
The vertical translation offset.
Definition render.h:144
float e
The horizontal translation offset.
Definition render.h:143
float b
The vertical shearing factor.
Definition render.h:140
float a
The horizontal scaling factor.
Definition render.h:139
A structure representing a point in 2D space.
Definition render.h:114
float y
The y-coordinate of the point.
Definition render.h:116
float x
The x-coordinate of the point.
Definition render.h:115
A structure representing a rectangle in 2D space.
Definition render.h:125
float x
The x-coordinate of the top-left corner of the rectangle.
Definition render.h:126
float w
The width of the rectangle.
Definition render.h:128
float h
The height of the rectangle.
Definition render.h:129
float y
The y-coordinate of the top-left corner of the rectangle.
Definition render.h:127