[build] Moved project dirs under src/
[adg.git] / src / adg / adg-matrix.c
blob0ca55acf94eae68ae316206853c2c89c8dd8a700
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010 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.
28 **/
30 /**
31 * AdgMatrix:
33 * Another name for #cairo_matrix_t: check its documentation for the
34 * fields description and visibility details.
35 **/
38 #include "adg-internal.h"
39 #include "adg-matrix.h"
40 #include <string.h>
41 #include <math.h>
44 GType
45 adg_matrix_get_type(void)
47 static int matrix_type = 0;
49 if (G_UNLIKELY(matrix_type == 0))
50 matrix_type = g_boxed_type_register_static("AdgMatrix",
51 (GBoxedCopyFunc) adg_matrix_dup,
52 g_free);
54 return matrix_type;
57 /**
58 * adg_matrix_identity:
60 * A convenient constant providing an identity matrix.
62 * Returns: a pointer to the identity matrix
63 **/
64 const AdgMatrix *
65 adg_matrix_identity(void)
67 static AdgMatrix *identity_matrix = NULL;
69 if (G_UNLIKELY(identity_matrix == NULL)) {
70 identity_matrix = g_new(AdgMatrix, 1);
71 cairo_matrix_init_identity(identity_matrix);
74 return identity_matrix;
77 /**
78 * adg_matrix_null:
80 * A convenient constant providing an null matrix, that is a matrix
81 * where all components are 0.
83 * Returns: a pointer to the null matrix
84 **/
85 const AdgMatrix *
86 adg_matrix_null(void)
88 static AdgMatrix *null_matrix = NULL;
90 if (G_UNLIKELY(null_matrix == NULL))
91 null_matrix = g_new0(AdgMatrix, 1);
93 return null_matrix;
96 /**
97 * adg_matrix_copy:
98 * @matrix: the destination #AdgMatrix
99 * @src: the source #AdgMatrix
101 * Copies @matrix to @dst.
103 * Returns: @matrix
105 AdgMatrix *
106 adg_matrix_copy(AdgMatrix *matrix, const AdgMatrix *src)
108 g_return_val_if_fail(matrix != NULL, matrix);
109 g_return_val_if_fail(src != NULL, matrix);
111 memcpy(matrix, src, sizeof(AdgMatrix));
113 return matrix;
117 * adg_matrix_dup:
118 * @matrix: the souce #AdgMatrix
120 * Duplicates @matrix.
122 * Returns: the duplicate of @matrix: must be freed with g_free()
123 * when no longer needed.
125 AdgMatrix *
126 adg_matrix_dup(const AdgMatrix *matrix)
128 g_return_val_if_fail(matrix != NULL, NULL);
130 return g_memdup(matrix, sizeof(AdgMatrix));
134 * adg_matrix_equal:
135 * @matrix1: an #AdgMatrix
136 * @matrix2: an #AdgMatrix
138 * Compares @matrix1 and @matrix2 and returns %TRUE if the matrices are equal.
140 * Returns: %TRUE if @matrix1 is equal to @matrix2, %FALSE otherwise
142 gboolean
143 adg_matrix_equal(const AdgMatrix *matrix1, const AdgMatrix *matrix2)
145 g_return_val_if_fail(matrix1 != NULL, FALSE);
146 g_return_val_if_fail(matrix2 != NULL, FALSE);
148 /* XXX: I don't know if the following is always correct */
149 return memcmp(matrix1, matrix2, sizeof(AdgMatrix)) == 0;
153 * adg_matrix_normalize:
154 * @matrix: the source/destination #AdgMatrix
156 * Gets rid of the scaling component of a matrix. The algorithm used
157 * has been found sperimentally so it could luckely be plain wrong.
159 * Returns: %TRUE on success, %FALSE on errors
161 gboolean
162 adg_matrix_normalize(AdgMatrix *matrix)
164 gdouble k;
166 g_return_val_if_fail(matrix != NULL, FALSE);
168 if (matrix->xx != matrix->yy || matrix->xy != -matrix->yx) {
169 /* TODO: does normalization make sense on these matrices? */
170 g_warning(_("%s: anamorphic matrices not supported"), G_STRLOC);
171 return FALSE;
174 if (matrix->xy == 0) {
175 k = matrix->xx;
176 } else if (matrix->xx == 0) {
177 k = matrix->xy;
178 } else {
179 k = sqrt(matrix->xx * matrix->xx + matrix->xy * matrix->xy);
182 g_return_val_if_fail(k != 0, FALSE);
184 matrix->xx /= k;
185 matrix->xy /= k;
186 matrix->yy /= k;
187 matrix->yx /= k;
189 return TRUE;
193 * adg_matrix_transform:
194 * @matrix: the source/destination #AdgMatrix
195 * @transformation: the transformation to apply
196 * @mode: how @transformation should be applied
198 * Modifies @matrix applying @transformation in the way specified by
199 * @mode.
201 void
202 adg_matrix_transform(AdgMatrix *matrix, const AdgMatrix *transformation,
203 AdgTransformMode mode)
205 AdgMatrix normalized;
207 g_return_if_fail(matrix != NULL);
208 g_return_if_fail(transformation != NULL);
210 switch (mode) {
211 case ADG_TRANSFORM_NONE:
212 break;
213 case ADG_TRANSFORM_BEFORE:
214 cairo_matrix_multiply(matrix, transformation, matrix);
215 break;
216 case ADG_TRANSFORM_AFTER:
217 cairo_matrix_multiply(matrix, matrix, transformation);
218 break;
219 case ADG_TRANSFORM_BEFORE_NORMALIZED:
220 adg_matrix_copy(&normalized, transformation);
221 adg_matrix_normalize(&normalized);
222 cairo_matrix_multiply(matrix, &normalized, matrix);
223 break;
224 case ADG_TRANSFORM_AFTER_NORMALIZED:
225 adg_matrix_copy(&normalized, transformation);
226 adg_matrix_normalize(&normalized);
227 cairo_matrix_multiply(matrix, matrix, &normalized);
228 break;
229 default:
230 g_return_if_reached();
235 * adg_matrix_dump:
236 * @matrix: an #AdgMatrix
238 * Dumps the specified @matrix to stdout. Useful for debugging purposes.
240 void
241 adg_matrix_dump(const AdgMatrix *matrix)
243 g_return_if_fail(matrix != NULL);
245 g_print("[%8.3lf %8.3lf] [%8.3lf]\n"
246 "[%8.3lf %8.3lf] [%8.3lf]\n",
247 matrix->xx, matrix->xy, matrix->x0,
248 matrix->yx, matrix->yy, matrix->y0);