1 | /* GDK - The GIMP Drawing Kit |
2 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
3 | * |
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. |
8 | * |
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. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
16 | */ |
17 | |
18 | /* |
19 | * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS |
20 | * file for a list of people on the GTK+ Team. See the ChangeLog |
21 | * files for a list of changes. These files are distributed with |
22 | * GTK+ at ftp://ftp.gtk.org/pub/gtk/. |
23 | */ |
24 | |
25 | #include "config.h" |
26 | |
27 | #include "gdkrectangle.h" |
28 | #include <cairo-gobject.h> |
29 | |
30 | |
31 | /** |
32 | * SECTION:regions |
33 | * @Short_description: Simple graphical data types |
34 | * @Title: Points and Rectangles |
35 | * |
36 | * GDK provides the #GdkPoint and #GdkRectangle data types for representing pixels |
37 | * and sets of pixels on the screen. Together with Cairo’s #cairo_region_t data |
38 | * type, they make up the central types for representing graphical data. |
39 | * |
40 | * A #GdkPoint represents an x and y coordinate of a point. |
41 | * |
42 | * A #GdkRectangle represents the position and size of a rectangle. |
43 | * The intersection of two rectangles can be computed with |
44 | * gdk_rectangle_intersect(). To find the union of two rectangles use |
45 | * gdk_rectangle_union(). |
46 | * |
47 | * #cairo_region_t is usually used for managing clipping of graphical operations. |
48 | */ |
49 | |
50 | |
51 | /** |
52 | * gdk_rectangle_union: |
53 | * @src1: a #GdkRectangle |
54 | * @src2: a #GdkRectangle |
55 | * @dest: (out): return location for the union of @src1 and @src2 |
56 | * |
57 | * Calculates the union of two rectangles. |
58 | * The union of rectangles @src1 and @src2 is the smallest rectangle which |
59 | * includes both @src1 and @src2 within it. |
60 | * It is allowed for @dest to be the same as either @src1 or @src2. |
61 | * |
62 | * Note that this function does not ignore 'empty' rectangles (ie. with |
63 | * zero width or height). |
64 | */ |
65 | void |
66 | gdk_rectangle_union (const GdkRectangle *src1, |
67 | const GdkRectangle *src2, |
68 | GdkRectangle *dest) |
69 | { |
70 | gint dest_x, dest_y; |
71 | |
72 | g_return_if_fail (src1 != NULL); |
73 | g_return_if_fail (src2 != NULL); |
74 | g_return_if_fail (dest != NULL); |
75 | |
76 | dest_x = MIN (src1->x, src2->x); |
77 | dest_y = MIN (src1->y, src2->y); |
78 | dest->width = MAX (src1->x + src1->width, src2->x + src2->width) - dest_x; |
79 | dest->height = MAX (src1->y + src1->height, src2->y + src2->height) - dest_y; |
80 | dest->x = dest_x; |
81 | dest->y = dest_y; |
82 | } |
83 | |
84 | /** |
85 | * gdk_rectangle_intersect: |
86 | * @src1: a #GdkRectangle |
87 | * @src2: a #GdkRectangle |
88 | * @dest: (out caller-allocates) (allow-none): return location for the |
89 | * intersection of @src1 and @src2, or %NULL |
90 | * |
91 | * Calculates the intersection of two rectangles. It is allowed for |
92 | * @dest to be the same as either @src1 or @src2. If the rectangles |
93 | * do not intersect, @dest’s width and height is set to 0 and its x |
94 | * and y values are undefined. If you are only interested in whether |
95 | * the rectangles intersect, but not in the intersecting area itself, |
96 | * pass %NULL for @dest. |
97 | * |
98 | * Returns: %TRUE if the rectangles intersect. |
99 | */ |
100 | gboolean |
101 | gdk_rectangle_intersect (const GdkRectangle *src1, |
102 | const GdkRectangle *src2, |
103 | GdkRectangle *dest) |
104 | { |
105 | gint dest_x, dest_y; |
106 | gint dest_x2, dest_y2; |
107 | gint return_val; |
108 | |
109 | g_return_val_if_fail (src1 != NULL, FALSE); |
110 | g_return_val_if_fail (src2 != NULL, FALSE); |
111 | |
112 | return_val = FALSE; |
113 | |
114 | dest_x = MAX (src1->x, src2->x); |
115 | dest_y = MAX (src1->y, src2->y); |
116 | dest_x2 = MIN (src1->x + src1->width, src2->x + src2->width); |
117 | dest_y2 = MIN (src1->y + src1->height, src2->y + src2->height); |
118 | |
119 | if (dest_x2 > dest_x && dest_y2 > dest_y) |
120 | { |
121 | if (dest) |
122 | { |
123 | dest->x = dest_x; |
124 | dest->y = dest_y; |
125 | dest->width = dest_x2 - dest_x; |
126 | dest->height = dest_y2 - dest_y; |
127 | } |
128 | return_val = TRUE; |
129 | } |
130 | else if (dest) |
131 | { |
132 | dest->width = 0; |
133 | dest->height = 0; |
134 | } |
135 | |
136 | return return_val; |
137 | } |
138 | |
139 | /** |
140 | * gdk_rectangle_equal: |
141 | * @rect1: a #GdkRectangle |
142 | * @rect2: a #GdkRectangle |
143 | * |
144 | * Checks if the two given rectangles are equal. |
145 | * |
146 | * Returns: %TRUE if the rectangles are equal. |
147 | * |
148 | * Since: 3.20 |
149 | */ |
150 | gboolean |
151 | gdk_rectangle_equal (const GdkRectangle *rect1, |
152 | const GdkRectangle *rect2) |
153 | { |
154 | return rect1->x == rect2->x |
155 | && rect1->y == rect2->y |
156 | && rect1->width == rect2->width |
157 | && rect1->height == rect2->height; |
158 | } |
159 | |
160 | static GdkRectangle * |
161 | gdk_rectangle_copy (const GdkRectangle *rectangle) |
162 | { |
163 | GdkRectangle *result = g_new (GdkRectangle, 1); |
164 | *result = *rectangle; |
165 | |
166 | return result; |
167 | } |
168 | |
169 | /* Transforms between identical boxed types. |
170 | */ |
171 | static void |
172 | gdk_rectangle_value_transform_rect (const GValue *src_value, GValue *dest_value) |
173 | { |
174 | g_value_set_boxed (dest_value, g_value_get_boxed (src_value)); |
175 | } |
176 | |
177 | /* Allow GValue transformation between the identical structs |
178 | * cairo_rectangle_int_t and GdkRectangle. |
179 | */ |
180 | static void |
181 | gdk_rectangle_register_value_transform_funcs (GType gtype_gdk_rectangle) |
182 | { |
183 | /* This function is called from the first call to gdk_rectangle_get_type(), |
184 | * before g_once_init_leave() has been called. |
185 | * If gdk_rectangle_get_type() is called from here (e.g. via |
186 | * GDK_TYPE_RECTANGLE), the program will wait indefinitely at |
187 | * g_once_init_enter() in gdk_rectangle_get_type(). |
188 | */ |
189 | g_value_register_transform_func (CAIRO_GOBJECT_TYPE_RECTANGLE_INT, |
190 | gtype_gdk_rectangle, |
191 | gdk_rectangle_value_transform_rect); |
192 | g_value_register_transform_func (gtype_gdk_rectangle, |
193 | CAIRO_GOBJECT_TYPE_RECTANGLE_INT, |
194 | gdk_rectangle_value_transform_rect); |
195 | } |
196 | |
197 | G_DEFINE_BOXED_TYPE_WITH_CODE (GdkRectangle, gdk_rectangle, |
198 | gdk_rectangle_copy, |
199 | g_free, |
200 | gdk_rectangle_register_value_transform_funcs (g_define_type_id)) |
201 | |
202 | |