adg: require a valid layout in adg_table_row_arrange()
[adg.git] / src / adg / adg-matrix.c
bloba601725be6eb070714926284f1087f99f031db0c
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2015 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 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 <constant>TRUE</constant>
124 * if the matrices are equal.
126 * Returns: <constant>TRUE</constant> if @matrix1 is equal to @matrix2, <constant>FALSE</constant> otherwise.
128 * Since: 1.0
130 gboolean
131 adg_matrix_equal(const cairo_matrix_t *matrix1, const cairo_matrix_t *matrix2)
133 g_return_val_if_fail(matrix1 != NULL, FALSE);
134 g_return_val_if_fail(matrix2 != NULL, FALSE);
136 return
137 matrix1->xx == matrix2->xx &&
138 matrix1->yx == matrix2->yx &&
139 matrix1->xy == matrix2->xy &&
140 matrix1->yy == matrix2->yy &&
141 matrix1->x0 == matrix2->x0 &&
142 matrix1->y0 == matrix2->y0;
146 * adg_matrix_normalize:
147 * @matrix: (inout): the source/destination #cairo_matrix_t
149 * Gets rid of the scaling component of a matrix.
151 * Returns: <constant>TRUE</constant> on success, <constant>FALSE</constant> on errors.
153 * Since: 1.0
155 gboolean
156 adg_matrix_normalize(cairo_matrix_t *matrix)
158 gdouble k;
160 g_return_val_if_fail(matrix != NULL, FALSE);
162 if (matrix->xx != matrix->yy || matrix->xy != -matrix->yx) {
163 g_warning(_("%s: normalization of anamorphic matrices not supported"),
164 G_STRLOC);
165 return FALSE;
168 if (matrix->xy == 0) {
169 k = matrix->xx;
170 } else if (matrix->xx == 0) {
171 k = matrix->xy;
172 } else {
173 k = sqrt(matrix->xx * matrix->xx + matrix->xy * matrix->xy);
176 g_return_val_if_fail(k != 0, FALSE);
178 matrix->xx /= k;
179 matrix->xy /= k;
180 matrix->yy /= k;
181 matrix->yx /= k;
183 return TRUE;
187 * adg_matrix_transform:
188 * @matrix: (inout): the source/destination #cairo_matrix_t
189 * @transformation: the transformation to apply
190 * @mode: (in): how @transformation should be applied
192 * Modifies @matrix applying @transformation in the way specified by
193 * @mode.
195 * Since: 1.0
197 void
198 adg_matrix_transform(cairo_matrix_t *matrix,
199 const cairo_matrix_t *transformation, AdgTransformMode mode)
201 cairo_matrix_t normalized;
203 g_return_if_fail(matrix != NULL);
204 g_return_if_fail(transformation != NULL);
206 switch (mode) {
207 case ADG_TRANSFORM_NONE:
208 break;
209 case ADG_TRANSFORM_BEFORE:
210 cairo_matrix_multiply(matrix, transformation, matrix);
211 break;
212 case ADG_TRANSFORM_AFTER:
213 cairo_matrix_multiply(matrix, matrix, transformation);
214 break;
215 case ADG_TRANSFORM_BEFORE_NORMALIZED:
216 adg_matrix_copy(&normalized, transformation);
217 adg_matrix_normalize(&normalized);
218 cairo_matrix_multiply(matrix, &normalized, matrix);
219 break;
220 case ADG_TRANSFORM_AFTER_NORMALIZED:
221 adg_matrix_copy(&normalized, transformation);
222 adg_matrix_normalize(&normalized);
223 cairo_matrix_multiply(matrix, matrix, &normalized);
224 break;
225 default:
226 g_return_if_reached();
231 * adg_matrix_dump:
232 * @matrix: an #cairo_matrix_t
234 * Dumps the specified @matrix to stdout. Useful for debugging purposes.
236 * Since: 1.0
238 void
239 adg_matrix_dump(const cairo_matrix_t *matrix)
241 g_return_if_fail(matrix != NULL);
243 g_print("[%8.3lf %8.3lf] [%8.3lf]\n"
244 "[%8.3lf %8.3lf] [%8.3lf]\n",
245 matrix->xx, matrix->xy, matrix->x0,
246 matrix->yx, matrix->yy, matrix->y0);