/*
 * C
 *
 * Copyright 2021-2025 MicroEJ Corp. All rights reserved.
 * MicroEJ Corp. PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

#if !defined LLVG_MATRIX_IMPL_H
#define LLVG_MATRIX_IMPL_H

#if defined __cplusplus
extern "C" {
#endif

// -----------------------------------------------------------------------------
// Includes
// -----------------------------------------------------------------------------

#include <sni.h>

// -----------------------------------------------------------------------------
// Defines
// -----------------------------------------------------------------------------

#define LLVG_MATRIX_SIZE 9

// --------------------------------------------------------------------------------
// VectorGraphics library's native functions names redefinition
// --------------------------------------------------------------------------------

/*
 * @brief Macros to declare native functions
 */
#define LLVG_MATRIX_IMPL_identity       Java_ej_microvg_MatrixNatives_identity
#define LLVG_MATRIX_IMPL_copy           Java_ej_microvg_MatrixNatives_copy
#define LLVG_MATRIX_IMPL_setTranslate   Java_ej_microvg_MatrixNatives_setTranslate
#define LLVG_MATRIX_IMPL_setScale       Java_ej_microvg_MatrixNatives_setScale
#define LLVG_MATRIX_IMPL_setRotate      Java_ej_microvg_MatrixNatives_setRotate
#define LLVG_MATRIX_IMPL_setConcat      Java_ej_microvg_MatrixNatives_setConcat
#define LLVG_MATRIX_IMPL_translate      Java_ej_microvg_MatrixNatives_translate
#define LLVG_MATRIX_IMPL_scale          Java_ej_microvg_MatrixNatives_scale
#define LLVG_MATRIX_IMPL_rotate         Java_ej_microvg_MatrixNatives_rotate
#define LLVG_MATRIX_IMPL_concatenate    Java_ej_microvg_MatrixNatives_concatenate
#define LLVG_MATRIX_IMPL_postTranslate  Java_ej_microvg_MatrixNatives_postTranslate
#define LLVG_MATRIX_IMPL_postScale      Java_ej_microvg_MatrixNatives_postScale
#define LLVG_MATRIX_IMPL_postRotate     Java_ej_microvg_MatrixNatives_postRotate
#define LLVG_MATRIX_IMPL_postConcat     Java_ej_microvg_MatrixNatives_postConcat
#define LLVG_MATRIX_IMPL_multiply       Java_ej_microvg_MatrixNatives_multiply

// --------------------------------------------------------------------------------
// VectorGraphics library's native functions
// --------------------------------------------------------------------------------

/*
 * @brief Creates an identity matrix.
 *
 * @param[in] matrix: the matrix to initialize
 */
void LLVG_MATRIX_IMPL_identity(jfloat *matrix);

/*
 * @brief Deep copies the given matrix into destination.
 *
 * @param[in] dest: the matrix to copy to
 * @param[in] src: the matrix to copy from
 */
void LLVG_MATRIX_IMPL_copy(jfloat *dest, const jfloat *src);

/*
 * @brief Sets the matrix to the concatenation of the two specified matrices.
 * <p>
 * Contrary to LLVG_MATRIX_IMPL_setConcat(), the target is not a parameter.
 *
 * @param[in] dest: the destination
 * @param[in] a: the first matrix
 * @param[in] b: the second matrix
 */
void LLVG_MATRIX_IMPL_multiply(jfloat *dest, const jfloat *a, const jfloat *b);

/*
 * @brief Sets the matrix to translate by (dx, dy).
 *
 * @param[in] matrix: the matrix to translate
 * @param[in] dx: the translation on x
 * @param[in] dy: the translation on y
 */
void LLVG_MATRIX_IMPL_setTranslate(jfloat *matrix, jfloat dx, jfloat dy);

/*
 * @brief Sets the matrix to scale by (sx, sy).
 *
 * @param[in] matrix: the matrix to scale
 * @param[in] sx: the scale on x
 * @param[in] sy: the scale on y
 */
void LLVG_MATRIX_IMPL_setScale(jfloat *matrix, jfloat sx, jfloat sy);

/*
 * @brief Sets the matrix to rotate about (0,0) by the specified number of degrees.
 *
 * @param[in] matrix: the matrix to rotate
 * @param[in] degrees: the degrees to rotate
 */
void LLVG_MATRIX_IMPL_setRotate(jfloat *matrix, jfloat degrees);

/*
 * @brief Sets the matrix to the concatenation of the two specified matrices.
 * <p>
 * Either of the two matrices may also be the target matrix, that is
 * <code>matrixA.setConcat(matrixA, matrixB);</code> is valid.
 *
 * @param[in] dest: the destination
 * @param[in] a: the first matrix
 * @param[in] b: the second matrix
 */
void LLVG_MATRIX_IMPL_setConcat(jfloat *dest, const jfloat *a, const jfloat *b);

/*
 * @brief Preconcats the matrix with the specified translation. M' = M * T(dx, dy)
 *
 * @param[in] matrix: the matrix to translate
 * @param[in] x: the translation on x
 * @param[in] y: the translation on y
 */
void LLVG_MATRIX_IMPL_translate(jfloat *matrix, jfloat x, jfloat y);

/*
 * @brief Preconcats the matrix with the specified scale. M' = M * S(sx, sy)
 *
 * @param[in] matrix: the matrix to scale
 * @param[in] scaleX: the scale on x
 * @param[in] scaleY: the scale on y
 */
void LLVG_MATRIX_IMPL_scale(jfloat *matrix, jfloat scaleX, jfloat scaleY);

/*
 * @brief Preconcats the matrix with the specified rotation. M' = M * R(degrees)
 *
 * @param[in] matrix: the matrix to rotate
 * @param[in] degrees: the degrees to rotate
 */
void LLVG_MATRIX_IMPL_rotate(jfloat *matrix, jfloat degrees);

/*
 * @brief Preconcats the matrix with the specified matrix. M' = M * other
 *
 * @param[in] matrix: the matrix to concat
 * @param[in] other: the matrix to concat with
 */
void LLVG_MATRIX_IMPL_concatenate(jfloat *matrix, const jfloat *other);

/*
 * @brief Postconcats the matrix with the specified translation. M' = T(dx, dy) * M
 *
 * @param[in] matrix: the matrix to translate
 * @param[in] dx: the translation on x
 * @param[in] dy: the translation on y
 */
void LLVG_MATRIX_IMPL_postTranslate(jfloat *matrix, jfloat dx, jfloat dy);

/*
 * @brief Postconcats the matrix with the specified scale. M' = S(sx, sy) * M
 *
 * @param[in] matrix: the matrix to scale
 * @param[in] sx: the scale on x
 * @param[in] sy: the scale on y
 */
void LLVG_MATRIX_IMPL_postScale(jfloat *matrix, jfloat sx, jfloat sy);

/*
 * @brief Postconcats the matrix with the specified rotation. M' = R(degrees) * M
 *
 * @param[in] matrix: the matrix to rotate
 * @param[in] degrees: the degrees to rotate
 */
void LLVG_MATRIX_IMPL_postRotate(jfloat *matrix, jfloat degrees);

/*
 * @brief Postconcats the matrix with the specified matrix. M' = other * M
 *
 * @param[in] matrix: the matrix to concat
 * @param[in] other: the matrix to concat with
 */
void LLVG_MATRIX_IMPL_postConcat(jfloat *matrix, const jfloat *other);

/*
 * @brief Transforms a point by the specified matrix.
 *
 * @param[in/out] x: the X-point to transform
 * @param[in/out] y: the Y-point to transform
 * @param[in] matrix: the transformation to apply
 */
void LLVG_MATRIX_IMPL_transformPoint(jfloat *x, jfloat *y, const jfloat *matrix);

// -----------------------------------------------------------------------------
// EOF
// -----------------------------------------------------------------------------

#ifdef __cplusplus
}
#endif

#endif // !defined LLVG_MATRIX_IMPL_H
