From: Jean-Philippe Bruyère Date: Fri, 28 Aug 2020 16:49:03 +0000 (+0200) Subject: doc wip X-Git-Tag: v0.2.0~94 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=93dc4d861ed1e4ed15e91307158c11b7db5f1f5f;p=jp%2Fvkvg.git doc wip --- diff --git a/include/vkvg.h b/include/vkvg.h index 6157094..8f90ee3 100644 --- a/include/vkvg.h +++ b/include/vkvg.h @@ -222,7 +222,6 @@ typedef struct { float a; } vkvg_color_t; - typedef struct { float ascent; float descent; @@ -255,7 +254,7 @@ typedef struct { typedef struct _vkvg_text_run_t* VkvgText; /** - * @brief Opaque pointer on a Vkvg Context structure. + * @brief The Vkvg drawing Context. * * A #VkvgContext is the central object for drawing operations. * #vkvg_context_t structure internals this pointer point to are @@ -268,7 +267,7 @@ typedef struct _vkvg_context_t* VkvgContext; * A #VkvgSurface represents an image, either as the destination * of a drawing operation or as source when drawing onto another * surface. To draw to a #VkvgSurface, create a vkvg context - * with the surface as the target, using vkvg_create(). + * with the surface as the target, using #vkvg_create(). * hidden internals. * * #VkvgSurface are created with a @ref VkvgDevice which has to stay @@ -295,7 +294,7 @@ typedef struct _vkvg_pattern_t* VkvgPattern; * This is the reference documentation for handling matrices to use as transformation in drawing operations. * Matrix computations in vkvg are taken from the cairo library. * @{ */ -#define VKVG_IDENTITY_MATRIX {1,0,0,1,0,0} +#define VKVG_IDENTITY_MATRIX {1,0,0,1,0,0}/*!< The identity matrix*/ /** * @xx: xx component of the affine transformation * @yx: yx component of the affine transformation @@ -324,13 +323,14 @@ typedef struct { * @brief Set matrix to identity * * Initialize members of the supplied #vkvg_matrix_t to make an identity matrix of it. - * @param matrix matrix to set to identity. + * @param matrix a valid #vkvg_matrix_t pointer. */ void vkvg_matrix_init_identity (vkvg_matrix_t *matrix); /** * @brief Matrix initialization. * * Initialize members of the supplied matrix to the values passed as arguments. + * Resulting matrix will hold an affine transformation defined by the parameters. * @param matrix a valid #vkvg_matrix_t pointer * @param xx xx component of the affine transformation * @param yx yx component of the affine transformation @@ -366,20 +366,91 @@ void vkvg_matrix_init_scale (vkvg_matrix_t *matrix, float sx, float sy); * * Initialize members of the supplied matrix to create a new rotation matrix * @param matrix a valid #vkvg_matrix_t pointer - * @param angle of rotation, in radians. The direction of rotation + * @param radians angle of rotation, in radians. The direction of rotation * is defined such that positive angles rotate in the direction from * the positive X axis toward the positive Y axis. With the default * axis orientation of vkvg, positive angles rotate in a clockwise * direction. */ void vkvg_matrix_init_rotate (vkvg_matrix_t *matrix, float radians); +/** + * @brief apply translation on matrix + * + * Apply the translation defined by tx and ty on the supplied matrix. + * The effect of the new transformation is to first translate the coordinates by tx and ty, + * then apply the original transformation to the coordinates. + * @param matrix a valid #vkvg_matrix_t pointer + * @param tx translation in the x direction + * @param ty translation in the y direction + */ void vkvg_matrix_translate (vkvg_matrix_t *matrix, float tx, float ty); +/** + * @brief apply scale on matrix + * + * Apply scaling by sx and sy on the supplied transformation matrix. + * The effect of the new transformation is to first scale the coordinates by sx and sy, + * then apply the original transformation to the coordinates. + * @param matrix a valid #vkvg_matrix_t pointer on which the scaling will be applied. + * @param sx scale in the x direction + * @param sy scale in the y direction + */ void vkvg_matrix_scale (vkvg_matrix_t *matrix, float sx, float sy); +/** + * @brief apply rotation on matrix + * + * Apply a rotation of radians on the supplied matrix. + * The effect of the new transformation is to first rotate the coordinates by radians, + * then apply the original transformation to the coordinates. + * @param matrix a valid #vkvg_matrix_t pointer on which the rotation will be applied + * @param radians angle of rotation in radians. The direction of rotation is defined such that positive angles + * rotate in the direction from the positive X axis toward the positive Y axis. + * With the default axis orientation of cairo, positive angles rotate in a clockwise direction. + */ void vkvg_matrix_rotate (vkvg_matrix_t *matrix, float radians); +/** + * @brief matrices multiplication + * + * compute the multiplication of two matrix. + * @param result a valid #vkvg_matrix_t pointer to hold the resulting matrix + * @param a first operand of the multiplication + * @param b second operand of the multiplication + */ void vkvg_matrix_multiply (vkvg_matrix_t *result, const vkvg_matrix_t *a, const vkvg_matrix_t *b); +/** + * @brief transform distances + * + * Transforms the distance vector (dx ,dy ) by matrix . This is similar to #cairo_matrix_transform_point() except that the translation + * components of the transformation are ignored. The calculation of the returned vector is as follows: + * @code + * dx2 = dx1 * a + dy1 * c; + * dy2 = dx1 * b + dy1 * d; + * @endcode + * Affine transformations are position invariant, so the same vector always transforms to the same vector. If (x1 ,y1 ) transforms to (x2 ,y2 ) + * then (x1 +dx1 ,y1 +dy1 ) will transform to (x1 +dx2 ,y1 +dy2 ) for all values of x1 and x2 . + * @param matrix a valid #vkvg_matrix_t to use to transform distance + * @param dx X component of a distance vector. An in/out parameter + * @param dy Y component of a distance vector. An in/out parameter + */ void vkvg_matrix_transform_distance (const vkvg_matrix_t *matrix, float *dx, float *dy); +/** + * @brief transform point + * + * Transforms the point (x , y ) by matrix . + * @param matrix a valid #vkvg_matrix_t to use to transform point + * @param x X position. An in/out parameter + * @param y Y position. An in/out parameter + */ void vkvg_matrix_transform_point (const vkvg_matrix_t *matrix, float *x, float *y); -void vkvg_matrix_invert (vkvg_matrix_t *matrix); +/** + * @brief invert matrix + * + * Changes matrix to be the inverse of its original value. Not all transformation matrices have inverses; + * if the matrix collapses points together (it is degenerate), then it has no inverse and this function will fail. + * @param matrix the matrix to invert + * @return If matrix has an inverse, modifies matrix to be the inverse matrix and returns VKVG_STATUS_SUCCESS. + * Otherwise, returns VKVG_STATUS_INVALID_MATRIX. + */ +vkvg_status_t vkvg_matrix_invert(vkvg_matrix_t *matrix); /** @}*/ diff --git a/src/vkvg_matrix.c b/src/vkvg_matrix.c index 109b914..6094efc 100644 --- a/src/vkvg_matrix.c +++ b/src/vkvg_matrix.c @@ -65,193 +65,195 @@ //matrix computations mainly taken from http://cairographics.org static void _vkvg_matrix_scalar_multiply (vkvg_matrix_t *matrix, float scalar) { - matrix->xx *= scalar; - matrix->yx *= scalar; + matrix->xx *= scalar; + matrix->yx *= scalar; - matrix->xy *= scalar; - matrix->yy *= scalar; + matrix->xy *= scalar; + matrix->yy *= scalar; - matrix->x0 *= scalar; - matrix->y0 *= scalar; + matrix->x0 *= scalar; + matrix->y0 *= scalar; } void _vkvg_matrix_get_affine (const vkvg_matrix_t *matrix, - float *xx, float *yx, - float *xy, float *yy, - float *x0, float *y0) + float *xx, float *yx, + float *xy, float *yy, + float *x0, float *y0) { - *xx = matrix->xx; - *yx = matrix->yx; + *xx = matrix->xx; + *yx = matrix->yx; - *xy = matrix->xy; - *yy = matrix->yy; + *xy = matrix->xy; + *yy = matrix->yy; - if (x0) - *x0 = matrix->x0; - if (y0) - *y0 = matrix->y0; + if (x0) + *x0 = matrix->x0; + if (y0) + *y0 = matrix->y0; } static void _vkvg_matrix_compute_adjoint (vkvg_matrix_t *matrix) { - /* adj (A) = transpose (C:cofactor (A,i,j)) */ - float a, b, c, d, tx, ty; - - _vkvg_matrix_get_affine (matrix, - &a, &b, - &c, &d, - &tx, &ty); - - vkvg_matrix_init (matrix, - d, -b, - -c, a, - c*ty - d*tx, b*tx - a*ty); + /* adj (A) = transpose (C:cofactor (A,i,j)) */ + float a, b, c, d, tx, ty; + + _vkvg_matrix_get_affine (matrix, + &a, &b, + &c, &d, + &tx, &ty); + + vkvg_matrix_init (matrix, + d, -b, + -c, a, + c*ty - d*tx, b*tx - a*ty); } float _vkvg_matrix_compute_determinant (const vkvg_matrix_t *matrix) { - float a, b, c, d; + float a, b, c, d; - a = matrix->xx; b = matrix->yx; - c = matrix->xy; d = matrix->yy; + a = matrix->xx; b = matrix->yx; + c = matrix->xy; d = matrix->yy; - return a*d - b*c; + return a*d - b*c; } -void vkvg_matrix_invert (vkvg_matrix_t *matrix) +vkvg_status_t vkvg_matrix_invert (vkvg_matrix_t *matrix) { - float det; + float det; - /* Simple scaling|translation matrices are quite common... */ - if (matrix->xy == 0. && matrix->yx == 0.) { - matrix->x0 = -matrix->x0; - matrix->y0 = -matrix->y0; + /* Simple scaling|translation matrices are quite common... */ + if (matrix->xy == 0. && matrix->yx == 0.) { + matrix->x0 = -matrix->x0; + matrix->y0 = -matrix->y0; - if (matrix->xx != 1.f) { - if (matrix->xx == 0.) - return; + if (matrix->xx != 1.f) { + if (matrix->xx == 0.) + return VKVG_STATUS_INVALID_MATRIX; - matrix->xx = 1.f / matrix->xx; - matrix->x0 *= matrix->xx; - } + matrix->xx = 1.f / matrix->xx; + matrix->x0 *= matrix->xx; + } - if (matrix->yy != 1.f) { - if (matrix->yy == 0.) - return; + if (matrix->yy != 1.f) { + if (matrix->yy == 0.) + return VKVG_STATUS_INVALID_MATRIX; - matrix->yy = 1.f / matrix->yy; - matrix->y0 *= matrix->yy; - } + matrix->yy = 1.f / matrix->yy; + matrix->y0 *= matrix->yy; + } - return; - } + return VKVG_STATUS_SUCCESS; + } - /* inv (A) = 1/det (A) * adj (A) */ - det = _vkvg_matrix_compute_determinant (matrix); + /* inv (A) = 1/det (A) * adj (A) */ + det = _vkvg_matrix_compute_determinant (matrix); - if (! ISFINITE (det)) - return; + if (! ISFINITE (det)) + return VKVG_STATUS_INVALID_MATRIX; - if (det == 0) - return; + if (det == 0) + return VKVG_STATUS_INVALID_MATRIX; - _vkvg_matrix_compute_adjoint (matrix); - _vkvg_matrix_scalar_multiply (matrix, 1 / det); + _vkvg_matrix_compute_adjoint (matrix); + _vkvg_matrix_scalar_multiply (matrix, 1 / det); + + return VKVG_STATUS_SUCCESS; } void vkvg_matrix_init_identity (vkvg_matrix_t *matrix) { - vkvg_matrix_init (matrix, - 1, 0, - 0, 1, - 0, 0); + vkvg_matrix_init (matrix, + 1, 0, + 0, 1, + 0, 0); } void vkvg_matrix_init (vkvg_matrix_t *matrix, - float xx, float yx, - float xy, float yy, - float x0, float y0) + float xx, float yx, + float xy, float yy, + float x0, float y0) { - matrix->xx = xx; matrix->yx = yx; - matrix->xy = xy; matrix->yy = yy; - matrix->x0 = x0; matrix->y0 = y0; + matrix->xx = xx; matrix->yx = yx; + matrix->xy = xy; matrix->yy = yy; + matrix->x0 = x0; matrix->y0 = y0; } void vkvg_matrix_init_translate (vkvg_matrix_t *matrix, float tx, float ty) { - vkvg_matrix_init (matrix, - 1, 0, - 0, 1, - tx, ty); + vkvg_matrix_init (matrix, + 1, 0, + 0, 1, + tx, ty); } void vkvg_matrix_init_scale (vkvg_matrix_t *matrix, float sx, float sy) { - vkvg_matrix_init (matrix, - sx, 0, - 0, sy, - 0, 0); + vkvg_matrix_init (matrix, + sx, 0, + 0, sy, + 0, 0); } void vkvg_matrix_init_rotate (vkvg_matrix_t *matrix, float radians) { - float s; - float c; + float s; + float c; - s = sinf (radians); - c = cosf (radians); + s = sinf (radians); + c = cosf (radians); - vkvg_matrix_init (matrix, - c, s, - -s, c, - 0, 0); + vkvg_matrix_init (matrix, + c, s, + -s, c, + 0, 0); } void vkvg_matrix_translate (vkvg_matrix_t *matrix, float tx, float ty) { - vkvg_matrix_t tmp; + vkvg_matrix_t tmp; - vkvg_matrix_init_translate (&tmp, tx, ty); + vkvg_matrix_init_translate (&tmp, tx, ty); - vkvg_matrix_multiply (matrix, &tmp, matrix); + vkvg_matrix_multiply (matrix, &tmp, matrix); } void vkvg_matrix_scale (vkvg_matrix_t *matrix, float sx, float sy) { - vkvg_matrix_t tmp; + vkvg_matrix_t tmp; - vkvg_matrix_init_scale (&tmp, sx, sy); + vkvg_matrix_init_scale (&tmp, sx, sy); - vkvg_matrix_multiply (matrix, &tmp, matrix); + vkvg_matrix_multiply (matrix, &tmp, matrix); } void vkvg_matrix_rotate (vkvg_matrix_t *matrix, float radians) { - vkvg_matrix_t tmp; + vkvg_matrix_t tmp; - vkvg_matrix_init_rotate (&tmp, radians); + vkvg_matrix_init_rotate (&tmp, radians); - vkvg_matrix_multiply (matrix, &tmp, matrix); + vkvg_matrix_multiply (matrix, &tmp, matrix); } void vkvg_matrix_multiply (vkvg_matrix_t *result, const vkvg_matrix_t *a, const vkvg_matrix_t *b) { - vkvg_matrix_t r; + vkvg_matrix_t r; - r.xx = a->xx * b->xx + a->yx * b->xy; - r.yx = a->xx * b->yx + a->yx * b->yy; + r.xx = a->xx * b->xx + a->yx * b->xy; + r.yx = a->xx * b->yx + a->yx * b->yy; - r.xy = a->xy * b->xx + a->yy * b->xy; - r.yy = a->xy * b->yx + a->yy * b->yy; + r.xy = a->xy * b->xx + a->yy * b->xy; + r.yy = a->xy * b->yx + a->yy * b->yy; - r.x0 = a->x0 * b->xx + a->y0 * b->xy + b->x0; - r.y0 = a->x0 * b->yx + a->y0 * b->yy + b->y0; + r.x0 = a->x0 * b->xx + a->y0 * b->xy + b->x0; + r.y0 = a->x0 * b->yx + a->y0 * b->yy + b->y0; - *result = r; + *result = r; } void vkvg_matrix_transform_distance (const vkvg_matrix_t *matrix, float *dx, float *dy) { - float new_x, new_y; + float new_x, new_y; - new_x = (matrix->xx * *dx + matrix->xy * *dy); - new_y = (matrix->yx * *dx + matrix->yy * *dy); + new_x = (matrix->xx * *dx + matrix->xy * *dy); + new_y = (matrix->yx * *dx + matrix->yy * *dy); - *dx = new_x; - *dy = new_y; + *dx = new_x; + *dy = new_y; } void vkvg_matrix_transform_point (const vkvg_matrix_t *matrix, float *x, float *y) { - vkvg_matrix_transform_distance (matrix, x, y); + vkvg_matrix_transform_distance (matrix, x, y); - *x += matrix->x0; - *y += matrix->y0; + *x += matrix->x0; + *y += matrix->y0; }