1 /* Libart_LGPL - library of basic graphic primitives
2 * Copyright (C) 1998 Raph Levien
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library 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 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20 #include "config.h"
21 #include "art_rect.h"
22
23 #include <math.h>
24
25 #ifndef MAX
26 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
27 #endif /* MAX */
28
29 #ifndef MIN
30 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
31 #endif /* MIN */
32
33 /* rectangle primitives stolen from gzilla */
34
35 /**
36 * art_irect_copy: Make a copy of an integer rectangle.
37 * @dest: Where the copy is stored.
38 * @src: The source rectangle.
39 *
40 * Copies the rectangle.
41 **/
42 void
art_irect_copy(ArtIRect * dest,const ArtIRect * src)43 art_irect_copy (ArtIRect *dest, const ArtIRect *src) {
44 dest->x0 = src->x0;
45 dest->y0 = src->y0;
46 dest->x1 = src->x1;
47 dest->y1 = src->y1;
48 }
49
50 /**
51 * art_irect_union: Find union of two integer rectangles.
52 * @dest: Where the result is stored.
53 * @src1: A source rectangle.
54 * @src2: Another source rectangle.
55 *
56 * Finds the smallest rectangle that includes @src1 and @src2.
57 **/
58 void
art_irect_union(ArtIRect * dest,const ArtIRect * src1,const ArtIRect * src2)59 art_irect_union (ArtIRect *dest, const ArtIRect *src1, const ArtIRect *src2) {
60 if (art_irect_empty (src1)) {
61 art_irect_copy (dest, src2);
62 } else if (art_irect_empty (src2)) {
63 art_irect_copy (dest, src1);
64 } else {
65 dest->x0 = MIN (src1->x0, src2->x0);
66 dest->y0 = MIN (src1->y0, src2->y0);
67 dest->x1 = MAX (src1->x1, src2->x1);
68 dest->y1 = MAX (src1->y1, src2->y1);
69 }
70 }
71
72 /**
73 * art_irect_intersection: Find intersection of two integer rectangles.
74 * @dest: Where the result is stored.
75 * @src1: A source rectangle.
76 * @src2: Another source rectangle.
77 *
78 * Finds the intersection of @src1 and @src2.
79 **/
80 void
art_irect_intersect(ArtIRect * dest,const ArtIRect * src1,const ArtIRect * src2)81 art_irect_intersect (ArtIRect *dest, const ArtIRect *src1, const ArtIRect *src2) {
82 dest->x0 = MAX (src1->x0, src2->x0);
83 dest->y0 = MAX (src1->y0, src2->y0);
84 dest->x1 = MIN (src1->x1, src2->x1);
85 dest->y1 = MIN (src1->y1, src2->y1);
86 }
87
88 /**
89 * art_irect_empty: Determine whether integer rectangle is empty.
90 * @src: The source rectangle.
91 *
92 * Return value: TRUE if @src is an empty rectangle, FALSE otherwise.
93 **/
94 int
art_irect_empty(const ArtIRect * src)95 art_irect_empty (const ArtIRect *src) {
96 return (src->x1 <= src->x0 || src->y1 <= src->y0);
97 }
98
99 #if 0
100 gboolean irect_point_inside (ArtIRect *rect, GzwPoint *point) {
101 return (point->x >= rect->x0 && point->y >= rect->y0 &&
102 point->x < rect->x1 && point->y < rect->y1);
103 }
104 #endif
105
106 /**
107 * art_drect_copy: Make a copy of a rectangle.
108 * @dest: Where the copy is stored.
109 * @src: The source rectangle.
110 *
111 * Copies the rectangle.
112 **/
113 void
art_drect_copy(ArtDRect * dest,const ArtDRect * src)114 art_drect_copy (ArtDRect *dest, const ArtDRect *src) {
115 dest->x0 = src->x0;
116 dest->y0 = src->y0;
117 dest->x1 = src->x1;
118 dest->y1 = src->y1;
119 }
120
121 /**
122 * art_drect_union: Find union of two rectangles.
123 * @dest: Where the result is stored.
124 * @src1: A source rectangle.
125 * @src2: Another source rectangle.
126 *
127 * Finds the smallest rectangle that includes @src1 and @src2.
128 **/
129 void
art_drect_union(ArtDRect * dest,const ArtDRect * src1,const ArtDRect * src2)130 art_drect_union (ArtDRect *dest, const ArtDRect *src1, const ArtDRect *src2) {
131 if (art_drect_empty (src1)) {
132 art_drect_copy (dest, src2);
133 } else if (art_drect_empty (src2)) {
134 art_drect_copy (dest, src1);
135 } else {
136 dest->x0 = MIN (src1->x0, src2->x0);
137 dest->y0 = MIN (src1->y0, src2->y0);
138 dest->x1 = MAX (src1->x1, src2->x1);
139 dest->y1 = MAX (src1->y1, src2->y1);
140 }
141 }
142
143 /**
144 * art_drect_intersection: Find intersection of two rectangles.
145 * @dest: Where the result is stored.
146 * @src1: A source rectangle.
147 * @src2: Another source rectangle.
148 *
149 * Finds the intersection of @src1 and @src2.
150 **/
151 void
art_drect_intersect(ArtDRect * dest,const ArtDRect * src1,const ArtDRect * src2)152 art_drect_intersect (ArtDRect *dest, const ArtDRect *src1, const ArtDRect *src2) {
153 dest->x0 = MAX (src1->x0, src2->x0);
154 dest->y0 = MAX (src1->y0, src2->y0);
155 dest->x1 = MIN (src1->x1, src2->x1);
156 dest->y1 = MIN (src1->y1, src2->y1);
157 }
158
159 /**
160 * art_irect_empty: Determine whether rectangle is empty.
161 * @src: The source rectangle.
162 *
163 * Return value: TRUE if @src is an empty rectangle, FALSE otherwise.
164 **/
165 int
art_drect_empty(const ArtDRect * src)166 art_drect_empty (const ArtDRect *src) {
167 return (src->x1 <= src->x0 || src->y1 <= src->y0);
168 }
169
170 /**
171 * art_drect_affine_transform: Affine transform rectangle.
172 * @dst: Where to store the result.
173 * @src: The source rectangle.
174 * @matrix: The affine transformation.
175 *
176 * Find the smallest rectangle enclosing the affine transformed @src.
177 * The result is exactly the affine transformation of @src when
178 * @matrix specifies a rectilinear affine transformation, otherwise it
179 * is a conservative approximation.
180 **/
181 void
art_drect_affine_transform(ArtDRect * dst,const ArtDRect * src,const double matrix[6])182 art_drect_affine_transform (ArtDRect *dst, const ArtDRect *src, const double matrix[6])
183 {
184 double x00, y00, x10, y10;
185 double x01, y01, x11, y11;
186
187 x00 = src->x0 * matrix[0] + src->y0 * matrix[2] + matrix[4];
188 y00 = src->x0 * matrix[1] + src->y0 * matrix[3] + matrix[5];
189 x10 = src->x1 * matrix[0] + src->y0 * matrix[2] + matrix[4];
190 y10 = src->x1 * matrix[1] + src->y0 * matrix[3] + matrix[5];
191 x01 = src->x0 * matrix[0] + src->y1 * matrix[2] + matrix[4];
192 y01 = src->x0 * matrix[1] + src->y1 * matrix[3] + matrix[5];
193 x11 = src->x1 * matrix[0] + src->y1 * matrix[2] + matrix[4];
194 y11 = src->x1 * matrix[1] + src->y1 * matrix[3] + matrix[5];
195 dst->x0 = MIN (MIN (x00, x10), MIN (x01, x11));
196 dst->y0 = MIN (MIN (y00, y10), MIN (y01, y11));
197 dst->x1 = MAX (MAX (x00, x10), MAX (x01, x11));
198 dst->y1 = MAX (MAX (y00, y10), MAX (y01, y11));
199 }
200
201 /**
202 * art_drect_to_irect: Convert rectangle to integer rectangle.
203 * @dst: Where to store resulting integer rectangle.
204 * @src: The source rectangle.
205 *
206 * Find the smallest integer rectangle that encloses @src.
207 **/
208 void
art_drect_to_irect(ArtIRect * dst,ArtDRect * src)209 art_drect_to_irect (ArtIRect *dst, ArtDRect *src)
210 {
211 dst->x0 = floor (src->x0);
212 dst->y0 = floor (src->y0);
213 dst->x1 = ceil (src->x1);
214 dst->y1 = ceil (src->y1);
215 }
216