1 /* CPML - Cairo Path Manipulation Library
2 * Copyright (C) 2007-2021 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.
22 * SECTION:cpml-extents
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.
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.
47 #include "cpml-internal.h"
48 #include "cpml-extents.h"
55 * @extents: (out): the destination #CpmlExtents
56 * @src: (in): the source #CpmlExtents
58 * Copies @src in @extents.
63 cpml_extents_copy(CpmlExtents
*extents
, const CpmlExtents
*src
)
65 memcpy(extents
, src
, sizeof(CpmlExtents
));
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
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
;
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 <constant>NULL</constant> or two undefined extents are considered equal,
96 * although <constant>NULL</constant> extents are not equal to undefined extents.
98 * Returns: (type gboolean): 1 if @extents is equal to @src, 0 otherwise.
103 cpml_extents_equal(const CpmlExtents
*extents
, const CpmlExtents
*src
)
105 if (extents
== NULL
&& src
== NULL
)
108 if (extents
== NULL
|| src
== NULL
)
111 return (!extents
->is_defined
&& !src
->is_defined
) ||
112 (extents
->is_defined
&& src
->is_defined
&&
113 cpml_pair_equal(&extents
->org
, &src
->org
) &&
114 cpml_pair_equal(&extents
->size
, &src
->size
));
119 * @extents: (inout): the destination #CpmlExtents
120 * @src: (in): the extents to add
122 * Merges @extents and @src and store the result in @extents.
127 cpml_extents_add(CpmlExtents
*extents
, const CpmlExtents
*src
)
131 if (src
->is_defined
== 0)
134 pair
.x
= src
->org
.x
+ src
->size
.x
;
135 pair
.y
= src
->org
.y
+ src
->size
.y
;
137 cpml_extents_pair_add(extents
, &src
->org
);
138 cpml_extents_pair_add(extents
, &pair
);
142 * cpml_extents_pair_add:
143 * @extents: (inout): the source and destination #CpmlExtents
144 * @src: (in): the #CpmlPair to add
146 * Extends @extents, if required, to include @src. If @extents is
147 * undefined, the origin of @extents is set to @src and its size
153 cpml_extents_pair_add(CpmlExtents
*extents
, const CpmlPair
*src
)
155 if (extents
->is_defined
== 0) {
156 extents
->is_defined
= 1;
157 cpml_pair_copy(&extents
->org
, src
);
163 if (src
->x
< extents
->org
.x
) {
164 extents
->size
.x
+= extents
->org
.x
- src
->x
;
165 extents
->org
.x
= src
->x
;
166 } else if (src
->x
> extents
->org
.x
+ extents
->size
.x
) {
167 extents
->size
.x
= src
->x
- extents
->org
.x
;
170 if (src
->y
< extents
->org
.y
) {
171 extents
->size
.y
+= extents
->org
.y
- src
->y
;
172 extents
->org
.y
= src
->y
;
173 } else if (src
->y
> extents
->org
.y
+ extents
->size
.y
) {
174 extents
->size
.y
= src
->y
- extents
->org
.y
;
179 * cpml_extents_is_inside:
180 * @extents: the container #CpmlExtents
181 * @src: the subject #CpmlExtents
183 * Checks wheter @src is enterely contained by @extents. If @extents
184 * is undefined, 0 will be returned. If @src is undefined, 1 will
185 * be returned. The border of @extents is considered inside.
187 * Returns: (type gboolean): 1 if @src is totally inside @extents, 0 otherwise.
192 cpml_extents_is_inside(const CpmlExtents
*extents
, const CpmlExtents
*src
)
196 if (extents
->is_defined
== 0)
199 if (src
->is_defined
== 0)
202 cpml_pair_copy(&pe
, &extents
->org
);
203 cpml_pair_copy(&ps
, &src
->org
);
205 if (ps
.x
< pe
.x
|| ps
.y
< pe
.y
)
208 pe
.x
+= extents
->size
.x
;
209 pe
.y
+= extents
->size
.y
;
213 return ps
.x
<= pe
.x
&& ps
.y
<= pe
.y
;
217 * cpml_extents_pair_is_inside:
218 * @extents: the container #CpmlExtents
219 * @src: the subject #CpmlPair
221 * Checks wheter @src is inside @extents. If @extents is undefined,
222 * 0 will be returned. The border of @extents is considered inside.
224 * Returns: (type gboolean): 1 if @src is inside @extents, 0 otherwise.
229 cpml_extents_pair_is_inside(const CpmlExtents
*extents
, const CpmlPair
*src
)
231 if (extents
->is_defined
== 0 ||
232 src
->x
< extents
->org
.x
|| src
->y
< extents
->org
.y
||
233 src
->x
> extents
->org
.x
+ extents
->size
.x
||
234 src
->y
> extents
->org
.y
+ extents
->size
.y
)
241 * cpml_extents_transform:
242 * @extents: (inout): the container #CpmlExtents
243 * @matrix: (in): the transformation matrix
245 * Transforms the four corners of @extents with @matrix and
246 * recomputes @extents. This will logically equivalent to transform
247 * an extents box and gets the extents of the resulting shape.
252 cpml_extents_transform(CpmlExtents
*extents
, const cairo_matrix_t
*matrix
)
256 if (extents
->is_defined
== 0)
260 p
[1].x
= extents
->org
.x
+ extents
->size
.x
;
261 p
[1].y
= extents
->org
.y
;
262 p
[2].x
= extents
->org
.x
+ extents
->size
.x
;
263 p
[2].y
= extents
->org
.y
+ extents
->size
.y
;
264 p
[3].x
= extents
->org
.x
;
265 p
[3].y
= extents
->org
.y
+ extents
->size
.y
;
267 cairo_matrix_transform_point(matrix
, &p
[0].x
, &p
[0].y
);
268 cairo_matrix_transform_point(matrix
, &p
[1].x
, &p
[1].y
);
269 cairo_matrix_transform_point(matrix
, &p
[2].x
, &p
[2].y
);
270 cairo_matrix_transform_point(matrix
, &p
[3].x
, &p
[3].y
);
272 extents
->is_defined
= 0;
273 cpml_extents_pair_add(extents
, &p
[0]);
274 cpml_extents_pair_add(extents
, &p
[1]);
275 cpml_extents_pair_add(extents
, &p
[2]);
276 cpml_extents_pair_add(extents
, &p
[3]);