Moved AdgPair to CpmlPair
[adg.git] / src / cpml / cpml-extents.c
blobe19e932ced523f6f4a40d031e6df6f3588e1986b
1 /* CPML - Cairo Path Manipulation Library
2 * Copyright (C) 2008,2009,2010,2011,2012 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:cpml-extents
23 * @Section_Id:CpmlExtents
24 * @title: CpmlExtents
25 * @short_description: A rectangular area representing a bounding box
27 * The #CpmlExtents struct groups two pairs representing the rectangular
28 * area of a bounding box.
30 * Since: 1.0
31 **/
33 /**
34 * CpmlExtents:
35 * @is_defined: set to %0 when these extents are undefined
36 * @org: the lowest x,y coordinates
37 * @size: the width (x) and height (y) of the extents
39 * A structure defining a bounding box area. These APIs expect the
40 * size of the extents to be always positives, so be careful while
41 * directly accessing the @size field.
43 * Since: 1.0
44 **/
47 #include "cpml-internal.h"
48 #include "cpml-extents.h"
49 #include <string.h>
50 #include <math.h>
53 /**
54 * cpml_extents_copy:
55 * @extents: (out): the destination #CpmlExtents
56 * @src: (in): the source #CpmlExtents
58 * Copies @src in @extents.
60 * Since: 1.0
61 **/
62 void
63 cpml_extents_copy(CpmlExtents *extents, const CpmlExtents *src)
65 memcpy(extents, src, sizeof(CpmlExtents));
68 /**
69 * cpml_extents_from_cairo_text:
70 * @extents: (out): the destination #CpmlExtents
71 * @cairo_extents: (in) (type gpointer): the source #cairo_text_extents_t
73 * Converts @cairo_extents in a #CpmlExtents format and stores the
74 * result in @extents.
76 * Since: 1.0
77 **/
78 void
79 cpml_extents_from_cairo_text(CpmlExtents *extents,
80 const cairo_text_extents_t *cairo_extents)
82 extents->is_defined = 1;
83 extents->org.x = cairo_extents->x_bearing;
84 extents->org.y = cairo_extents->y_bearing;
85 extents->size.x = cairo_extents->width;
86 extents->size.y = cairo_extents->height;
89 /**
90 * cpml_extents_equal:
91 * @extents: the first extents to compare
92 * @src: the second extents to compare
94 * Compares @extents to @src and returns 1 if the extents are equals.
95 * Two %NULL or two undefined extents are considered equal, athough
96 * %NULL extents are not equal to undefined extents.
98 * Returns: (type gboolean): %1 if @extents is equal to @src,
99 * %0 otherwise
101 * Since: 1.0
104 cpml_extents_equal(const CpmlExtents *extents, const CpmlExtents *src)
106 if (extents == NULL && src == NULL)
107 return 1;
109 if (extents == NULL || src == NULL)
110 return 0;
112 return (!extents->is_defined && !src->is_defined) ||
113 (extents->is_defined && src->is_defined &&
114 cpml_pair_equal(&extents->org, &src->org) &&
115 cpml_pair_equal(&extents->size, &src->size));
119 * cpml_extents_add:
120 * @extents: (inout): the destination #CpmlExtents
121 * @src: (in): the extents to add
123 * Merges @extents and @src and store the result in @extents.
125 * Since: 1.0
127 void
128 cpml_extents_add(CpmlExtents *extents, const CpmlExtents *src)
130 CpmlPair pair;
132 if (src->is_defined == 0)
133 return;
135 pair.x = src->org.x + src->size.x;
136 pair.y = src->org.y + src->size.y;
138 cpml_extents_pair_add(extents, &src->org);
139 cpml_extents_pair_add(extents, &pair);
143 * cpml_extents_pair_add:
144 * @extents: (inout): the source and destination #CpmlExtents
145 * @src: (in): the #CpmlPair to add
147 * Extends @extents, if required, to include @src. If @extents is
148 * undefined, the origin of @extents is set to @src and its size
149 * will be (0,0).
151 * Since: 1.0
153 void
154 cpml_extents_pair_add(CpmlExtents *extents, const CpmlPair *src)
156 if (extents->is_defined == 0) {
157 extents->is_defined = 1;
158 cpml_pair_copy(&extents->org, src);
159 extents->size.x = 0;
160 extents->size.y = 0;
161 return;
164 if (src->x < extents->org.x) {
165 extents->size.x += extents->org.x - src->x;
166 extents->org.x = src->x;
167 } else if (src->x > extents->org.x + extents->size.x) {
168 extents->size.x = src->x - extents->org.x;
171 if (src->y < extents->org.y) {
172 extents->size.y += extents->org.y - src->y;
173 extents->org.y = src->y;
174 } else if (src->y > extents->org.y + extents->size.y) {
175 extents->size.y = src->y - extents->org.y;
180 * cpml_extents_is_inside:
181 * @extents: the container #CpmlExtents
182 * @src: the subject #CpmlExtents
184 * Checks wheter @src is enterely contained by @extents. If @extents
185 * is undefined, %0 will be returned. If @src is undefined, %1 will
186 * be returned. The border of @extents is considered inside.
188 * Returns: (type gboolean): %1 if @src is totally inside @extents,
189 * %0 otherwise
191 * Since: 1.0
194 cpml_extents_is_inside(const CpmlExtents *extents, const CpmlExtents *src)
196 CpmlPair pe, ps;
198 if (extents->is_defined == 0)
199 return 0;
201 if (src->is_defined == 0)
202 return 1;
204 cpml_pair_copy(&pe, &extents->org);
205 cpml_pair_copy(&ps, &src->org);
207 if (ps.x < pe.x || ps.y < pe.y)
208 return 0;
210 pe.x += extents->size.x;
211 pe.y += extents->size.y;
212 ps.x += extents->size.x;
213 ps.y += extents->size.y;
215 return ps.x <= pe.x && ps.y <= pe.y;
219 * cpml_extents_pair_is_inside:
220 * @extents: the container #CpmlExtents
221 * @src: the subject #CpmlPair
223 * Checks wheter @src is inside @extents. If @extents is undefined,
224 * %0 will be returned. The border of @extents is considered inside.
226 * Returns: (type gboolean): %1 if @src is inside @extents,
227 * %0 otherwise
229 * Since: 1.0
232 cpml_extents_pair_is_inside(const CpmlExtents *extents, const CpmlPair *src)
234 if (extents->is_defined == 0 ||
235 src->x < extents->org.x || src->y < extents->org.y ||
236 src->x > extents->org.x + extents->size.x ||
237 src->y > extents->org.y + extents->size.y)
238 return 0;
240 return 1;
244 * cpml_extents_transform:
245 * @extents: (inout): the container #CpmlExtents
246 * @matrix: (in): the transformation matrix
248 * Transforms the four corners of @extents with @matrix and
249 * recomputes @extents. This will logically equivalent to transform
250 * an extents box and gets the extents of the resulting shape.
252 * Since: 1.0
254 void
255 cpml_extents_transform(CpmlExtents *extents, const cairo_matrix_t *matrix)
257 CpmlPair p[4];
259 if (extents->is_defined == 0)
260 return;
262 p[0] = extents->org;
263 p[1].x = extents->org.x + extents->size.x;
264 p[1].y = extents->org.y;
265 p[2].x = extents->org.x + extents->size.x;
266 p[2].y = extents->org.y + extents->size.y;
267 p[3].x = extents->org.x;
268 p[3].y = extents->org.y + extents->size.y;
270 cairo_matrix_transform_point(matrix, &p[0].x, &p[0].y);
271 cairo_matrix_transform_point(matrix, &p[1].x, &p[1].y);
272 cairo_matrix_transform_point(matrix, &p[2].x, &p[2].y);
273 cairo_matrix_transform_point(matrix, &p[3].x, &p[3].y);
275 extents->is_defined = 0;
276 cpml_extents_pair_add(extents, &p[0]);
277 cpml_extents_pair_add(extents, &p[1]);
278 cpml_extents_pair_add(extents, &p[2]);
279 cpml_extents_pair_add(extents, &p[3]);