build: depends on cairo-gobject if introspection is enabled
[adg.git] / src / adg / adg-matrix.c
blob059f086ddcf3e3d76c91431a1ac1eec7029161ef
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010,2011,2012,2013 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 * The following functions augment the cairo_matrix_t available methods
28 * providing some useful addition.
30 * Since: 1.0
31 **/
34 #include "adg-internal.h"
35 #include <string.h>
36 #include <math.h>
39 /**
40 * adg_matrix_identity:
42 * A convenient constant providing an identity matrix.
44 * Returns: (transfer none): a pointer to the identity matrix
46 * Since: 1.0
47 **/
48 const cairo_matrix_t *
49 adg_matrix_identity(void)
51 static cairo_matrix_t *identity_matrix = NULL;
53 if (G_UNLIKELY(identity_matrix == NULL)) {
54 identity_matrix = g_new(cairo_matrix_t, 1);
55 cairo_matrix_init_identity(identity_matrix);
58 return identity_matrix;
61 /**
62 * adg_matrix_null:
64 * A convenient constant providing an null matrix, that is a matrix
65 * where all components are 0.
67 * Returns: (transfer none): a pointer to the null matrix
69 * Since: 1.0
70 **/
71 const cairo_matrix_t *
72 adg_matrix_null(void)
74 static cairo_matrix_t *null_matrix = NULL;
76 if (G_UNLIKELY(null_matrix == NULL))
77 null_matrix = g_new0(cairo_matrix_t, 1);
79 return null_matrix;
82 /**
83 * adg_matrix_copy:
84 * @matrix: (out caller-allocates): the destination #cairo_matrix_t
85 * @src: the source #cairo_matrix_t
87 * Copies @src to @matrix.
89 * Since: 1.0
90 **/
91 void
92 adg_matrix_copy(cairo_matrix_t *matrix, const cairo_matrix_t *src)
94 g_return_if_fail(matrix != NULL);
95 g_return_if_fail(src != NULL);
97 memcpy(matrix, src, sizeof(cairo_matrix_t));
101 * adg_matrix_dup:
102 * @matrix: the souce #cairo_matrix_t
104 * Duplicates @matrix.
106 * Returns: (transfer full): a duplicate of @matrix that must be freed with g_free() when no longer needed.
108 * Since: 1.0
110 cairo_matrix_t *
111 adg_matrix_dup(const cairo_matrix_t *matrix)
113 g_return_val_if_fail(matrix != NULL, NULL);
115 return g_memdup(matrix, sizeof(cairo_matrix_t));
119 * adg_matrix_equal:
120 * @matrix1: the first operand
121 * @matrix2: the second operand
123 * Compares @matrix1 and @matrix2 and returns %TRUE if the matrices are equal.
125 * Returns: %TRUE if @matrix1 is equal to @matrix2, %FALSE otherwise
127 * Since: 1.0
129 gboolean
130 adg_matrix_equal(const cairo_matrix_t *matrix1, const cairo_matrix_t *matrix2)
132 g_return_val_if_fail(matrix1 != NULL, FALSE);
133 g_return_val_if_fail(matrix2 != NULL, FALSE);
135 return
136 matrix1->xx == matrix2->xx &&
137 matrix1->yx == matrix2->yx &&
138 matrix1->xy == matrix2->xy &&
139 matrix1->yy == matrix2->yy &&
140 matrix1->x0 == matrix2->x0 &&
141 matrix1->y0 == matrix2->y0;
145 * adg_matrix_normalize:
146 * @matrix: (inout): the source/destination #cairo_matrix_t
148 * Gets rid of the scaling component of a matrix.
150 * Returns: %TRUE on success, %FALSE on errors
152 * Since: 1.0
154 gboolean
155 adg_matrix_normalize(cairo_matrix_t *matrix)
157 gdouble k;
159 g_return_val_if_fail(matrix != NULL, FALSE);
161 if (matrix->xx != matrix->yy || matrix->xy != -matrix->yx) {
162 g_warning(_("%s: normalization of anamorphic matrices not supported"),
163 G_STRLOC);
164 return FALSE;
167 if (matrix->xy == 0) {
168 k = matrix->xx;
169 } else if (matrix->xx == 0) {
170 k = matrix->xy;
171 } else {
172 k = sqrt(matrix->xx * matrix->xx + matrix->xy * matrix->xy);
175 g_return_val_if_fail(k != 0, FALSE);
177 matrix->xx /= k;
178 matrix->xy /= k;
179 matrix->yy /= k;
180 matrix->yx /= k;
182 return TRUE;
186 * adg_matrix_transform:
187 * @matrix: (inout): the source/destination #cairo_matrix_t
188 * @transformation: the transformation to apply
189 * @mode: (in): how @transformation should be applied
191 * Modifies @matrix applying @transformation in the way specified by
192 * @mode.
194 * Since: 1.0
196 void
197 adg_matrix_transform(cairo_matrix_t *matrix,
198 const cairo_matrix_t *transformation, AdgTransformMode mode)
200 cairo_matrix_t normalized;
202 g_return_if_fail(matrix != NULL);
203 g_return_if_fail(transformation != NULL);
205 switch (mode) {
206 case ADG_TRANSFORM_NONE:
207 break;
208 case ADG_TRANSFORM_BEFORE:
209 cairo_matrix_multiply(matrix, transformation, matrix);
210 break;
211 case ADG_TRANSFORM_AFTER:
212 cairo_matrix_multiply(matrix, matrix, transformation);
213 break;
214 case ADG_TRANSFORM_BEFORE_NORMALIZED:
215 adg_matrix_copy(&normalized, transformation);
216 adg_matrix_normalize(&normalized);
217 cairo_matrix_multiply(matrix, &normalized, matrix);
218 break;
219 case ADG_TRANSFORM_AFTER_NORMALIZED:
220 adg_matrix_copy(&normalized, transformation);
221 adg_matrix_normalize(&normalized);
222 cairo_matrix_multiply(matrix, matrix, &normalized);
223 break;
224 default:
225 g_return_if_reached();
230 * adg_matrix_dump:
231 * @matrix: an #cairo_matrix_t
233 * Dumps the specified @matrix to stdout. Useful for debugging purposes.
235 * Since: 1.0
237 void
238 adg_matrix_dump(const cairo_matrix_t *matrix)
240 g_return_if_fail(matrix != NULL);
242 g_print("[%8.3lf %8.3lf] [%8.3lf]\n"
243 "[%8.3lf %8.3lf] [%8.3lf]\n",
244 matrix->xx, matrix->xy, matrix->x0,
245 matrix->yx, matrix->yy, matrix->y0);