aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gmisc/gmisc_matrix2d.c196
-rw-r--r--src/gmisc/sys_defs.h260
-rw-r--r--src/gmisc/sys_make.mk1
3 files changed, 451 insertions, 6 deletions
diff --git a/src/gmisc/gmisc_matrix2d.c b/src/gmisc/gmisc_matrix2d.c
new file mode 100644
index 00000000..dd13603e
--- /dev/null
+++ b/src/gmisc/gmisc_matrix2d.c
@@ -0,0 +1,196 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file src/gmisc/gmisc_matrix2d.c
+ * @brief GMISC 2D matrix operations code.
+ */
+#include "gfx.h"
+
+#if GFX_USE_GMISC
+
+#if GMISC_NEED_MATRIXFLOAT2D
+
+#if !GMISC_NEED_FASTTRIG
+ #include <math.h>
+#endif
+
+void gmiscMatrixFloat2DSetIdentity(MatrixFloat2D *m) {
+ m->a00 = m->a11 = m->a22 = 1.0;
+ m->a01 = m->a02 = m->a10 = m->a12 = m->a20 = m->a21 = 0.0;
+}
+
+void gmiscMatrixFloat2DMultiply(MatrixFloat2D *dst, const MatrixFloat2D *src1, const MatrixFloat2D *src2) {
+ dst->a00 = src1->a00*src2->a00 + src1->a01*src2->a10 + src1->a02*src2->a20;
+ dst->a01 = src1->a00*src2->a01 + src1->a01*src2->a11 + src1->a02*src2->a21;
+ dst->a02 = src1->a00*src2->a02 + src1->a01*src2->a12 + src1->a02*src2->a22;
+ dst->a10 = src1->a10*src2->a00 + src1->a11*src2->a10 + src1->a12*src2->a20;
+ dst->a11 = src1->a10*src2->a01 + src1->a11*src2->a11 + src1->a12*src2->a21;
+ dst->a12 = src1->a10*src2->a02 + src1->a11*src2->a12 + src1->a12*src2->a22;
+ dst->a20 = src1->a20*src2->a00 + src1->a21*src2->a10 + src1->a22*src2->a20;
+ dst->a21 = src1->a20*src2->a01 + src1->a21*src2->a11 + src1->a22*src2->a21;
+ dst->a22 = src1->a20*src2->a02 + src1->a21*src2->a12 + src1->a22*src2->a22;
+}
+
+void gmiscMatrixFloat2DApplyTranslation(MatrixFloat2D *dst, const MatrixFloat2D *src, float tx, float ty) {
+ if (src) {
+ dst->a00 = src->a00; dst->a01 = src->a01; dst->a02 = src->a02+tx;
+ dst->a10 = src->a10; dst->a11 = src->a11; dst->a12 = src->a12+ty;
+ dst->a20 = src->a20; dst->a21 = src->a21; dst->a22 = src->a22;
+ } else {
+ dst->a00 = 1.0; dst->a01 = 0.0; dst->a02 = tx;
+ dst->a10 = 0.0; dst->a11 = 1.0; dst->a12 = ty;
+ dst->a20 = 0.0; dst->a21 = 0.0; dst->a22 = 1.0;
+ }
+}
+
+void gmiscMatrixFloat2DApplyScale(MatrixFloat2D *dst, const MatrixFloat2D *src, float sx, float sy) {
+ if (src) {
+ dst->a00 = src->a00*sx; dst->a01 = src->a01*sy; dst->a02 = src->a02;
+ dst->a10 = src->a10*sx; dst->a11 = src->a11*sy; dst->a12 = src->a12;
+ dst->a20 = src->a20*sx; dst->a21 = src->a21*sy; dst->a22 = src->a22;
+ } else {
+ dst->a00 = sx; dst->a01 = 0.0; dst->a02 = 0.0;
+ dst->a10 = 0.0; dst->a11 = sy; dst->a12 = 0.0;
+ dst->a20 = 0.0; dst->a21 = 0.0; dst->a22 = 1.0;
+ }
+}
+
+void gmiscMatrixFloat2DApplyShear(MatrixFloat2D *dst, const MatrixFloat2D *src, float sx, float sy) {
+ if (src) {
+ dst->a00 = src->a00 + src->a01*sy; dst->a01 = src->a00*sx + src->a01; dst->a02 = src->a02;
+ dst->a10 = src->a10 + src->a11*sy; dst->a11 = src->a10*sx + src->a11; dst->a12 = src->a12;
+ dst->a20 = src->a20 + src->a21*sy; dst->a21 = src->a20*sx + src->a21; dst->a22 = src->a22;
+ } else {
+ dst->a00 = 1.0; dst->a01 = sx; dst->a02 = 0.0;
+ dst->a10 = sy; dst->a11 = 1.0; dst->a12 = 0.0;
+ dst->a20 = 0.0; dst->a21 = 0.0; dst->a22 = 1.0;
+ }
+}
+
+void gmiscMatrixFloat2DApplyRotation(MatrixFloat2D *dst, const MatrixFloat2D *src, int angle) {
+ float s, c;
+
+ #if GMISC_NEED_FASTTRIG
+ s = fsin(angle);
+ c = fcos(angle);
+ #else
+ c = angle*M_PI/180;
+ s = sin(c);
+ c = cos(c);
+ #endif
+
+ if (src) {
+ dst->a00 = src->a00*c - src->a01*s; dst->a01 = src->a00*s + src->a01*c; dst->a02 = src->a02;
+ dst->a10 = src->a10*c - src->a11*s; dst->a11 = src->a10*s + src->a11*c; dst->a12 = src->a12;
+ dst->a20 = src->a20*c - src->a21*s; dst->a21 = src->a20*s + src->a21*c; dst->a22 = src->a22;
+ } else {
+ dst->a00 = c; dst->a01 = s; dst->a02 = 0.0;
+ dst->a10 = -s; dst->a11 = c; dst->a12 = 0.0;
+ dst->a20 = 0.0; dst->a21 = 0.0; dst->a22 = 1.0;
+ }
+}
+
+void gmiscMatrixFloat2DApplyToPoints(point *dst, const point *src, const MatrixFloat2D *m, int cnt) {
+ float x;
+
+ for( ;cnt--; dst++, src++) {
+ x = src->x; // This allows in-place operation
+ dst->x = round(x*m->a00+src->y*m->a01+m->a02);
+ dst->y = round(x*m->a10+src->y*m->a11+m->a12);
+ }
+}
+
+#endif // GMISC_NEED_MATRIXFLOAT2D
+
+#if GMISC_NEED_MATRIXFIXED2D
+
+void gmiscMatrixFixed2DSetIdentity(MatrixFixed2D *m) {
+ m->a00 = m->a11 = m->a22 = FIXED(1);
+ m->a01 = m->a02 = m->a10 = m->a12 = m->a20 = m->a21 = 0;
+}
+
+void gmiscMatrixFixed2DMultiply(MatrixFixed2D *dst, const MatrixFixed2D *src1, const MatrixFixed2D *src2) {
+ dst->a00 = FIXEDMUL(src1->a00,src2->a00) + FIXEDMUL(src1->a01,src2->a10) + FIXEDMUL(src1->a02,src2->a20);
+ dst->a01 = FIXEDMUL(src1->a00,src2->a01) + FIXEDMUL(src1->a01,src2->a11) + FIXEDMUL(src1->a02,src2->a21);
+ dst->a02 = FIXEDMUL(src1->a00,src2->a02) + FIXEDMUL(src1->a01,src2->a12) + FIXEDMUL(src1->a02,src2->a22);
+ dst->a10 = FIXEDMUL(src1->a10,src2->a00) + FIXEDMUL(src1->a11,src2->a10) + FIXEDMUL(src1->a12,src2->a20);
+ dst->a11 = FIXEDMUL(src1->a10,src2->a01) + FIXEDMUL(src1->a11,src2->a11) + FIXEDMUL(src1->a12,src2->a21);
+ dst->a12 = FIXEDMUL(src1->a10,src2->a02) + FIXEDMUL(src1->a11,src2->a12) + FIXEDMUL(src1->a12,src2->a22);
+ dst->a20 = FIXEDMUL(src1->a20,src2->a00) + FIXEDMUL(src1->a21,src2->a10) + FIXEDMUL(src1->a22,src2->a20);
+ dst->a21 = FIXEDMUL(src1->a20,src2->a01) + FIXEDMUL(src1->a21,src2->a11) + FIXEDMUL(src1->a22,src2->a21);
+ dst->a22 = FIXEDMUL(src1->a20,src2->a02) + FIXEDMUL(src1->a21,src2->a12) + FIXEDMUL(src1->a22,src2->a22);
+}
+
+void gmiscMatrixFixed2DApplyTranslation(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed tx, fixed ty) {
+ if (src) {
+ dst->a00 = src->a00; dst->a01 = src->a01; dst->a02 = src->a02+tx;
+ dst->a10 = src->a10; dst->a11 = src->a11; dst->a12 = src->a12+ty;
+ dst->a20 = src->a20; dst->a21 = src->a21; dst->a22 = src->a22;
+ } else {
+ dst->a00 = FIXED(1); dst->a01 = 0; dst->a02 = tx;
+ dst->a10 = 0; dst->a11 = FIXED(1); dst->a12 = ty;
+ dst->a20 = 0; dst->a21 = 0; dst->a22 = FIXED(1);
+ }
+}
+
+void gmiscMatrixFixed2DApplyScale(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed sx, fixed sy) {
+ if (src) {
+ dst->a00 = FIXEDMUL(sx,src->a00); dst->a01 = FIXEDMUL(sy,src->a01); dst->a02 = src->a02;
+ dst->a10 = FIXEDMUL(sx,src->a10); dst->a11 = FIXEDMUL(sy,src->a11); dst->a12 = src->a12;
+ dst->a20 = FIXEDMUL(sx,src->a20); dst->a21 = FIXEDMUL(sy,src->a21); dst->a22 = src->a22;
+ } else {
+ dst->a00 = sx; dst->a01 = 0; dst->a02 = 0;
+ dst->a10 = 0; dst->a11 = sy; dst->a12 = 0;
+ dst->a20 = 0; dst->a21 = 0; dst->a22 = FIXED(1);
+ }
+}
+
+void gmiscMatrixFixed2DApplyShear(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed sx, fixed sy) {
+ if (src) {
+ dst->a00 = src->a00 + FIXEDMUL(sy,src->a01); dst->a01 = FIXEDMUL(sx,src->a00) + src->a01; dst->a02 = src->a02;
+ dst->a10 = src->a10 + FIXEDMUL(sy,src->a11); dst->a11 = FIXEDMUL(sx,src->a10) + src->a11; dst->a12 = src->a12;
+ dst->a20 = src->a20 + FIXEDMUL(sy,src->a21); dst->a21 = FIXEDMUL(sx,src->a20) + src->a21; dst->a22 = src->a22;
+ } else {
+ dst->a00 = FIXED(1); dst->a01 = sx; dst->a02 = 0;
+ dst->a10 = sy; dst->a11 = FIXED(1); dst->a12 = 0;
+ dst->a20 = 0; dst->a21 = 0; dst->a22 = FIXED(1);
+ }
+}
+
+#if GMISC_NEED_FIXEDTRIG
+ void gmiscMatrixFixed2DApplyRotation(MatrixFixed2D *dst, const MatrixFixed2D *src, int angle) {
+ fixed s, c;
+
+ s = ffsin(angle);
+ c = ffcos(angle);
+
+ if (src) {
+ dst->a00 = FIXEDMUL(c,src->a00) - FIXEDMUL(s,src->a01); dst->a01 = FIXEDMUL(s,src->a00) + FIXEDMUL(c,src->a01); dst->a02 = src->a02;
+ dst->a10 = FIXEDMUL(c,src->a10) - FIXEDMUL(s,src->a11); dst->a11 = FIXEDMUL(s,src->a10) + FIXEDMUL(c,src->a11); dst->a12 = src->a12;
+ dst->a20 = FIXEDMUL(c,src->a20) - FIXEDMUL(s,src->a21); dst->a21 = FIXEDMUL(s,src->a20) + FIXEDMUL(c,src->a21); dst->a22 = src->a22;
+ } else {
+ dst->a00 = c; dst->a01 = s; dst->a02 = 0;
+ dst->a10 = -s; dst->a11 = c; dst->a12 = 0;
+ dst->a20 = 0; dst->a21 = 0; dst->a22 = FIXED(1);
+ }
+ }
+#endif
+
+void gmiscMatrixFixed2DApplyToPoints(point *dst, const point *src, const MatrixFixed2D *m, int cnt) {
+ coord_t x;
+
+ for( ;cnt--; dst++, src++) {
+ x = src->x; // This allows in-place operation
+ dst->x = NONFIXED(x*m->a00+src->y*m->a01+m->a02+FIXED0_5);
+ dst->y = NONFIXED(x*m->a10+src->y*m->a11+m->a12+FIXED0_5);
+ }
+}
+
+#endif // GMISC_NEED_MATRIXFIXED2D
+
+#endif // GFX_USE_GMISC
diff --git a/src/gmisc/sys_defs.h b/src/gmisc/sys_defs.h
index 4b5a1127..813fa07e 100644
--- a/src/gmisc/sys_defs.h
+++ b/src/gmisc/sys_defs.h
@@ -25,6 +25,9 @@
/* Type definitions */
/*===========================================================================*/
+// Forward definition
+typedef struct point point;
+
/**
* @brief Sample data formats
* @note These are defined regardless of whether you use the GMISC module
@@ -60,11 +63,13 @@ typedef int32_t fixed;
* @brief Macros to convert to and from a fixed point.
* @{
*/
-#define FIXED(x) ((fixed)(x)<<16) /* @< integer to fixed */
-#define NONFIXED(x) ((x)>>16) /* @< fixed to integer */
-#define FIXED0_5 32768 /* @< 0.5 as a fixed (used for rounding) */
-#define FP2FIXED(x) ((fixed)((x)*65536.0)) /* @< floating point to fixed */
-#define FIXED2FP(x) ((double)(x)/65536.0) /* @< fixed to floating point */
+#define FIXED(x) ((fixed)(x)<<16) /* @< integer to fixed */
+#define NONFIXED(x) ((x)>>16) /* @< fixed to integer */
+#define FIXED0_5 32768 /* @< 0.5 as a fixed (used for rounding) */
+#define FP2FIXED(x) ((fixed)((x)*65536.0)) /* @< floating point to fixed */
+#define FIXED2FP(x) ((double)(x)/65536.0) /* @< fixed to floating point */
+#define FIXEDMUL(a,b) ((fixed)((((long long)(a))*(b))>>16)) /* @< fixed,fixed multiplication */
+#define FIXEDMULINT(a,b) ((a)*(b)) /* @< integer,fixed multiplication */
/** @} */
/**
@@ -90,6 +95,7 @@ extern "C" {
#if GMISC_NEED_ARRAYOPS || defined(__DOXYGEN__)
/**
* @brief Convert from one array format to another array format.
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_ARRAYOPS
*
* @param[in] srcfmt The format of the source array
* @param[in] src The source array
@@ -131,6 +137,7 @@ extern "C" {
/**
* @brief Fast Table Based Trig functions
* @return A double in the range -1.0 .. 0.0 .. 1.0
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_FASTTRIG
*
* @param[in] degrees The angle in degrees (not radians)
*
@@ -145,6 +152,7 @@ extern "C" {
*
* @brief Fast Table Based Trig functions
* @return A double in the range -1.0 .. 0.0 .. 1.0
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_FASTTRIG
*
* @param[in] degrees The angle in degrees 0 .. 359
*
@@ -166,6 +174,7 @@ extern "C" {
/**
* @brief Fast Table Based Trig functions
* @return A fixed point in the range -1.0 .. 0.0 .. 1.0
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_FIXEDTRIG
*
* @param[in] degrees The angle in degrees (not radians)
*
@@ -180,6 +189,7 @@ extern "C" {
*
* @brief Fast Table Based Trig functions
* @return A fixed point in the range -1.0 .. 0.0 .. 1.0
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_FIXEDTRIG
*
* @param[in] degrees The angle in degrees 0 .. 359
*
@@ -195,10 +205,11 @@ extern "C" {
/** @} */
#endif
-#if GMISC_NEED_INVSQRT
+#if GMISC_NEED_INVSQRT || defined(__DOXYGEN__)
/**
* @brief Fast inverse square root function (x^-1/2)
* @return The approximate inverse square root
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_INVSQRT
*
* @param[in] n The number to find the inverse square root of
*
@@ -212,6 +223,243 @@ extern "C" {
*/
float invsqrt(float n);
#endif
+
+#if GMISC_NEED_MATRIXFLOAT2D || defined(__DOXYGEN__)
+
+ /**
+ * @brief A matrix for doing 2D graphics using floats
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
+ */
+ typedef struct MatrixFloat2D {
+ float a00, a01, a02;
+ float a10, a11, a12;
+ float a20, a21, a22;
+ } MatrixFloat2D;
+
+ /**
+ * @brief Apply the matrix to a set of points
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
+ *
+ * @param[in] dst The destination array of points
+ * @param[in] src The source array of points
+ * @param[in] m The matrix to apply
+ * @param[in] cnt How many points are in the array
+ *
+ * @note In-place matrix application is allowed ie. dst = src
+ *
+ * @api
+ */
+ void gmiscMatrixFloat2DApplyToPoints(point *dst, const point *src, const MatrixFloat2D *m, int cnt);
+
+ /**
+ * @brief Set the 2D matrix to the identity matrix
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
+ *
+ * @param[in] m The matrix to set to identity
+ *
+ * @api
+ */
+ void gmiscMatrixFloat2DSetIdentity(MatrixFloat2D *m);
+
+ /**
+ * @brief Multiple two 2D matrixes together
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
+ *
+ * @param[in] dst The destination matrix
+ * @param[in] src1 The first source matrix
+ * @param[in] src2 The second source matrix
+ *
+ * @note In-place matrix application is NOT allowed ie. dst != src1, dst != src2
+ *
+ * @api
+ */
+ void gmiscMatrixFloat2DMultiply(MatrixFloat2D *dst, const MatrixFloat2D *src1, const MatrixFloat2D *src2);
+
+ /**
+ * @brief Add an x,y translation to a matrix
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
+ *
+ * @param[in] dst The destination matrix
+ * @param[in] src The source matrix. Can be NULL
+ * @param[in] tx, ty The x and y translation to apply
+ *
+ * @note In-place matrix operation is NOT allowed ie. dst != src
+ * @note If no source matrix is provided, it is equivalent to applying the operation
+ * to an identity matrix. It also is a much simpler operation requiring no multiplication.
+ *
+ * @api
+ */
+ void gmiscMatrixFloat2DApplyTranslation(MatrixFloat2D *dst, const MatrixFloat2D *src, float tx, float ty);
+
+ /**
+ * @brief Add x,y scaling to a matrix
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
+ *
+ * @param[in] dst The destination matrix
+ * @param[in] src The source matrix. Can be NULL
+ * @param[in] sx, sy The scaling to apply in the x and y direction. Negative numbers give reflection.
+ *
+ * @note In-place matrix operation is NOT allowed ie. dst != src
+ * @note If no source matrix is provided, it is equivalent to applying the operation
+ * to an identity matrix. It also is a much simpler operation requiring no multiplication.
+ *
+ * @api
+ */
+ void gmiscMatrixFloat2DApplyScale(MatrixFloat2D *dst, const MatrixFloat2D *src, float sx, float sy);
+
+ /**
+ * @brief Add x,y shear to a matrix
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
+ *
+ * @param[in] dst The destination matrix
+ * @param[in] src The source matrix. Can be NULL
+ * @param[in] sx, sy The shear to apply in the x and y direction.
+ *
+ * @note In-place matrix operation is NOT allowed ie. dst != src
+ * @note If no source matrix is provided, it is equivalent to applying the operation
+ * to an identity matrix. It also is a much simpler operation requiring no multiplication.
+ *
+ * @api
+ */
+ void gmiscMatrixFloat2DApplyShear(MatrixFloat2D *dst, const MatrixFloat2D *src, float sx, float sy);
+
+ /**
+ * @brief Add rotation to a matrix
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFLOAT2D
+ *
+ * @param[in] dst The destination matrix
+ * @param[in] src The source matrix. Can be NULL
+ * @param[in] angle The angle to apply in degrees (not radians).
+ *
+ * @note In-place matrix operation is NOT allowed ie. dst != src
+ * @note If no source matrix is provided, it is equivalent to applying the operation
+ * to an identity matrix. It also is a much simpler operation.
+ * @note If GMISC_NEED_FASTTRIG is defined then the fast table sin and cos lookup's will be used
+ * rather than the C library versions.
+ *
+ * @api
+ */
+ void gmiscMatrixFloat2DApplyRotation(MatrixFloat2D *dst, const MatrixFloat2D *src, int angle);
+#endif
+
+#if GMISC_NEED_MATRIXFIXED2D || defined(__DOXYGEN__)
+
+ /**
+ * @brief A matrix for doing 2D graphics using fixed point maths
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D
+ */
+ typedef struct MatrixFixed2D {
+ fixed a00, a01, a02;
+ fixed a10, a11, a12;
+ fixed a20, a21, a22;
+ } MatrixFixed2D;
+
+ /**
+ * @brief Apply the matrix to a set of points
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D
+ *
+ * @param[in] dst The destination array of points
+ * @param[in] src The source array of points
+ * @param[in] m The matrix to apply
+ * @param[in] cnt How many points are in the array
+ *
+ * @note In-place matrix application is allowed ie. dst = src
+ *
+ * @api
+ */
+ void gmiscMatrixFixed2DApplyToPoints(point *dst, const point *src, const MatrixFixed2D *m, int cnt);
+
+ /**
+ * @brief Set the 2D matrix to the identity matrix
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D
+ *
+ * @param[in] m The matrix to set to identity
+ *
+ * @api
+ */
+ void gmiscMatrixFixed2DSetIdentity(MatrixFixed2D *m);
+
+ /**
+ * @brief Multiple two 2D matrixes together
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D
+ *
+ * @param[in] dst The destination matrix
+ * @param[in] src1 The first source matrix
+ * @param[in] src2 The second source matrix
+ *
+ * @note In-place matrix application is NOT allowed ie. dst != src1, dst != src2
+ *
+ * @api
+ */
+ void gmiscMatrixFixed2DMultiply(MatrixFixed2D *dst, const MatrixFixed2D *src1, const MatrixFixed2D *src2);
+
+ /**
+ * @brief Add an x,y translation to a matrix
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D
+ *
+ * @param[in] dst The destination matrix
+ * @param[in] src The source matrix. Can be NULL
+ * @param[in] tx, ty The x and y translation to apply
+ *
+ * @note In-place matrix operation is NOT allowed ie. dst != src
+ * @note If no source matrix is provided, it is equivalent to applying the operation
+ * to an identity matrix. It also is a much simpler operation requiring no multiplication.
+ *
+ * @api
+ */
+ void gmiscMatrixFixed2DApplyTranslation(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed tx, fixed ty);
+
+ /**
+ * @brief Add x,y scaling to a matrix
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D
+ *
+ * @param[in] dst The destination matrix
+ * @param[in] src The source matrix. Can be NULL
+ * @param[in] sx, sy The scaling to apply in the x and y direction. Negative numbers give reflection.
+ *
+ * @note In-place matrix operation is NOT allowed ie. dst != src
+ * @note If no source matrix is provided, it is equivalent to applying the operation
+ * to an identity matrix. It also is a much simpler operation requiring no multiplication.
+ *
+ * @api
+ */
+ void gmiscMatrixFixed2DApplyScale(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed sx, fixed sy);
+
+ /**
+ * @brief Add x,y shear to a matrix
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D
+ *
+ * @param[in] dst The destination matrix
+ * @param[in] src The source matrix. Can be NULL
+ * @param[in] sx, sy The shear to apply in the x and y direction.
+ *
+ * @note In-place matrix operation is NOT allowed ie. dst != src
+ * @note If no source matrix is provided, it is equivalent to applying the operation
+ * to an identity matrix. It also is a much simpler operation requiring no multiplication.
+ *
+ * @api
+ */
+ void gmiscMatrixFixed2DApplyShear(MatrixFixed2D *dst, const MatrixFixed2D *src, fixed sx, fixed sy);
+
+ #if GMISC_NEED_FIXEDTRIG || defined(__DOXYGEN__)
+ /**
+ * @brief Add rotation to a matrix
+ * @pre Requires GFX_USE_GMISC and GMISC_NEED_MATRIXFIXED2D and GMISC_NEED_FIXEDTRIG
+ *
+ * @param[in] dst The destination matrix
+ * @param[in] src The source matrix. Can be NULL
+ * @param[in] angle The angle to apply in degrees (not radians).
+ *
+ * @note In-place matrix operation is NOT allowed ie. dst != src
+ * @note If no source matrix is provided, it is equivalent to applying the operation
+ * to an identity matrix. It also is a much simpler operation requiring no multiplication.
+ *
+ * @api
+ */
+ void gmiscMatrixFixed2DApplyRotation(MatrixFixed2D *dst, const MatrixFixed2D *src, int angle);
+ #endif
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/src/gmisc/sys_make.mk b/src/gmisc/sys_make.mk
index 0431c134..203910e6 100644
--- a/src/gmisc/sys_make.mk
+++ b/src/gmisc/sys_make.mk
@@ -1,3 +1,4 @@
GFXSRC += $(GFXLIB)/src/gmisc/gmisc_gmisc.c \
$(GFXLIB)/src/gmisc/gmisc_arrayops.c \
+ $(GFXLIB)/src/gmisc/gmisc_matrix2d.c \
$(GFXLIB)/src/gmisc/gmisc_trig.c