float a;
} vkvg_color_t;
-
typedef struct {
float ascent;
float descent;
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
* 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
* 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
* @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
*
* 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);
/** @}*/
//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;
}