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 |