1 /* CPML - Cairo Path Manipulation Library
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.
25 * @short_description: Basic struct holding a couple of values
27 * The #CpmlPair is a generic 2D structure. It can be used to represent
28 * coordinates, sizes, offsets or whatever have two components.
30 * The name comes from MetaFont.
37 * @x: the x component of the pair
38 * @y: the y component of the pair
40 * A generic 2D structure.
47 * @x: the x component of the vector
48 * @y: the y component of the vector
50 * Another name for #CpmlPair. It is used to clarify when a function
51 * expects a generic pair (usually coordinates) or a vector.
53 * A vector represents a line starting from the origin (0,0) and ending
54 * to the given coordinates pair. Vectors are useful to define direction
55 * and length at once. Keep in mind the cairo default coordinates system
56 * is not problably what you expect: the x axis increases at right
57 * (as usual) but the y axis increases at down (the reverse of a usual
58 * cartesian plan). An angle of 0 is at V=(1; 0) (middle right).
64 #include "cpml-internal.h"
69 static CpmlPair fallback_pair
= { 0, 0 };
73 * cpml_pair_from_cairo:
74 * @pair: the destination #CpmlPair
75 * @path_data: (allow-none) (type gpointer): the original path data point
77 * Sets @pair from a #cairo_path_data_t struct. @path_data should contains
78 * a point data: it is up to the caller to be sure @path_data is valid.
83 cpml_pair_from_cairo(CpmlPair
*pair
, const cairo_path_data_t
*path_data
)
85 if (path_data
!= NULL
) {
86 pair
->x
= path_data
->point
.x
;
87 pair
->y
= path_data
->point
.y
;
93 * @pair: the destination #CpmlPair
94 * @src: (allow-none): the source #CpmlPair
96 * Copies @src in @pair. If @src or @pair is <constant>NULL</constant>,
97 * this function does nothing.
102 cpml_pair_copy(CpmlPair
*pair
, const CpmlPair
*src
)
105 memcpy(pair
, src
, sizeof(CpmlPair
));
111 * @pair: (allow-none): the first pair to compare
112 * @src: (allow-none): the second pair to compare
114 * Compares @pair to @src and returns 1 if the pairs are equals.
115 * Two <constant>NULL</constant> pairs are considered equal.
117 * Returns: (type gboolean): 1 if @pair is equal to @src, 0 otherwise.
122 cpml_pair_equal(const CpmlPair
*pair
, const CpmlPair
*src
)
124 if (pair
== NULL
&& src
== NULL
)
127 if (pair
== NULL
|| src
== NULL
)
130 return pair
->x
== src
->x
&& pair
->y
== src
->y
? 1 : 0;
134 * cpml_pair_transform:
135 * @pair: the destination #CpmlPair struct
136 * @matrix: (allow-none): the transformation matrix
138 * Shortcut to apply a specific transformation matrix to @pair.
143 cpml_pair_transform(CpmlPair
*pair
, const cairo_matrix_t
*matrix
)
145 if (matrix
!= NULL
) {
146 cairo_matrix_transform_point(matrix
, &pair
->x
, &pair
->y
);
151 * cpml_pair_squared_distance:
152 * @from: (allow-none): the first #CpmlPair struct
153 * @to: (allow-none): the second #CpmlPair struct
155 * Gets the squared distance between @from and @to. This value is useful
156 * for comparation purpose: if you need to get the real distance, use
157 * cpml_pair_distance().
159 * @from or @to could be <constant>NULL</constant>, in which case the
160 * fallback <constant>(0, 0)</constant> pair will be used.
162 * Returns: the squared distance
167 cpml_pair_squared_distance(const CpmlPair
*from
, const CpmlPair
*to
)
172 from
= &fallback_pair
;
179 return x
* x
+ y
* y
;
183 * cpml_pair_distance:
184 * @from: (allow-none): the first #CpmlPair struct
185 * @to: (allow-none): the second #CpmlPair struct
187 * Gets the distance between @from and @to. If you need this value only
188 * for comparation purpose, you could use cpml_pair_squared_distance()
191 * @from or @to could be <constant>NULL</constant>, in which case the
192 * fallback <constant>(0, 0)</constant> pair will be used.
194 * The algorithm used is adapted from:
195 * "Replacing Square Roots by Pythagorean Sums"
196 * by Clave Moler and Donald Morrison (1983)
197 * IBM Journal of Research and Development 27 (6): 577–581
198 * http://www.research.ibm.com/journal/rd/276/ibmrd2706P.pdf
200 * Returns: the distance
205 cpml_pair_distance(const CpmlPair
*from
, const CpmlPair
*to
)
211 from
= &fallback_pair
;
248 * cpml_pair_to_cairo:
249 * @pair: the source #CpmlPair
250 * @path_data: (out) (allow-none) (type gpointer): the path data point to modify
252 * Sets a #cairo_path_data_t struct to @pair. This is exactly the reverse
253 * operation of cpml_pair_from_cairo().
258 cpml_pair_to_cairo(const CpmlPair
*pair
, cairo_path_data_t
*path_data
)
260 if (path_data
!= NULL
) {
261 path_data
->point
.x
= pair
->x
;
262 path_data
->point
.y
= pair
->y
;
268 * cpml_vector_from_angle:
269 * @vector: the destination #CpmlVector
270 * @angle: angle of direction, in radians
272 * Calculates the coordinates of the point far 1 from the origin
273 * in the @angle direction. The result is stored in @vector.
278 cpml_vector_from_angle(CpmlVector
*vector
, double angle
)
280 /* Check for common conditions */
281 if (angle
== -M_PI_2
) {
284 } else if (angle
== M_PI_2
) {
287 } else if (angle
== M_PI
|| angle
== -M_PI
) {
290 } else if (angle
== 0) {
294 vector
->x
= cos(angle
);
295 vector
->y
= sin(angle
);
300 * cpml_vector_set_length:
301 * @vector: a #CpmlVector
302 * @length: the new length
304 * Imposes the specified @length to @vector. If the old length is 0
305 * (and so the direction is not known), nothing happens. If @length
306 * is 0, @vector is set to <constant>(0, 0)</constant>.
308 * The @length parameter can be negative, in which case the vector
314 cpml_vector_set_length(CpmlVector
*vector
, double length
)
324 divisor
= cpml_pair_distance(NULL
, vector
);
326 /* Check for valid length (anything other than 0) */
329 vector
->x
/= divisor
;
330 vector
->y
/= divisor
;
336 * @vector: the source #CpmlVector
338 * Gets the angle of @vector, in radians. If @vector is (0, 0),
341 * Returns: the angle in radians, a value between -M_PI and M_PI
346 cpml_vector_angle(const CpmlVector
*vector
)
348 /* Check for common conditions */
350 return vector
->x
>= 0 ? 0 : M_PI
;
352 return vector
->y
> 0 ? M_PI_2
: -M_PI_2
;
353 if (vector
->x
== vector
->y
)
354 return vector
->x
> 0 ? M_PI_4
: -M_PI_4
* 3;
355 if (vector
->x
== -vector
->y
)
356 return vector
->x
> 0 ? -M_PI_4
: M_PI_4
* 3;
358 return atan2(vector
->y
, vector
->x
);
362 * cpml_vector_normal:
363 * @vector: the subject #CpmlVector
365 * Stores in @vector a vector normal to the original @vector.
366 * The length is retained.
368 * The algorithm is really quick because no trigonometry is involved.
373 cpml_vector_normal(CpmlVector
*vector
)
375 double tmp
= vector
->x
;
377 vector
->x
= -vector
->y
;
382 * cpml_vector_transform:
383 * @vector: the destination #CpmlPair struct
384 * @matrix: (allow-none): the transformation matrix
386 * Shortcut to apply a specific transformation matrix to @vector.
387 * It works in a similar way of cpml_pair_transform() but uses
388 * cairo_matrix_transform_distance() instead of
389 * cairo_matrix_transform_point().
394 cpml_vector_transform(CpmlPair
*vector
, const cairo_matrix_t
*matrix
)
396 if (matrix
!= NULL
) {
397 cairo_matrix_transform_distance(matrix
, &vector
->x
, &vector
->y
);