adg: use cairo_matrix_t instead of AdgMatrix
[adg.git] / src / adg / adg-matrix.c
blobb248adc1e09b3ca38c9358de800ead3dbfc4f28a
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010,2011,2012 Nicola Fontana <ntd at entidi.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 /**
22 * SECTION:adg-matrix
23 * @Section_Id:Matrix
24 * @title: Matrix
25 * @short_description: #cairo_matrix_t enhancements and utilities.
27 * This API provides a #GBoxed wrapper around #cairo_matrix_t
28 * (if not yet provided by cairo-gobject) * and augments its methods
29 * with some useful addition.
31 * Since: 1.0
32 **/
35 #include "adg-internal.h"
36 #include <string.h>
37 #include <math.h>
39 #include "adg-matrix-fallback.h"
42 #ifdef ADG_MISSING_GBOXED_MATRIX
44 GType
45 cairo_gobject_matrix_get_type(void)
47 static GType matrix_type = 0;
49 if (G_UNLIKELY(matrix_type == 0))
50 matrix_type = g_boxed_type_register_static("CairoMatrix",
51 (GBoxedCopyFunc) cairo_gobject_cairo_matrix_copy,
52 g_free);
54 return matrix_type;
57 cairo_matrix_t *
58 cairo_gobject_cairo_matrix_copy(const cairo_matrix_t *matrix)
60 return g_memdup(matrix, sizeof(cairo_matrix_t));
63 #endif /* ADG_MISSING_GBOXED_MATRIX */
66 /**
67 * adg_matrix_new:
69 * Creates a new empty #cairo_matrix_t. The returned pointer
70 * should be freed with g_free() when no longer needed.
72 * Returns: (transfer full): a newly created #cairo_matrix_t
74 * Since: 1.0
75 **/
76 cairo_matrix_t *
77 adg_matrix_new(void)
79 return g_new0(cairo_matrix_t, 1);
82 /**
83 * adg_matrix_identity:
85 * A convenient constant providing an identity matrix.
87 * Returns: (transfer none): a pointer to the identity matrix
89 * Since: 1.0
90 **/
91 const cairo_matrix_t *
92 adg_matrix_identity(void)
94 static cairo_matrix_t *identity_matrix = NULL;
96 if (G_UNLIKELY(identity_matrix == NULL)) {
97 identity_matrix = g_new(cairo_matrix_t, 1);
98 cairo_matrix_init_identity(identity_matrix);
101 return identity_matrix;
105 * adg_matrix_null:
107 * A convenient constant providing an null matrix, that is a matrix
108 * where all components are 0.
110 * Returns: (transfer none): a pointer to the null matrix
112 * Since: 1.0
114 const cairo_matrix_t *
115 adg_matrix_null(void)
117 static cairo_matrix_t *null_matrix = NULL;
119 if (G_UNLIKELY(null_matrix == NULL))
120 null_matrix = g_new0(cairo_matrix_t, 1);
122 return null_matrix;
126 * adg_matrix_copy:
127 * @matrix: (out caller-allocates): the destination #cairo_matrix_t
128 * @src: the source #cairo_matrix_t
130 * Copies @src to @matrix.
132 * Since: 1.0
134 void
135 adg_matrix_copy(cairo_matrix_t *matrix, const cairo_matrix_t *src)
137 g_return_if_fail(matrix != NULL);
138 g_return_if_fail(src != NULL);
140 memcpy(matrix, src, sizeof(cairo_matrix_t));
144 * adg_matrix_dup:
145 * @matrix: the souce #cairo_matrix_t
147 * Duplicates @matrix.
149 * Returns: (transfer full): a duplicate of @matrix that must be freed with g_free() when no longer needed.
151 * Since: 1.0
153 cairo_matrix_t *
154 adg_matrix_dup(const cairo_matrix_t *matrix)
156 g_return_val_if_fail(matrix != NULL, NULL);
158 return g_memdup(matrix, sizeof(cairo_matrix_t));
162 * adg_matrix_equal:
163 * @matrix1: the first operand
164 * @matrix2: the second operand
166 * Compares @matrix1 and @matrix2 and returns %TRUE if the matrices are equal.
168 * Returns: %TRUE if @matrix1 is equal to @matrix2, %FALSE otherwise
170 * Since: 1.0
172 gboolean
173 adg_matrix_equal(const cairo_matrix_t *matrix1, const cairo_matrix_t *matrix2)
175 g_return_val_if_fail(matrix1 != NULL, FALSE);
176 g_return_val_if_fail(matrix2 != NULL, FALSE);
178 return
179 matrix1->xx == matrix2->xx &&
180 matrix1->yx == matrix2->yx &&
181 matrix1->xy == matrix2->xy &&
182 matrix1->yy == matrix2->yy &&
183 matrix1->x0 == matrix2->x0 &&
184 matrix1->y0 == matrix2->y0;
188 * adg_matrix_normalize:
189 * @matrix: (inout): the source/destination #cairo_matrix_t
191 * Gets rid of the scaling component of a matrix.
193 * Returns: %TRUE on success, %FALSE on errors
195 * Since: 1.0
197 gboolean
198 adg_matrix_normalize(cairo_matrix_t *matrix)
200 gdouble k;
202 g_return_val_if_fail(matrix != NULL, FALSE);
204 if (matrix->xx != matrix->yy || matrix->xy != -matrix->yx) {
205 g_warning(_("%s: normalization of anamorphic matrices not supported"),
206 G_STRLOC);
207 return FALSE;
210 if (matrix->xy == 0) {
211 k = matrix->xx;
212 } else if (matrix->xx == 0) {
213 k = matrix->xy;
214 } else {
215 k = sqrt(matrix->xx * matrix->xx + matrix->xy * matrix->xy);
218 g_return_val_if_fail(k != 0, FALSE);
220 matrix->xx /= k;
221 matrix->xy /= k;
222 matrix->yy /= k;
223 matrix->yx /= k;
225 return TRUE;
229 * adg_matrix_transform:
230 * @matrix: (inout): the source/destination #cairo_matrix_t
231 * @transformation: the transformation to apply
232 * @mode: (in): how @transformation should be applied
234 * Modifies @matrix applying @transformation in the way specified by
235 * @mode.
237 * Since: 1.0
239 void
240 adg_matrix_transform(cairo_matrix_t *matrix,
241 const cairo_matrix_t *transformation, AdgTransformMode mode)
243 cairo_matrix_t normalized;
245 g_return_if_fail(matrix != NULL);
246 g_return_if_fail(transformation != NULL);
248 switch (mode) {
249 case ADG_TRANSFORM_NONE:
250 break;
251 case ADG_TRANSFORM_BEFORE:
252 cairo_matrix_multiply(matrix, transformation, matrix);
253 break;
254 case ADG_TRANSFORM_AFTER:
255 cairo_matrix_multiply(matrix, matrix, transformation);
256 break;
257 case ADG_TRANSFORM_BEFORE_NORMALIZED:
258 adg_matrix_copy(&normalized, transformation);
259 adg_matrix_normalize(&normalized);
260 cairo_matrix_multiply(matrix, &normalized, matrix);
261 break;
262 case ADG_TRANSFORM_AFTER_NORMALIZED:
263 adg_matrix_copy(&normalized, transformation);
264 adg_matrix_normalize(&normalized);
265 cairo_matrix_multiply(matrix, matrix, &normalized);
266 break;
267 default:
268 g_return_if_reached();
273 * adg_matrix_dump:
274 * @matrix: an #cairo_matrix_t
276 * Dumps the specified @matrix to stdout. Useful for debugging purposes.
278 * Since: 1.0
280 void
281 adg_matrix_dump(const cairo_matrix_t *matrix)
283 g_return_if_fail(matrix != NULL);
285 g_print("[%8.3lf %8.3lf] [%8.3lf]\n"
286 "[%8.3lf %8.3lf] [%8.3lf]\n",
287 matrix->xx, matrix->xy, matrix->x0,
288 matrix->yx, matrix->yy, matrix->y0);