First Commit
This commit is contained in:
231
3rdparty/plutosvg/plutovg/source/plutovg-matrix.c
vendored
Normal file
231
3rdparty/plutosvg/plutovg/source/plutovg-matrix.c
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
#include "plutovg.h"
|
||||
#include "plutovg-utils.h"
|
||||
|
||||
void plutovg_matrix_init(plutovg_matrix_t* matrix, float a, float b, float c, float d, float e, float f)
|
||||
{
|
||||
matrix->a = a; matrix->b = b;
|
||||
matrix->c = c; matrix->d = d;
|
||||
matrix->e = e; matrix->f = f;
|
||||
}
|
||||
|
||||
void plutovg_matrix_init_identity(plutovg_matrix_t* matrix)
|
||||
{
|
||||
matrix->a = 1; matrix->b = 0;
|
||||
matrix->c = 0; matrix->d = 1;
|
||||
matrix->e = 0; matrix->f = 0;
|
||||
}
|
||||
|
||||
void plutovg_matrix_init_translate(plutovg_matrix_t* matrix, float tx, float ty)
|
||||
{
|
||||
plutovg_matrix_init(matrix, 1, 0, 0, 1, tx, ty);
|
||||
}
|
||||
|
||||
void plutovg_matrix_init_scale(plutovg_matrix_t* matrix, float sx, float sy)
|
||||
{
|
||||
plutovg_matrix_init(matrix, sx, 0, 0, sy, 0, 0);
|
||||
}
|
||||
|
||||
void plutovg_matrix_init_rotate(plutovg_matrix_t* matrix, float angle)
|
||||
{
|
||||
float c = cosf(angle);
|
||||
float s = sinf(angle);
|
||||
plutovg_matrix_init(matrix, c, s, -s, c, 0, 0);
|
||||
}
|
||||
|
||||
void plutovg_matrix_init_shear(plutovg_matrix_t* matrix, float shx, float shy)
|
||||
{
|
||||
plutovg_matrix_init(matrix, 1, tanf(shy), tanf(shx), 1, 0, 0);
|
||||
}
|
||||
|
||||
void plutovg_matrix_translate(plutovg_matrix_t* matrix, float tx, float ty)
|
||||
{
|
||||
plutovg_matrix_t m;
|
||||
plutovg_matrix_init_translate(&m, tx, ty);
|
||||
plutovg_matrix_multiply(matrix, &m, matrix);
|
||||
}
|
||||
|
||||
void plutovg_matrix_scale(plutovg_matrix_t* matrix, float sx, float sy)
|
||||
{
|
||||
plutovg_matrix_t m;
|
||||
plutovg_matrix_init_scale(&m, sx, sy);
|
||||
plutovg_matrix_multiply(matrix, &m, matrix);
|
||||
}
|
||||
|
||||
void plutovg_matrix_rotate(plutovg_matrix_t* matrix, float angle)
|
||||
{
|
||||
plutovg_matrix_t m;
|
||||
plutovg_matrix_init_rotate(&m, angle);
|
||||
plutovg_matrix_multiply(matrix, &m, matrix);
|
||||
}
|
||||
|
||||
void plutovg_matrix_shear(plutovg_matrix_t* matrix, float shx, float shy)
|
||||
{
|
||||
plutovg_matrix_t m;
|
||||
plutovg_matrix_init_shear(&m, shx, shy);
|
||||
plutovg_matrix_multiply(matrix, &m, matrix);
|
||||
}
|
||||
|
||||
void plutovg_matrix_multiply(plutovg_matrix_t* matrix, const plutovg_matrix_t* left, const plutovg_matrix_t* right)
|
||||
{
|
||||
float a = left->a * right->a + left->b * right->c;
|
||||
float b = left->a * right->b + left->b * right->d;
|
||||
float c = left->c * right->a + left->d * right->c;
|
||||
float d = left->c * right->b + left->d * right->d;
|
||||
float e = left->e * right->a + left->f * right->c + right->e;
|
||||
float f = left->e * right->b + left->f * right->d + right->f;
|
||||
plutovg_matrix_init(matrix, a, b, c, d, e, f);
|
||||
}
|
||||
|
||||
bool plutovg_matrix_invert(const plutovg_matrix_t* matrix, plutovg_matrix_t* inverse)
|
||||
{
|
||||
float det = (matrix->a * matrix->d - matrix->b * matrix->c);
|
||||
if(det == 0.f)
|
||||
return false;
|
||||
if(inverse) {
|
||||
float inv_det = 1.f / det;
|
||||
float a = matrix->a * inv_det;
|
||||
float b = matrix->b * inv_det;
|
||||
float c = matrix->c * inv_det;
|
||||
float d = matrix->d * inv_det;
|
||||
float e = (matrix->c * matrix->f - matrix->d * matrix->e) * inv_det;
|
||||
float f = (matrix->b * matrix->e - matrix->a * matrix->f) * inv_det;
|
||||
plutovg_matrix_init(inverse, d, -b, -c, a, e, f);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void plutovg_matrix_map(const plutovg_matrix_t* matrix, float x, float y, float* xx, float* yy)
|
||||
{
|
||||
*xx = x * matrix->a + y * matrix->c + matrix->e;
|
||||
*yy = x * matrix->b + y * matrix->d + matrix->f;
|
||||
}
|
||||
|
||||
void plutovg_matrix_map_point(const plutovg_matrix_t* matrix, const plutovg_point_t* src, plutovg_point_t* dst)
|
||||
{
|
||||
plutovg_matrix_map(matrix, src->x, src->y, &dst->x, &dst->y);
|
||||
}
|
||||
|
||||
void plutovg_matrix_map_points(const plutovg_matrix_t* matrix, const plutovg_point_t* src, plutovg_point_t* dst, int count)
|
||||
{
|
||||
for(int i = 0; i < count; ++i) {
|
||||
plutovg_matrix_map_point(matrix, &src[i], &dst[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void plutovg_matrix_map_rect(const plutovg_matrix_t* matrix, const plutovg_rect_t* src, plutovg_rect_t* dst)
|
||||
{
|
||||
plutovg_point_t p[4];
|
||||
p[0].x = src->x;
|
||||
p[0].y = src->y;
|
||||
p[1].x = src->x + src->w;
|
||||
p[1].y = src->y;
|
||||
p[2].x = src->x + src->w;
|
||||
p[2].y = src->y + src->h;
|
||||
p[3].x = src->x;
|
||||
p[3].y = src->y + src->h;
|
||||
plutovg_matrix_map_points(matrix, p, p, 4);
|
||||
|
||||
float l = p[0].x;
|
||||
float t = p[0].y;
|
||||
float r = p[0].x;
|
||||
float b = p[0].y;
|
||||
|
||||
for(int i = 1; i < 4; i++) {
|
||||
if(p[i].x < l) l = p[i].x;
|
||||
if(p[i].x > r) r = p[i].x;
|
||||
if(p[i].y < t) t = p[i].y;
|
||||
if(p[i].y > b) b = p[i].y;
|
||||
}
|
||||
|
||||
dst->x = l;
|
||||
dst->y = t;
|
||||
dst->w = r - l;
|
||||
dst->h = b - t;
|
||||
}
|
||||
|
||||
static int parse_matrix_parameters(const char** begin, const char* end, float values[6], int required, int optional)
|
||||
{
|
||||
if(!plutovg_skip_ws_and_delim(begin, end, '('))
|
||||
return 0;
|
||||
int count = 0;
|
||||
int max_count = required + optional;
|
||||
bool has_trailing_comma = false;
|
||||
for(; count < max_count; ++count) {
|
||||
if(!plutovg_parse_number(begin, end, values + count))
|
||||
break;
|
||||
plutovg_skip_ws_or_comma(begin, end, &has_trailing_comma);
|
||||
}
|
||||
|
||||
if(!has_trailing_comma && (count == required || count == max_count)
|
||||
&& plutovg_skip_delim(begin, end, ')')) {
|
||||
return count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool plutovg_matrix_parse(plutovg_matrix_t* matrix, const char* data, int length)
|
||||
{
|
||||
float values[6];
|
||||
plutovg_matrix_init_identity(matrix);
|
||||
if(length == -1)
|
||||
length = strlen(data);
|
||||
const char* it = data;
|
||||
const char* end = it + length;
|
||||
bool has_trailing_comma = false;
|
||||
plutovg_skip_ws(&it, end);
|
||||
while(it < end) {
|
||||
if(plutovg_skip_string(&it, end, "matrix")) {
|
||||
int count = parse_matrix_parameters(&it, end, values, 6, 0);
|
||||
if(count == 0)
|
||||
return false;
|
||||
plutovg_matrix_t m = { values[0], values[1], values[2], values[3], values[4], values[5] };
|
||||
plutovg_matrix_multiply(matrix, &m, matrix);
|
||||
} else if(plutovg_skip_string(&it, end, "translate")) {
|
||||
int count = parse_matrix_parameters(&it, end, values, 1, 1);
|
||||
if(count == 0)
|
||||
return false;
|
||||
if(count == 1) {
|
||||
plutovg_matrix_translate(matrix, values[0], 0);
|
||||
} else {
|
||||
plutovg_matrix_translate(matrix, values[0], values[1]);
|
||||
}
|
||||
} else if(plutovg_skip_string(&it, end, "scale")) {
|
||||
int count = parse_matrix_parameters(&it, end, values, 1, 1);
|
||||
if(count == 0)
|
||||
return false;
|
||||
if(count == 1) {
|
||||
plutovg_matrix_scale(matrix, values[0], values[0]);
|
||||
} else {
|
||||
plutovg_matrix_scale(matrix, values[0], values[1]);
|
||||
}
|
||||
} else if(plutovg_skip_string(&it, end, "rotate")) {
|
||||
int count = parse_matrix_parameters(&it, end, values, 1, 2);
|
||||
if(count == 0)
|
||||
return false;
|
||||
if(count == 3)
|
||||
plutovg_matrix_translate(matrix, values[1], values[2]);
|
||||
plutovg_matrix_rotate(matrix, PLUTOVG_DEG2RAD(values[0]));
|
||||
if(count == 3) {
|
||||
plutovg_matrix_translate(matrix, -values[1], -values[2]);
|
||||
}
|
||||
} else if(plutovg_skip_string(&it, end, "skewX")) {
|
||||
int count = parse_matrix_parameters(&it, end, values, 1, 0);
|
||||
if(count == 0)
|
||||
return false;
|
||||
plutovg_matrix_shear(matrix, PLUTOVG_DEG2RAD(values[0]), 0);
|
||||
} else if(plutovg_skip_string(&it, end, "skewY")) {
|
||||
int count = parse_matrix_parameters(&it, end, values, 1, 0);
|
||||
if(count == 0)
|
||||
return false;
|
||||
plutovg_matrix_shear(matrix, 0, PLUTOVG_DEG2RAD(values[0]));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
plutovg_skip_ws_or_comma(&it, end, &has_trailing_comma);
|
||||
}
|
||||
|
||||
return !has_trailing_comma;
|
||||
}
|
||||
Reference in New Issue
Block a user