Moved AdgPair to CpmlPair
[adg.git] / src / adg / adg-matrix.c
blob10bcc07c8b6261372578d8269a41bde37f91dab7
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:AdgMatrix
24 * @title: AdgMatrix
25 * @short_description: A wrapper for #cairo_matrix_t
27 * AdgMatrix is a wrapper in #GType syntax of the #cairo_matrix_t struct.
29 * Since: 1.0
30 **/
32 /**
33 * AdgMatrix:
35 * Another name for #cairo_matrix_t: check its documentation for the
36 * fields description and visibility details.
38 * Since: 1.0
39 **/
42 #include "adg-internal.h"
43 #include <string.h>
44 #include <math.h>
47 GType
48 adg_matrix_get_type(void)
50 static GType matrix_type = 0;
52 if (G_UNLIKELY(matrix_type == 0))
53 matrix_type = g_boxed_type_register_static("AdgMatrix",
54 (GBoxedCopyFunc) adg_matrix_dup,
55 g_free);
57 return matrix_type;
61 /**
62 * adg_matrix_new:
64 * Creates a new empty #AdgMatrix. The returned pointer
65 * should be freed with g_free() when no longer needed.
67 * Returns: (transfer full): a newly created #AdgMatrix
69 * Since: 1.0
70 **/
71 AdgMatrix *
72 adg_matrix_new(void)
74 return g_new0(AdgMatrix, 1);
77 /**
78 * adg_matrix_identity:
80 * A convenient constant providing an identity matrix.
82 * Returns: (transfer none): a pointer to the identity matrix
84 * Since: 1.0
85 **/
86 const AdgMatrix *
87 adg_matrix_identity(void)
89 static AdgMatrix *identity_matrix = NULL;
91 if (G_UNLIKELY(identity_matrix == NULL)) {
92 identity_matrix = g_new(AdgMatrix, 1);
93 cairo_matrix_init_identity(identity_matrix);
96 return identity_matrix;
99 /**
100 * adg_matrix_null:
102 * A convenient constant providing an null matrix, that is a matrix
103 * where all components are 0.
105 * Returns: (transfer none): a pointer to the null matrix
107 * Since: 1.0
109 const AdgMatrix *
110 adg_matrix_null(void)
112 static AdgMatrix *null_matrix = NULL;
114 if (G_UNLIKELY(null_matrix == NULL))
115 null_matrix = g_new0(AdgMatrix, 1);
117 return null_matrix;
121 * adg_matrix_copy:
122 * @matrix: (out caller-allocates): the destination #AdgMatrix
123 * @src: the source #AdgMatrix
125 * Copies @src to @matrix.
127 * Since: 1.0
129 void
130 adg_matrix_copy(AdgMatrix *matrix, const AdgMatrix *src)
132 g_return_if_fail(matrix != NULL);
133 g_return_if_fail(src != NULL);
135 memcpy(matrix, src, sizeof(AdgMatrix));
139 * adg_matrix_dup:
140 * @matrix: the souce #AdgMatrix
142 * Duplicates @matrix.
144 * Returns: (transfer full): a duplicate of @matrix that must be freed with g_free() when no longer needed.
146 * Since: 1.0
148 AdgMatrix *
149 adg_matrix_dup(const AdgMatrix *matrix)
151 g_return_val_if_fail(matrix != NULL, NULL);
153 return g_memdup(matrix, sizeof(AdgMatrix));
157 * adg_matrix_equal:
158 * @matrix1: the first operand
159 * @matrix2: the second operand
161 * Compares @matrix1 and @matrix2 and returns %TRUE if the matrices are equal.
163 * Returns: %TRUE if @matrix1 is equal to @matrix2, %FALSE otherwise
165 * Since: 1.0
167 gboolean
168 adg_matrix_equal(const AdgMatrix *matrix1, const AdgMatrix *matrix2)
170 g_return_val_if_fail(matrix1 != NULL, FALSE);
171 g_return_val_if_fail(matrix2 != NULL, FALSE);
173 return
174 matrix1->xx == matrix2->xx &&
175 matrix1->yx == matrix2->yx &&
176 matrix1->xy == matrix2->xy &&
177 matrix1->yy == matrix2->yy &&
178 matrix1->x0 == matrix2->x0 &&
179 matrix1->y0 == matrix2->y0;
183 * adg_matrix_normalize:
184 * @matrix: (inout): the source/destination #AdgMatrix
186 * Gets rid of the scaling component of a matrix.
188 * Returns: %TRUE on success, %FALSE on errors
190 * Since: 1.0
192 gboolean
193 adg_matrix_normalize(AdgMatrix *matrix)
195 gdouble k;
197 g_return_val_if_fail(matrix != NULL, FALSE);
199 if (matrix->xx != matrix->yy || matrix->xy != -matrix->yx) {
200 g_warning(_("%s: normalization of anamorphic matrices not supported"),
201 G_STRLOC);
202 return FALSE;
205 if (matrix->xy == 0) {
206 k = matrix->xx;
207 } else if (matrix->xx == 0) {
208 k = matrix->xy;
209 } else {
210 k = sqrt(matrix->xx * matrix->xx + matrix->xy * matrix->xy);
213 g_return_val_if_fail(k != 0, FALSE);
215 matrix->xx /= k;
216 matrix->xy /= k;
217 matrix->yy /= k;
218 matrix->yx /= k;
220 return TRUE;
224 * adg_matrix_transform:
225 * @matrix: (inout): the source/destination #AdgMatrix
226 * @transformation: the transformation to apply
227 * @mode: (in): how @transformation should be applied
229 * Modifies @matrix applying @transformation in the way specified by
230 * @mode.
232 * Since: 1.0
234 void
235 adg_matrix_transform(AdgMatrix *matrix, const AdgMatrix *transformation,
236 AdgTransformMode mode)
238 AdgMatrix normalized;
240 g_return_if_fail(matrix != NULL);
241 g_return_if_fail(transformation != NULL);
243 switch (mode) {
244 case ADG_TRANSFORM_NONE:
245 break;
246 case ADG_TRANSFORM_BEFORE:
247 cairo_matrix_multiply(matrix, transformation, matrix);
248 break;
249 case ADG_TRANSFORM_AFTER:
250 cairo_matrix_multiply(matrix, matrix, transformation);
251 break;
252 case ADG_TRANSFORM_BEFORE_NORMALIZED:
253 adg_matrix_copy(&normalized, transformation);
254 adg_matrix_normalize(&normalized);
255 cairo_matrix_multiply(matrix, &normalized, matrix);
256 break;
257 case ADG_TRANSFORM_AFTER_NORMALIZED:
258 adg_matrix_copy(&normalized, transformation);
259 adg_matrix_normalize(&normalized);
260 cairo_matrix_multiply(matrix, matrix, &normalized);
261 break;
262 default:
263 g_return_if_reached();
268 * adg_matrix_dump:
269 * @matrix: an #AdgMatrix
271 * Dumps the specified @matrix to stdout. Useful for debugging purposes.
273 * Since: 1.0
275 void
276 adg_matrix_dump(const AdgMatrix *matrix)
278 g_return_if_fail(matrix != NULL);
280 g_print("[%8.3lf %8.3lf] [%8.3lf]\n"
281 "[%8.3lf %8.3lf] [%8.3lf]\n",
282 matrix->xx, matrix->xy, matrix->x0,
283 matrix->yx, matrix->yy, matrix->y0);