From ed7b191ba74762b3a1eee1c0100d6868153181fa Mon Sep 17 00:00:00 2001 From: Subhransu Mohanty Date: Thu, 14 Jul 2016 09:58:23 +0900 Subject: [PATCH] eina: backported eina_bezier and eina_matrix from opensource Change-Id: I27d16079ff7da00ef0ca2b4b4139cda55e70dcb3 --- src/lib/eina/eina_bezier.c | 58 +++++++ src/lib/eina/eina_bezier.h | 27 +++ src/lib/eina/eina_matrix.c | 415 +++++++++++++++++++++++++++++++++++---------- src/lib/eina/eina_matrix.h | 275 +++++++++++++++++++++++++++++- 4 files changed, 684 insertions(+), 91 deletions(-) diff --git a/src/lib/eina/eina_bezier.c b/src/lib/eina/eina_bezier.c index 4e8ffca..6494551 100644 --- a/src/lib/eina/eina_bezier.c +++ b/src/lib/eina/eina_bezier.c @@ -273,3 +273,61 @@ eina_bezier_split_at_length(const Eina_Bezier *b, double len, t = eina_bezier_t_at(right, len); _eina_bezier_split_left(right, t, left); } + +EAPI void +eina_bezier_bounds_get(const Eina_Bezier *b, double *x, double *y, double *w, double *h) +{ + double xmin = b->start.x; + double xmax = b->start.x; + double ymin = b->start.y; + double ymax = b->start.y; + + if (b->ctrl_start.x < xmin) + xmin = b->ctrl_start.x; + else if (b->ctrl_start.x > xmax) + xmax = b->ctrl_start.x; + if (b->ctrl_end.x < xmin) + xmin = b->ctrl_end.x; + else if (b->ctrl_end.x > xmax) + xmax = b->ctrl_end.x; + if (b->end.x < xmin) + xmin = b->end.x; + else if (b->end.x > xmax) + xmax = b->end.x; + + if (b->ctrl_start.y < ymin) + ymin = b->ctrl_start.y; + else if (b->ctrl_start.y > ymax) + ymax = b->ctrl_start.y; + if (b->ctrl_end.y < ymin) + ymin = b->ctrl_end.y; + else if (b->ctrl_end.y > ymax) + ymax = b->ctrl_end.y; + if (b->end.y < ymin) + ymin = b->end.y; + else if (b->end.y > ymax) + ymax = b->end.y; + + if (x) *x = xmin; + if (y) *y = ymin; + if (w) *w = xmax - xmin; + if (h) *h = ymax - ymin; +} + +EAPI void +eina_bezier_on_interval(Eina_Bezier *b, double t0, double t1, Eina_Bezier *result) +{ + Eina_Bezier bezier; + double t; + + if (t0 == 0 && t1 == 1) + { + *result = *b; + return; + } + + bezier = *b; + _eina_bezier_split_left(&bezier, t0, result); + t = (t1-t0)/(1-t0); + _eina_bezier_split_left(&bezier, t, result); +} diff --git a/src/lib/eina/eina_bezier.h b/src/lib/eina/eina_bezier.h index aef32e4..e8d1a7b 100644 --- a/src/lib/eina/eina_bezier.h +++ b/src/lib/eina/eina_bezier.h @@ -143,4 +143,31 @@ EAPI double eina_bezier_angle_at(const Eina_Bezier *b, double t) EINA_ARG_NONNUL */ EAPI void eina_bezier_split_at_length(const Eina_Bezier *b, double len, Eina_Bezier *left, Eina_Bezier *right) EINA_ARG_NONNULL(1); +/** + * @brief get the bound of the the bezier. + * + * @param b The floating point bezier. + * @param x x coordinate of bounding box. + * @param y y coordinate of bounding box. + * @param w width of bounding box. + * @param h height of bounding box. + * + * @p b. No check is done on @p b. + * @since 1.17 + */ +EAPI void eina_bezier_bounds_get(const Eina_Bezier *b, double *x, double *y, double *w, double *h) EINA_ARG_NONNULL(1); + +/** + * @brief find the bezier at given interval. + * + * @param b The floating point bezier. + * @param t0 The start interval. + * @param t1 The end interval. + * @param result The result bezier. + * + * @p b. No check is done on @p b. + * @since 1.17 + */ +EAPI void eina_bezier_on_interval(Eina_Bezier *b, double t0, double t1, Eina_Bezier *result); + #endif // EINA_BEZIER_H diff --git a/src/lib/eina/eina_matrix.c b/src/lib/eina/eina_matrix.c index 4263322..d7aeebf 100644 --- a/src/lib/eina/eina_matrix.c +++ b/src/lib/eina/eina_matrix.c @@ -939,113 +939,350 @@ eina_matrix4_transpose(Eina_Matrix4 *out, const Eina_Matrix4 *in) } EAPI void -eina_matrix4_multiply(Eina_Matrix4 *out, - const Eina_Matrix4 *a, const Eina_Matrix4 *b) +eina_matrix4_multiply_copy(Eina_Matrix4 *out, + const Eina_Matrix4 *mat_a, const Eina_Matrix4 *mat_b) { - // FIXME: start implementing SSE multiplication here - MATRIX_XX(out) = - MATRIX_XX(a) * MATRIX_XX(b) - + MATRIX_XY(a) * MATRIX_YX(b) - + MATRIX_XZ(a) * MATRIX_ZX(b) - + MATRIX_XW(a) * MATRIX_WX(b); + if (out != mat_a && out != mat_b) + { + eina_matrix4_multiply(out, mat_a, mat_b); + } + else + { + Eina_Matrix4 result; - MATRIX_XY(out) = - MATRIX_XX(a) * MATRIX_XY(b) - + MATRIX_XY(a) * MATRIX_YY(b) - + MATRIX_XZ(a) * MATRIX_ZY(b) - + MATRIX_XW(a) * MATRIX_WY(b); + eina_matrix4_multiply(&result, mat_a, mat_b); + eina_matrix4_copy(out, &result); + } +} - MATRIX_XZ(out) = - MATRIX_XX(a) * MATRIX_XZ(b) - + MATRIX_XY(a) * MATRIX_YZ(b) - + MATRIX_XZ(a) * MATRIX_ZZ(b) - + MATRIX_XW(a) * MATRIX_WZ(b); +EAPI void +eina_matrix4_identity(Eina_Matrix4 *out) +{ + memset(out, 0, sizeof (Eina_Matrix4)); - MATRIX_XW(out) = - MATRIX_XX(a) * MATRIX_XW(b) - + MATRIX_XY(a) * MATRIX_YW(b) - + MATRIX_XZ(a) * MATRIX_ZW(b) - + MATRIX_XW(a) * MATRIX_WW(b); + MATRIX_XX(out) = 1.0; + MATRIX_YY(out) = 1.0; + MATRIX_ZZ(out) = 1.0; + MATRIX_WW(out) = 1.0; +} - MATRIX_YX(out) = - MATRIX_YX(a) * MATRIX_XX(b) - + MATRIX_YY(a) * MATRIX_YX(b) - + MATRIX_YZ(a) * MATRIX_ZX(b) - + MATRIX_YW(a) * MATRIX_WX(b); +EAPI Eina_Matrix_Type +eina_matrix2_type_get(const Eina_Matrix2 *m) +{ + if ((MATRIX_XX(m) == 1) && (MATRIX_XY(m) == 0) && + (MATRIX_YX(m) == 0) && (MATRIX_YY(m) == 1)) + return EINA_MATRIX_TYPE_IDENTITY; + return EINA_MATRIX_TYPE_AFFINE; +} - MATRIX_YY(out) = - MATRIX_YX(a) * MATRIX_XY(b) - + MATRIX_YY(a) * MATRIX_YY(b) - + MATRIX_YZ(a) * MATRIX_ZY(b) - + MATRIX_YW(a) * MATRIX_WY(b); +EAPI void +eina_matrix4_array_set(Eina_Matrix4 *m, const double *v) +{ + memcpy(&MATRIX_XX(m), v, sizeof(double) * 16); +} - MATRIX_YZ(out) = - MATRIX_YX(a) * MATRIX_XZ(b) - + MATRIX_YY(a) * MATRIX_YZ(b) - + MATRIX_YZ(a) * MATRIX_ZZ(b) - + MATRIX_YW(a) * MATRIX_WZ(b); +EAPI void +eina_matrix4_copy(Eina_Matrix4 *dst, const Eina_Matrix4 *src) +{ + memcpy(dst, src, sizeof(Eina_Matrix4)); +} - MATRIX_YW(out) = - MATRIX_YX(a) * MATRIX_XW(b) - + MATRIX_YY(a) * MATRIX_YW(b) - + MATRIX_YZ(a) * MATRIX_ZW(b) - + MATRIX_YW(a) * MATRIX_WW(b); +EAPI void +eina_matrix4_multiply(Eina_Matrix4 *out, const Eina_Matrix4 *mat_a, + const Eina_Matrix4 *mat_b) +{ + if (eina_matrix4_type_get(mat_a) == EINA_MATRIX_TYPE_IDENTITY) + { + eina_matrix4_copy(out, mat_b); + return; + } - MATRIX_ZX(out) = - MATRIX_ZX(a) * MATRIX_XX(b) - + MATRIX_ZY(a) * MATRIX_YX(b) - + MATRIX_ZZ(a) * MATRIX_ZX(b) - + MATRIX_ZW(a) * MATRIX_WX(b); + if (eina_matrix4_type_get(mat_b) == EINA_MATRIX_TYPE_IDENTITY) + { + eina_matrix4_copy(out, mat_a); + return; + } - MATRIX_ZY(out) = - MATRIX_ZX(a) * MATRIX_XY(b) - + MATRIX_ZY(a) * MATRIX_YY(b) - + MATRIX_ZZ(a) * MATRIX_ZY(b) - + MATRIX_ZW(a) * MATRIX_WY(b); + MATRIX_XX(out) = MATRIX_XX(mat_a) * MATRIX_XX(mat_b) + MATRIX_YX(mat_a) * MATRIX_XY(mat_b) + + MATRIX_ZX(mat_a) * MATRIX_XZ(mat_b) + MATRIX_WX(mat_a) * MATRIX_XW(mat_b); + MATRIX_YX(out) = MATRIX_XX(mat_a) * MATRIX_YX(mat_b) + MATRIX_YX(mat_a) * MATRIX_YY(mat_b) + + MATRIX_ZX(mat_a) * MATRIX_YZ(mat_b) + MATRIX_WX(mat_a) * MATRIX_YW(mat_b); + MATRIX_ZX(out) = MATRIX_XX(mat_a) * MATRIX_ZX(mat_b) + MATRIX_YX(mat_a) * MATRIX_ZY(mat_b) + + MATRIX_ZX(mat_a) * MATRIX_ZZ(mat_b) + MATRIX_WX(mat_a) * MATRIX_ZW(mat_b); + MATRIX_WX(out) = MATRIX_XX(mat_a) * MATRIX_WX(mat_b) + MATRIX_YX(mat_a) * MATRIX_WY(mat_b) + + MATRIX_ZX(mat_a) * MATRIX_WZ(mat_b) + MATRIX_WX(mat_a) * MATRIX_WW(mat_b); + + MATRIX_XY(out) = MATRIX_XY(mat_a) * MATRIX_XX(mat_b) + MATRIX_YY(mat_a) * MATRIX_XY(mat_b) + + MATRIX_ZY(mat_a) * MATRIX_XZ(mat_b) + MATRIX_WY(mat_a) * MATRIX_XW(mat_b); + MATRIX_YY(out) = MATRIX_XY(mat_a) * MATRIX_YX(mat_b) + MATRIX_YY(mat_a) * MATRIX_YY(mat_b) + + MATRIX_ZY(mat_a) * MATRIX_YZ(mat_b) + MATRIX_WY(mat_a) * MATRIX_YW(mat_b); + MATRIX_ZY(out) = MATRIX_XY(mat_a) * MATRIX_ZX(mat_b) + MATRIX_YY(mat_a) * MATRIX_ZY(mat_b) + + MATRIX_ZY(mat_a) * MATRIX_ZZ(mat_b) + MATRIX_WY(mat_a) * MATRIX_ZW(mat_b); + MATRIX_WY(out) = MATRIX_XY(mat_a) * MATRIX_WX(mat_b) + MATRIX_YY(mat_a) * MATRIX_WY(mat_b) + + MATRIX_ZY(mat_a) * MATRIX_WZ(mat_b) + MATRIX_WY(mat_a) * MATRIX_WW(mat_b); + + MATRIX_XZ(out) = MATRIX_XZ(mat_a) * MATRIX_XX(mat_b) + MATRIX_YZ(mat_a) * MATRIX_XY(mat_b) + + MATRIX_ZZ(mat_a) * MATRIX_XZ(mat_b) + MATRIX_WZ(mat_a) * MATRIX_XW(mat_b); + MATRIX_YZ(out) = MATRIX_XZ(mat_a) * MATRIX_YX(mat_b) + MATRIX_YZ(mat_a) * MATRIX_YY(mat_b) + + MATRIX_ZZ(mat_a) * MATRIX_YZ(mat_b) + MATRIX_WZ(mat_a) * MATRIX_YW(mat_b); + MATRIX_ZZ(out) = MATRIX_XZ(mat_a) * MATRIX_ZX(mat_b) + MATRIX_YZ(mat_a) * MATRIX_ZY(mat_b) + + MATRIX_ZZ(mat_a) * MATRIX_ZZ(mat_b) + MATRIX_WZ(mat_a) * MATRIX_ZW(mat_b); + MATRIX_WZ(out) = MATRIX_XZ(mat_a) * MATRIX_WX(mat_b) + MATRIX_YZ(mat_a) * MATRIX_WY(mat_b) + + MATRIX_ZZ(mat_a) * MATRIX_WZ(mat_b) + MATRIX_WZ(mat_a) * MATRIX_WW(mat_b); + + MATRIX_XW(out) = MATRIX_XW(mat_a) * MATRIX_XX(mat_b) + MATRIX_YW(mat_a) * MATRIX_XY(mat_b) + + MATRIX_ZW(mat_a) * MATRIX_XZ(mat_b) + MATRIX_WW(mat_a) * MATRIX_XW(mat_b); + MATRIX_YW(out) = MATRIX_XW(mat_a) * MATRIX_YX(mat_b) + MATRIX_YW(mat_a) * MATRIX_YY(mat_b) + + MATRIX_ZW(mat_a) * MATRIX_YZ(mat_b) + MATRIX_WW(mat_a) * MATRIX_YW(mat_b); + MATRIX_ZW(out) = MATRIX_XW(mat_a) * MATRIX_ZX(mat_b) + MATRIX_YW(mat_a) * MATRIX_ZY(mat_b) + + MATRIX_ZW(mat_a) * MATRIX_ZZ(mat_b) + MATRIX_WW(mat_a) * MATRIX_ZW(mat_b); + MATRIX_WW(out) = MATRIX_XW(mat_a) * MATRIX_WX(mat_b) + MATRIX_YW(mat_a) * MATRIX_WY(mat_b) + + MATRIX_ZW(mat_a) * MATRIX_WZ(mat_b) + MATRIX_WW(mat_a) * MATRIX_WW(mat_b); +} - MATRIX_ZZ(out) = - MATRIX_ZX(a) * MATRIX_XZ(b) - + MATRIX_ZY(a) * MATRIX_YZ(b) - + MATRIX_ZZ(a) * MATRIX_ZZ(b) - + MATRIX_ZW(a) * MATRIX_WZ(b); +EAPI void +eina_matrix4_ortho_set(Eina_Matrix4 *m, + double left, double right, double bottom, double top, + double dnear, double dfar) +{ + double w = right - left; + double h = top - bottom; + double depth = dnear - dfar; + + MATRIX_XX(m) = 2.0f / w; + MATRIX_XY(m) = 0.0f; + MATRIX_XZ(m) = 0.0f; + MATRIX_XW(m) = 0.0f; + + MATRIX_YX(m) = 0.0f; + MATRIX_YY(m) = 2.0f / h; + MATRIX_YZ(m) = 0.0f; + MATRIX_YW(m) = 0.0f; + + MATRIX_ZX(m) = 0.0f; + MATRIX_ZY(m) = 0.0f; + MATRIX_ZZ(m) = 2.0f / depth; + MATRIX_ZW(m) = 0.0f; + + MATRIX_WX(m) = -(right + left) / w; + MATRIX_WY(m) = -(top + bottom) / h; + MATRIX_WZ(m) = (dfar + dnear) / depth; + MATRIX_WW(m) = 1.0f; +} - MATRIX_ZW(out) = - MATRIX_ZX(a) * MATRIX_XW(b) - + MATRIX_ZY(a) * MATRIX_YW(b) - + MATRIX_ZZ(a) * MATRIX_ZW(b) - + MATRIX_ZW(a) * MATRIX_WW(b); +EAPI void +eina_matrix3_array_set(Eina_Matrix3 *m, const double *v) +{ + memcpy(&MATRIX_XX(m), v, sizeof(double) * 9); +} - MATRIX_WX(out) = - MATRIX_WX(a) * MATRIX_XX(b) - + MATRIX_WY(a) * MATRIX_YX(b) - + MATRIX_WZ(a) * MATRIX_ZX(b) - + MATRIX_WW(a) * MATRIX_WX(b); +EAPI void +eina_matrix3_copy(Eina_Matrix3 *dst, const Eina_Matrix3 *src) +{ + memcpy(dst, src, sizeof(Eina_Matrix3)); +} - MATRIX_WY(out) = - MATRIX_WX(a) * MATRIX_XY(b) - + MATRIX_WY(a) * MATRIX_YY(b) - + MATRIX_WZ(a) * MATRIX_ZY(b) - + MATRIX_WW(a) * MATRIX_WY(b); +EAPI void +eina_matrix3_multiply(Eina_Matrix3 *out, const Eina_Matrix3 *mat_a, const Eina_Matrix3 *mat_b) +{ + if (eina_matrix3_type_get(mat_a) == EINA_MATRIX_TYPE_IDENTITY) + { + eina_matrix3_copy(out, mat_b); + return; + } - MATRIX_WZ(out) = - MATRIX_WX(a) * MATRIX_XZ(b) - + MATRIX_WY(a) * MATRIX_YZ(b) - + MATRIX_WZ(a) * MATRIX_ZZ(b) - + MATRIX_WW(a) * MATRIX_WZ(b); + if (eina_matrix3_type_get(mat_b) == EINA_MATRIX_TYPE_IDENTITY) + { + eina_matrix3_copy(out, mat_a); + return; + } - MATRIX_WW(out) = - MATRIX_WX(a) * MATRIX_XW(b) - + MATRIX_WY(a) * MATRIX_YW(b) - + MATRIX_WZ(a) * MATRIX_ZW(b) - + MATRIX_WW(a) * MATRIX_WW(b); + MATRIX_XX(out) = MATRIX_XX(mat_b) * MATRIX_XX(mat_a) + MATRIX_YX(mat_b) * MATRIX_XY(mat_a) + MATRIX_ZX(mat_b) * MATRIX_XZ(mat_a); + MATRIX_XY(out) = MATRIX_XY(mat_b) * MATRIX_XX(mat_a) + MATRIX_YY(mat_b) * MATRIX_XY(mat_a) + MATRIX_ZY(mat_b) * MATRIX_XZ(mat_a); + MATRIX_XZ(out) = MATRIX_XZ(mat_b) * MATRIX_XX(mat_a) + MATRIX_YZ(mat_b) * MATRIX_XY(mat_a) + MATRIX_ZZ(mat_b) * MATRIX_XZ(mat_a); + + MATRIX_YX(out) = MATRIX_XX(mat_b) * MATRIX_YX(mat_a) + MATRIX_YX(mat_b) * MATRIX_YY(mat_a) + MATRIX_ZX(mat_b) * MATRIX_YZ(mat_a); + MATRIX_YY(out) = MATRIX_XY(mat_b) * MATRIX_YX(mat_a) + MATRIX_YY(mat_b) * MATRIX_YY(mat_a) + MATRIX_ZY(mat_b) * MATRIX_YZ(mat_a); + MATRIX_YZ(out) = MATRIX_XZ(mat_b) * MATRIX_YX(mat_a) + MATRIX_YZ(mat_b) * MATRIX_YY(mat_a) + MATRIX_ZZ(mat_b) * MATRIX_YZ(mat_a); + + MATRIX_ZX(out) = MATRIX_XX(mat_b) * MATRIX_ZX(mat_a) + MATRIX_YX(mat_b) * MATRIX_ZY(mat_a) + MATRIX_ZX(mat_b) * MATRIX_ZZ(mat_a); + MATRIX_ZY(out) = MATRIX_XY(mat_b) * MATRIX_ZX(mat_a) + MATRIX_YY(mat_b) * MATRIX_ZY(mat_a) + MATRIX_ZY(mat_b) * MATRIX_ZZ(mat_a); + MATRIX_ZZ(out) = MATRIX_XZ(mat_b) * MATRIX_ZX(mat_a) + MATRIX_YZ(mat_b) * MATRIX_ZY(mat_a) + MATRIX_ZZ(mat_b) * MATRIX_ZZ(mat_a); } EAPI void -eina_matrix4_identity(Eina_Matrix4 *out) +eina_matrix3_multiply_copy(Eina_Matrix3 *out, const Eina_Matrix3 *mat_a, const Eina_Matrix3 *mat_b) { - memset(out, 0, sizeof (Eina_Matrix4)); - MATRIX_XX(out) = 1; - MATRIX_YY(out) = 1; - MATRIX_ZZ(out) = 1; - MATRIX_WW(out) = 1; + if (out != mat_a && out != mat_b) + { + eina_matrix3_multiply(out, mat_a, mat_b); + } + else + { + Eina_Matrix3 tmp; + + eina_matrix3_multiply(&tmp, mat_a, mat_b); + eina_matrix3_copy(out, &tmp); + } +} + +EAPI void +eina_matrix3_position_transform_set(Eina_Matrix3 *out, const double p_x, + const double p_y) +{ + eina_matrix3_identity(out); + MATRIX_XZ(out) = p_x; + MATRIX_YZ(out) = p_y; +} + +EAPI void +eina_matrix3_scale_transform_set(Eina_Matrix3 *out, double s_x, double s_y) +{ + eina_matrix3_identity(out); + MATRIX_XX(out) = s_x; + MATRIX_YY(out) = s_y; +} + +EAPI void +eina_normal3_matrix_get(Eina_Matrix3 *out, const Eina_Matrix4 *m) +{ + /* Normal matrix is a transposed matrix of inversed modelview. + * And we need only upper-left 3x3 terms to work with. */ + + double det; + + double a = MATRIX_XX(m); + double b = MATRIX_YX(m); + double c = MATRIX_ZX(m); + + double d = MATRIX_XY(m); + double e = MATRIX_YY(m); + double f = MATRIX_ZY(m); + + double g = MATRIX_XZ(m); + double h = MATRIX_YZ(m); + double i = MATRIX_ZZ(m); + + det = a * e * i + b * f * g + c * d * h - g * e * c - h * f * a - i * d * b; + + if (fabs(det) >= DBL_EPSILON) det = 1.0 / det; + else det = 0.0; + + MATRIX_XX(out) = (e * i - f * h) * det; + MATRIX_XY(out) = (h * c - i * b) * det; + MATRIX_XZ(out) = (b * f - c * e) * det; + + MATRIX_YX(out) = (g * f - d * i) * det; + MATRIX_YY(out) = (a * i - g * c) * det; + MATRIX_YZ(out) = (d * c - a * f) * det; + + MATRIX_ZX(out) = (d * h - g * e) * det; + MATRIX_ZY(out) = (g * b - a * h) * det; + MATRIX_ZZ(out) = (a * e - d * b) * det; +} + +EAPI void +eina_matrix2_values_set(Eina_Matrix2 *m, + double xx, double xy, + double yx, double yy) +{ + MATRIX_XX(m) = xx; + MATRIX_XY(m) = xy; + MATRIX_YX(m) = yx; + MATRIX_YY(m) = yy; +} + +EAPI void +eina_matrix2_values_get(const Eina_Matrix2 *m, + double *xx, double *xy, + double *yx, double *yy) +{ + if (xx) *xx = MATRIX_XX(m); + if (xy) *xy = MATRIX_XY(m); + if (yx) *yx = MATRIX_YX(m); + if (yy) *yy = MATRIX_YY(m); +} + +EAPI void +eina_matrix2_inverse(Eina_Matrix2 *out, const Eina_Matrix2 *mat) +{ + double det; + + if (eina_matrix2_type_get(mat) == EINA_MATRIX_TYPE_IDENTITY) + { + eina_matrix2_copy(out, mat); + return; + } + + det = MATRIX_XX(mat) * MATRIX_YY(mat) - MATRIX_YX(mat) * MATRIX_XY(mat); + + if (det == 0.0) + return; + + det = 1.0 / det; + + MATRIX_XX(out) = MATRIX_YY(mat) * det; + MATRIX_XY(out) = -MATRIX_XY(mat) * det; + MATRIX_YX(out) = -MATRIX_YX(mat) * det; + MATRIX_YY(out) = MATRIX_XX(mat) * det; +} + +EAPI void +eina_matrix2_identity(Eina_Matrix2 *m) +{ + MATRIX_XX(m) = 1.0; + MATRIX_XY(m) = 0.0; + + MATRIX_YX(m) = 0.0; + MATRIX_YY(m) = 1.0; +} + +EAPI void +eina_matrix2_array_set(Eina_Matrix2 *m, const double *v) +{ + memcpy(&MATRIX_XX(m), v, sizeof(double) * 4); +} + +EAPI void +eina_matrix2_copy(Eina_Matrix2 *dst, const Eina_Matrix2 *src) +{ + memcpy(dst, src, sizeof(Eina_Matrix2)); +} + +EAPI void +eina_matrix2_multiply(Eina_Matrix2 *out, const Eina_Matrix2 *mat_a, const Eina_Matrix2 *mat_b) +{ + if (eina_matrix2_type_get(mat_a) == EINA_MATRIX_TYPE_IDENTITY) + { + eina_matrix2_copy(out, mat_b); + return; + } + + if (eina_matrix2_type_get(mat_b) == EINA_MATRIX_TYPE_IDENTITY) + { + eina_matrix2_copy(out, mat_a); + return; + } + + MATRIX_XX(out) = MATRIX_XX(mat_a) * MATRIX_XX(mat_b) + MATRIX_YX(mat_a) * MATRIX_XY(mat_b); + MATRIX_YX(out) = MATRIX_XX(mat_a) * MATRIX_YX(mat_b) + MATRIX_YX(mat_a) * MATRIX_YY(mat_b); + + MATRIX_XY(out) = MATRIX_XY(mat_a) * MATRIX_XX(mat_b) + MATRIX_YY(mat_a) * MATRIX_XY(mat_b); + MATRIX_YY(out) = MATRIX_XY(mat_a) * MATRIX_YX(mat_b) + MATRIX_YY(mat_a) * MATRIX_YY(mat_b); +} + +EAPI void +eina_matrix2_multiply_copy(Eina_Matrix2 *out, const Eina_Matrix2 *mat_a, const Eina_Matrix2 *mat_b) +{ + if (out != mat_a && out != mat_b) + { + eina_matrix2_multiply(out, mat_a, mat_b); + } + else + { + Eina_Matrix2 tmp; + + eina_matrix2_multiply(&tmp, mat_a, mat_b); + eina_matrix2_copy(out, &tmp); + } } diff --git a/src/lib/eina/eina_matrix.h b/src/lib/eina/eina_matrix.h index 0558c98..14dcd8e 100644 --- a/src/lib/eina/eina_matrix.h +++ b/src/lib/eina/eina_matrix.h @@ -429,6 +429,23 @@ struct _Eina_Matrix4 }; /** + * @} + * @defgroup Eina_Matrix2 Matrices in floating point + * @ingroup Eina_Basic + * @brief Matrix definition and operations + * @{ + */ + +typedef struct _Eina_Matrix2 Eina_Matrix2; +struct _Eina_Matrix2 +{ + double xx; + double xy; + + double yx; + double yy; +}; +/** * @brief Return the type of the given floating point matrix. * * @param m The floating point matrix. @@ -597,11 +614,265 @@ EAPI void eina_matrix4_identity(Eina_Matrix4 *out); * @param a The first member of the multiplication * @param b The second member of the multiplication * + * @since 1.17 + */ +EAPI void eina_matrix4_multiply_copy(Eina_Matrix4 *out, + const Eina_Matrix4 *mat_a, const Eina_Matrix4 *mat_b); + +/** + * @brief Set array to matrix. + * + * @param m The result matrix + * @param v The the array[16] for set + * + * Set to matrix first 16 elements from array + * + * @since 1.17 + */ +EAPI void eina_matrix4_array_set(Eina_Matrix4 *m, const double *v); + +/** + * @brief Copy matrix. + * + * @param dst The matrix copy + * @param src The matrix for copy. + * + * @since 1.17 + */ +EAPI void eina_matrix4_copy(Eina_Matrix4 *dst, const Eina_Matrix4 *src); + +/** + * @brief Multiply two matrix with check + * + * @param out The resulting matrix + * @param a The first member of the multiplication + * @param b The second member of the multiplication + * + * @since 1.17 + */ +EAPI void eina_matrix4_multiply(Eina_Matrix4 *out, const Eina_Matrix4 *mat_a, + const Eina_Matrix4 *mat_b); + +/** + * @brief Set orthogonality matrix + * + * @param m The resulting matrix + * @param right The right value + * @param left The left value + * @param bottom The bottom value + * @param top The top value + * @param dneat The dnear value + * @param dfar The dfar value + * + * @since 1.17 + */ +EAPI void eina_matrix4_ortho_set(Eina_Matrix4 *m, + double left, double right, double bottom, double top, + double dnear, double dfar); + +/** + * @brief Set array to matrix. + * + * @param m The result matrix + * @param v The the array[9] for set + * + * Set to matrix first 9 elements from array + * + * @since 1.17 + */ +EAPI void eina_matrix3_array_set(Eina_Matrix3 *m, const double *v); + +/** + * @brief Copy matrix. + * + * @param dst The matrix copy + * @param src The matrix for copy. + * * @since 1.16 */ -EAPI void eina_matrix4_multiply(Eina_Matrix4 *out, - const Eina_Matrix4 *a, const Eina_Matrix4 *b); +EAPI void eina_matrix3_copy(Eina_Matrix3 *dst, const Eina_Matrix3 *src); + +/* + * @brief Multiply two matrix + * + * @param out The resulting matrix + * @param a The first member of the multiplication + * @param b The second member of the multiplication + * + * @since 1.17 + */ +EAPI void eina_matrix3_multiply(Eina_Matrix3 *out, const Eina_Matrix3 *mat_a, + const Eina_Matrix3 *mat_b); + +/** + * @brief Multiply two matrix + * + * @param out The resulting matrix + * @param a The first member of the multiplication + * @param b The second member of the multiplication + * + * @since 1.17 + */ +EAPI void eina_matrix3_multiply_copy(Eina_Matrix3 *out, const Eina_Matrix3 *mat_a, + const Eina_Matrix3 *mat_b); + +/** + * @brief Transform scale of matrix + * + * @param out The resulting matrix + * @param s_x The scale value for x + * @param s_y The scale value for y + * + * @since 1.17 + */ +EAPI void eina_matrix3_scale_transform_set(Eina_Matrix3 *out, double s_x, double s_y); + +/** + * @brief Transform position of matrix + * + * @param out The resulting matrix + * @param p_x The position value for x + * @param p_y The position value for y + * + * @since 1.17 + */ +EAPI void eina_matrix3_position_transform_set(Eina_Matrix3 *out, const double p_x, + const double p_y); + +/** + * @brief Set normal of the given matrix. + * + * @param out The result mtrix of normal + * @param m The matrix + * + * @since 1.17 + */ +EAPI void eina_normal3_matrix_get(Eina_Matrix3 *out, const Eina_Matrix4 *m); + +/** + * @brief Set the values of the coefficients of the given floating + * point matrix. + * + * @param m The floating point matrix. + * @param xx The first coefficient value. + * @param xy The second coefficient value. + * @param yx The fourth coefficient value. + * @param yy The fifth coefficient value. + * + * This function sets the values of the coefficients of the matrix + * @p m. No check is done on @p m. + * + * @see eina_matrix2_values_get() + * + * @since 1.17 + */ +EAPI void eina_matrix2_values_set(Eina_Matrix2 *m, double xx, double xy, + double yx, double yy); +/** + * @brief Get the values of the coefficients of the given floating + * point matrix. + * + * @param m The floating point matrix. + * @param xx The first coefficient value. + * @param xy The second coefficient value. + * @param yx The fourth coefficient value. + * @param yy The fifth coefficient value. + * + * This function gets the values of the coefficients of the matrix + * @p m. No check is done on @p m. + * + * @see eina_matrix2_values_set() + * + * @since 1.17 + */ +EAPI void eina_matrix2_values_get(const Eina_Matrix2 *m, double *xx, double *xy, + double *yx, double *yy); + +/** + * @brief Compute the inverse with check of the given matrix. + * + * @param m The matrix to inverse. + * @param m2 The inverse matrix. + * + * This function inverse the matrix @p m and stores the result in + * @p m2. No check is done on @p m or @p m2. If @p m can not be + * invertible, then @p m2 is set to the identity matrix. + * + * @since 1.17 + */ +EAPI void eina_matrix2_inverse(Eina_Matrix2 *out, const Eina_Matrix2 *mat); + +/** + * @brief Set the given floating point matrix to the identity matrix. + * + * @param m The floating point matrix to set + * + * This function sets @p m to the identity matrix. No check is done on + * @p m. + * + * @since 1.17 + */ +EAPI void eina_matrix2_identity(Eina_Matrix2 *m); + +/** + * @brief Set array to matrix. + * + * @param m The rsult matrix + * @param v The the array[4] for set + * + * Set to matrix first 4 elements from array + * + * @since 1.17 + */ +EAPI void eina_matrix2_array_set(Eina_Matrix2 *m, const double *v); + +/** + * @brief Copy matrix. + * + * @param dst The matrix copy + * @param src The matrix for copy. + * + * @since 1.17 + */ +EAPI void eina_matrix2_copy(Eina_Matrix2 *dst, const Eina_Matrix2 *src); + +/** + * @brief Multiply two matrix + * + * @param out The resulting matrix + * @param a The first member of the multiplication + * @param b The second member of the multiplication + * + * @since 1.17 + */ +EAPI void eina_matrix2_multiply(Eina_Matrix2 *out, const Eina_Matrix2 *mat_a, + const Eina_Matrix2 *mat_b); + +/** + * @brief Multiply two matrix with check + * + * @param out The resulting matrix + * @param a The first member of the multiplication + * @param b The second member of the multiplication + * + * @since 1.17 + */ +EAPI void eina_matrix2_multiply_copy(Eina_Matrix2 *out, const Eina_Matrix2 *mat_a, + const Eina_Matrix2 *mat_b); + +/** + * @brief Return the type of the given floating point matrix. + * + * @param m The floating point matrix. + * @return The type of the matrix. + * + * This function returns the type of the matrix @p m. No check is done + * on @p m. + * + * @since 1.17 + */ +EAPI Eina_Matrix_Type eina_matrix2_type_get(const Eina_Matrix2 *m); /** * @} -- 2.7.4