[CpmlArc] Fixed issue 7: arc extents bug
[adg.git] / adg / adg-matrix.c
blob84fbc17c73c6a1e47ec1692e39485392ca920589
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009 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-matrix.h"
39 #include "adg-intl.h"
41 #include <string.h>
42 #include <math.h>
45 GType
46 adg_matrix_get_type(void)
48 static int matrix_type = 0;
50 if (G_UNLIKELY(matrix_type == 0))
51 matrix_type = g_boxed_type_register_static("AdgMatrix",
52 (GBoxedCopyFunc) adg_matrix_dup,
53 g_free);
55 return matrix_type;
58 /**
59 * adg_matrix_identity:
61 * A constant identity matrix provided as facility.
63 * Returns: a pointer to the identity matrix
64 **/
65 const AdgMatrix *
66 adg_matrix_identity(void)
68 static AdgMatrix identity_matrix;
69 static gboolean initialized = FALSE;
71 if (G_UNLIKELY(!initialized)) {
72 cairo_matrix_init_identity(&identity_matrix);
73 initialized = TRUE;
76 return &identity_matrix;
79 /**
80 * adg_matrix_copy:
81 * @matrix: the destination #AdgMatrix
82 * @src: the source #AdgMatrix
84 * Copies @matrix to @dst.
86 * Returns: @matrix
87 **/
88 AdgMatrix *
89 adg_matrix_copy(AdgMatrix *matrix, const AdgMatrix *src)
91 g_return_val_if_fail(matrix != NULL, matrix);
92 g_return_val_if_fail(src != NULL, matrix);
94 memcpy(matrix, src, sizeof(AdgMatrix));
96 return matrix;
99 /**
100 * adg_matrix_dup:
101 * @matrix: the souce #AdgMatrix
103 * Duplicates @matrix.
105 * Returns: the duplicate of @matrix: must be freed with g_free()
106 * when no longer needed.
108 AdgMatrix *
109 adg_matrix_dup(const AdgMatrix *matrix)
111 g_return_val_if_fail(matrix != NULL, NULL);
113 return g_memdup(matrix, sizeof(AdgMatrix));
117 * adg_matrix_equal:
118 * @matrix1: an #AdgMatrix
119 * @matrix2: an #AdgMatrix
121 * Compares @matrix1 and @matrix2 and returns %TRUE if the matrices are equal.
123 * Returns: %TRUE if @matrix1 is equal to @matrix2, %FALSE otherwise
125 gboolean
126 adg_matrix_equal(const AdgMatrix *matrix1, const AdgMatrix *matrix2)
128 g_return_val_if_fail(matrix1 != NULL, FALSE);
129 g_return_val_if_fail(matrix2 != NULL, FALSE);
131 /* XXX: I don't know if the following is always correct */
132 return memcmp(matrix1, matrix2, sizeof(AdgMatrix)) == 0;
136 * adg_matrix_normalize:
137 * @matrix: the source/destination #AdgMatrix
139 * Gets rid of the scaling component of a matrix. The algorithm used
140 * has been found sperimentally so it could luckely be plain wrong.
142 * Returns: %TRUE on success, %FALSE on errors
144 gboolean
145 adg_matrix_normalize(AdgMatrix *matrix)
147 gdouble k;
149 g_return_val_if_fail(matrix != NULL, FALSE);
151 if (matrix->xx != matrix->yy || matrix->xy != -matrix->yx) {
152 /* TODO: does normalization make sense on these matrices? */
153 g_warning(_("%s: anamorphic matrices not supported"), G_STRLOC);
154 return FALSE;
157 if (matrix->xy == 0) {
158 k = matrix->xx;
159 } else if (matrix->xx == 0) {
160 k = matrix->xy;
161 } else {
162 k = sqrt(matrix->xx * matrix->xx + matrix->xy * matrix->xy);
165 g_return_val_if_fail(k != 0, FALSE);
167 matrix->xx /= k;
168 matrix->xy /= k;
169 matrix->yy /= k;
170 matrix->yx /= k;
172 return TRUE;
176 * adg_matrix_transform:
177 * @matrix: the source/destination #AdgMatrix
178 * @transformation: the transformation to apply
179 * @mode: how @transformation should be applied
181 * Modifies @matrix applying @transformation in the way specified by
182 * @mode.
184 void
185 adg_matrix_transform(AdgMatrix *matrix, const AdgMatrix *transformation,
186 AdgTransformMode mode)
188 AdgMatrix tmp_matrix;
190 g_return_if_fail(matrix != NULL);
191 g_return_if_fail(transformation != NULL);
193 switch (mode) {
194 case ADG_TRANSFORM_NONE:
195 break;
196 case ADG_TRANSFORM_BEFORE:
197 cairo_matrix_multiply(matrix, transformation, matrix);
198 break;
199 case ADG_TRANSFORM_AFTER:
200 cairo_matrix_multiply(matrix, matrix, transformation);
201 break;
202 case ADG_TRANSFORM_BEFORE_NORMALIZED:
203 adg_matrix_copy(&tmp_matrix, transformation);
204 adg_matrix_normalize(&tmp_matrix);
205 cairo_matrix_multiply(matrix, &tmp_matrix, matrix);
206 break;
207 case ADG_TRANSFORM_AFTER_NORMALIZED:
208 adg_matrix_copy(&tmp_matrix, transformation);
209 adg_matrix_normalize(&tmp_matrix);
210 cairo_matrix_multiply(matrix, matrix, &tmp_matrix);
211 break;
212 default:
213 g_assert_not_reached();
218 * adg_matrix_dump:
219 * @matrix: an #AdgMatrix
221 * Dumps the specified @matrix to stdout. Useful for debugging purposes.
223 void
224 adg_matrix_dump(const AdgMatrix *matrix)
226 g_print("[%8.3lf %8.3lf] [%8.3lf]\n"
227 "[%8.3lf %8.3lf] [%8.3lf]\n",
228 matrix->xx, matrix->xy, matrix->x0,
229 matrix->yx, matrix->yy, matrix->y0);