1 /* CPML - Cairo Path Manipulation Library
2 * Copyright (C) 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.
23 * @Section_Id:CpmlPair
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.
35 * @x: the x component of the pair
36 * @y: the y component of the pair
38 * A generic 2D structure.
43 * @x: the x component of the vector
44 * @y: the y component of the vector
46 * Another name for #CpmlPair. It is used to clarify when a function expects
49 * A vector represents a line starting from the origin (0,0) and ending
50 * to the given coordinates pair. Vectors are useful to define directions
51 * and length at once. Keep in mind the cairo default coordinates system
52 * is not problably what you expect: the x axis increases at right
53 * (as usual) but the y axis increases at down (the reverse of a usual
54 * cartesian plan). An angle of 0 is at V=(1; 0) (middle right).
58 #include "cpml-internal.h"
64 static CpmlPair fallback_pair
= { 0, 0 };
69 * @pair: the destination #CpmlPair
70 * @src: the source #CpmlPair
72 * Copies @src in @pair.
75 cpml_pair_copy(CpmlPair
*pair
, const CpmlPair
*src
)
77 memcpy(pair
, src
, sizeof(CpmlPair
));
81 * cpml_pair_from_cairo:
82 * @pair: the destination #CpmlPair
83 * @path_data: the original path data point
85 * Sets @pair from a #cairo_path_data_t struct. @path_data should contains
86 * a point data: it is up to the caller to be sure @path_data is valid.
89 cpml_pair_from_cairo(CpmlPair
*pair
, const cairo_path_data_t
*path_data
)
91 pair
->x
= path_data
->point
.x
;
92 pair
->y
= path_data
->point
.y
;
100 * Negates the coordinates of @pair.
103 cpml_pair_negate(CpmlPair
*pair
)
113 * Inverts (1/x) the coordinates of @pair. If @pair cannot be inverted
114 * because one coordinate is 0, 0 is returned and no transformation is
117 * Returns: 1 on success, 0 on errors
120 cpml_pair_invert(CpmlPair
*pair
)
122 if (pair
->x
== 0 || pair
->y
== 0)
125 pair
->x
= 1. / pair
->x
;
126 pair
->y
= 1. / pair
->y
;
132 * @pair: the destination #CpmlPair
133 * @src: the source pair to add
135 * Adds @src to @pair and stores the result in @pair. In other words,
136 * @pair = @pair + @src.
139 cpml_pair_add(CpmlPair
*pair
, const CpmlPair
*src
)
147 * @pair: the destination #CpmlPair
148 * @src: the source pair to subtract
150 * Subtracts @src from @pair and stores the result in @pair. In other words,
151 * @pair = @pair - @src.
154 cpml_pair_sub(CpmlPair
*pair
, const CpmlPair
*src
)
162 * @pair: the destination #CpmlPair
163 * @src: the source pair factor
165 * Multiplies the x coordinate of @pair by the @src x factor and the
166 * y coordinate by the @src y factor.
169 cpml_pair_mul(CpmlPair
*pair
, const CpmlPair
*src
)
177 * @pair: the destination #CpmlPair
178 * @src: the source pair divisor
180 * Divides the x coordinate of @pair by the @src x divisor and the
181 * y coordinate by the @src y divisor. If @pair cannot be divided
182 * because of a division by 0, 0 is returned and no transformation
185 * Returns: 1 on success, 0 on errors
188 cpml_pair_div(CpmlPair
*pair
, const CpmlPair
*src
)
190 if (src
->x
== 0 || src
->y
== 0)
199 * cpml_pair_transform:
200 * @pair: the destination #CpmlPair struct
201 * @matrix: the transformation matrix
203 * Shortcut to apply a specific transformation matrix to @pair.
206 cpml_pair_transform(CpmlPair
*pair
, const cairo_matrix_t
*matrix
)
208 cairo_matrix_transform_point(matrix
, &pair
->x
, &pair
->y
);
212 * cpml_pair_squared_distance:
213 * @from: the first #CpmlPair struct
214 * @to: the second #CpmlPair struct
216 * Gets the squared distance between @from and @to. This value is useful
217 * for comparation purpose: if you need to get the real distance, use
218 * cpml_pair_distance().
220 * @from or @to could be %NULL, in which case the fallback (0, 0) pair
223 * Returns: the squared distance
226 cpml_pair_squared_distance(const CpmlPair
*from
, const CpmlPair
*to
)
231 from
= &fallback_pair
;
238 return x
* x
+ y
* y
;
242 * cpml_pair_distance:
243 * @from: the first #CpmlPair struct
244 * @to: the second #CpmlPair struct
245 * @distance: where to store the result
247 * Gets the distance between @from and @to, storing the result in @distance.
248 * If you need this value only for comparation purpose, you could use
249 * cpm_pair_squared_distance() instead.
251 * @from or @to could be %NULL, in which case the fallback (0, 0) pair
254 * The algorithm used is adapted from:
255 * "Replacing Square Roots by Pythagorean Sums"
256 * by Clave Moler and Donald Morrison (1983)
257 * IBM Journal of Research and Development 27 (6): 577–581
258 * http://www.research.ibm.com/journal/rd/276/ibmrd2706P.pdf
260 * Returns: the distance
263 cpml_pair_distance(const CpmlPair
*from
, const CpmlPair
*to
)
269 from
= &fallback_pair
;
306 * cpml_pair_to_cairo:
307 * @pair: the destination #CpmlPair
308 * @path_data: the original path data point
310 * Sets a #cairo_path_data_t struct to @pair. This is exactly the reverse
311 * operation of cpml_pair_from_cairo().
314 cpml_pair_to_cairo(const CpmlPair
*pair
, cairo_path_data_t
*path_data
)
316 path_data
->point
.x
= pair
->x
;
317 path_data
->point
.y
= pair
->y
;
322 * cpml_vector_from_angle:
323 * @vector: the destination #CpmlVector
324 * @angle: angle of direction, in radians
326 * Calculates the coordinates of the point far %1 from the origin
327 * in the @angle direction. The result is stored in @vector.
330 cpml_vector_from_angle(CpmlVector
*vector
, double angle
)
332 /* Check for common conditions */
333 if (angle
== -M_PI_2
) {
336 } else if (angle
== M_PI_2
) {
339 } else if (angle
== M_PI
|| angle
== -M_PI
) {
342 } else if (angle
== 0) {
346 vector
->x
= cos(angle
);
347 vector
->y
= sin(angle
);
352 * cpml_vector_set_length:
353 * @vector: a #CpmlVector
354 * @length: the new length
356 * Imposes the specified @length to @vector. If the old length is %0
357 * (and so the direction is not known), nothing happens. If @length
358 * is %0, @vector is set to (0, 0).
360 * The @length parameter can be negative, in which case the vector
364 cpml_vector_set_length(CpmlVector
*vector
, double length
)
374 divisor
= cpml_pair_distance(NULL
, vector
);
376 /* Check for valid length (anything other than 0) */
379 vector
->x
/= divisor
;
380 vector
->y
/= divisor
;
386 * @vector: the source #CpmlVector
388 * Gets the angle of @vector, in radians. If @vector is (0, 0),
391 * Returns: the angle in radians, a value between -M_PI and M_PI
394 cpml_vector_angle(const CpmlVector
*vector
)
396 /* Check for common conditions */
398 return vector
->x
>= 0 ? 0 : M_PI
;
400 return vector
->y
> 0 ? M_PI_2
: -M_PI_2
;
401 if (vector
->x
== vector
->y
)
402 return vector
->x
> 0 ? M_PI_4
: -M_PI_4
* 3;
403 if (vector
->x
== -vector
->y
)
404 return vector
->x
> 0 ? -M_PI_4
: M_PI_4
* 3;
406 return atan2(vector
->y
, vector
->x
);
410 * cpml_vector_normal:
411 * @vector: the subject #CpmlVector
413 * Stores in @vector a vector normal to the original @vector.
414 * The length is retained.
416 * The algorithm is really quick because no trigonometry is involved.
419 cpml_vector_normal(CpmlVector
*vector
)
421 double tmp
= vector
->x
;
423 vector
->x
= -vector
->y
;
428 * cpml_vector_transform:
429 * @vector: the destination #CpmlPair struct
430 * @matrix: the transformation matrix
432 * Shortcut to apply a specific transformation matrix to @vector.
433 * It works in a similar way of cpml_pair_transform() but uses
434 * cairo_matrix_transform_distance() instead of
435 * cairo_matrix_transform_point().
438 cpml_vector_transform(CpmlPair
*vector
, const cairo_matrix_t
*matrix
)
440 cairo_matrix_transform_distance(matrix
, &vector
->x
, &vector
->y
);