1 /*
2 * Copyright �� 2008 Dennis Kasprzyk
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Dennis Kasprzyk not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Dennis Kasprzyk makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
24 */
25
26 #include <X11/Xlib.h>
27 #include <X11/Xregion.h>
28 #include <core/rect.h>
29 #include <math.h>
30 #include <stdlib.h>
31
32
33 CompRect::CompRect ()
34 {
35 mRegion.rects = &mRegion.extents;
36 mRegion.numRects = 1;
37 mRegion.extents.x1 = 0;
38 mRegion.extents.x2 = 0;
39 mRegion.extents.y1 = 0;
40 mRegion.extents.y2 = 0;
41 }
42
43 CompRect::CompRect (int x, int y, int width, int height)
44 {
45 mRegion.rects = &mRegion.extents;
46 mRegion.numRects = 1;
47 mRegion.extents.x1 = x;
48 mRegion.extents.y1 = y;
49 mRegion.extents.x2 = x + width;
50 mRegion.extents.y2 = y + height;
51 }
52
53 CompRect::CompRect (const CompRect& r)
54 {
55 mRegion = r.mRegion;
56 mRegion.rects = &mRegion.extents;
57 }
58
59 CompRect::CompRect (const XRectangle xr)
60 {
61 mRegion.rects = &mRegion.extents;
62 mRegion.numRects = 1;
63 mRegion.extents.x1 = xr.x;
64 mRegion.extents.y1 = xr.y;
65 mRegion.extents.x2 = xr.x + xr.width;
66 mRegion.extents.y2 = xr.y + xr.height;
67 }
68
69 CompPoint
70 compiz::rect::wraparoundPoint (const CompRect &bounds, const CompPoint &p)
71 {
72 CompPoint r (p);
73
74 if (p.x () > bounds.x2 ())
75 r.setX ((p.x () % bounds.width ()) + bounds.x1 ());
76 else if (p.x () < bounds.x1 ())
77 r.setX (bounds.width () - (abs (p.x ()) % bounds.width ()));
78
79 if (p.y () > bounds.y2 ())
80 r.setY ((p.y () % bounds.height ()) + bounds.y1 ());
81 else if (p.y () < bounds.y1 ())
82 r.setY (bounds.height () - (abs (p.y ()) % bounds.height ()));
83
84 return r;
85 }
86
87 Region
88 CompRect::region () const
89 {
CID 10884 - PW.CAST_TO_QUALIFIED_TYPE
type qualifier is meaningless on cast type
90 return const_cast<const Region> (&mRegion);
91 }
92
93 void
94 CompRect::setGeometry (int x,
95 int y,
96 int width,
97 int height)
98 {
99 mRegion.extents.x1 = x;
100 mRegion.extents.y1 = y;
101 mRegion.extents.x2 = x + width;
102 mRegion.extents.y2 = y + height;
103 }
104
105 void
106 CompRect::setX (int x)
107 {
108 int width = mRegion.extents.x2 - mRegion.extents.x1;
109
110 mRegion.extents.x1 = x;
111 mRegion.extents.x2 = x + width;
112 }
113
114 void
115 CompRect::setY (int y)
116 {
117 int height = mRegion.extents.y2 - mRegion.extents.y1;
118
119 mRegion.extents.y1 = y;
120 mRegion.extents.y2 = y + height;
121 }
122
123 void
124 CompRect::setPos (const CompPoint& pos)
125 {
126 setX (pos.x ());
127 setY (pos.y ());
128 }
129
130 void
131 CompRect::setWidth (int width)
132 {
133 mRegion.extents.x2 = mRegion.extents.x1 + width;
134 }
135
136 void
137 CompRect::setHeight (int height)
138 {
139 mRegion.extents.y2 = mRegion.extents.y1 + height;
140 }
141
142 void
143 CompRect::setSize (const CompSize& size)
144 {
145 mRegion.extents.x2 = mRegion.extents.x1 + size.width ();
146 mRegion.extents.y2 = mRegion.extents.y1 + size.height ();
147 }
148
149 void
150 CompRect::setLeft (int x1)
151 {
152 mRegion.extents.x1 = x1;
153 if (mRegion.extents.x2 < x1)
154 mRegion.extents.x2 = x1;
155 }
156
157 void
158 CompRect::setTop (int y1)
159 {
160 mRegion.extents.y1 = y1;
161 if (mRegion.extents.y2 < y1)
162 mRegion.extents.y2 = y1;
163 }
164
165 void
166 CompRect::setRight (int x2)
167 {
168 mRegion.extents.x2 = x2;
169 if (mRegion.extents.x1 > x2)
170 mRegion.extents.x1 = x2;
171 }
172
173 void
174 CompRect::setBottom (int y2)
175 {
176 mRegion.extents.y2 = y2;
177 if (mRegion.extents.y1 > y2)
178 mRegion.extents.y1 = y2;
179 }
180
181 bool
182 CompRect::contains (const CompPoint& point) const
183 {
184 if (point.x () < x1 ())
185 return false;
186 if (point.x () > x2 ())
187 return false;
188 if (point.y () < y1 ())
189 return false;
190 if (point.y () > y2 ())
191 return false;
192
193 return true;
194 }
195
196 bool
197 CompRect::contains (const CompRect& rect) const
198 {
199 if (rect.x1 () < x1 ())
200 return false;
201 if (rect.x2 () > x2 ())
202 return false;
203 if (rect.y1 () < y1 ())
204 return false;
205 if (rect.y2 () > y2 ())
206 return false;
207
208 return true;
209 }
210
211 bool
212 CompRect::intersects (const CompRect& rect) const
213 {
214 int l, r, t, b;
215
216 /* extents of overlapping rectangle */
217 l = MAX (left (), rect.left ());
218 r = MIN (right (), rect.right ());
219 t = MAX (top (), rect.top ());
220 b = MIN (bottom (), rect.bottom ());
221
222 return (l < r) && (t < b);
223 }
224
225 bool
226 CompRect::isEmpty () const
227 {
228 return mRegion.extents.x1 == mRegion.extents.x2 ||
229 mRegion.extents.y1 == mRegion.extents.y2;
230 }
231
232 int
233 CompRect::area () const
234 {
235 if (mRegion.extents.x2 < mRegion.extents.x1)
236 return 0;
237 if (mRegion.extents.y2 < mRegion.extents.y1)
238 return 0;
239
240 return (mRegion.extents.x2 - mRegion.extents.x1) *
241 (mRegion.extents.y2 - mRegion.extents.y1);
242 }
243
244 bool
245 CompRect::operator== (const CompRect &rect) const
246 {
247 if (mRegion.extents.x1 != rect.mRegion.extents.x1)
248 return false;
249 if (mRegion.extents.y1 != rect.mRegion.extents.y1)
250 return false;
251 if (mRegion.extents.x2 != rect.mRegion.extents.x2)
252 return false;
253 if (mRegion.extents.y2 != rect.mRegion.extents.y2)
254 return false;
255
256 return true;
257 }
258
259 bool
260 CompRect::operator!= (const CompRect &rect) const
261 {
262 return !(*this == rect);
263 }
264
265 CompRect
266 CompRect::operator& (const CompRect &rect) const
267 {
268 CompRect result (*this);
269
270 result &= rect;
271 return result;
272 }
273
274 CompRect&
275 CompRect::operator&= (const CompRect &rect)
276 {
277 int l, r, t, b;
278
279 /* extents of overlapping rectangle */
280 l = MAX (left (), rect.left ());
281 r = MIN (right (), rect.right ());
282 t = MAX (top (), rect.top ());
283 b = MIN (bottom (), rect.bottom ());
284
285 mRegion.extents.x1 = l;
286 mRegion.extents.x2 = r;
287 mRegion.extents.y1 = t;
288 mRegion.extents.y2 = b;
289
290 /* FIXME: This can result in negative widths
291 * and heights, which makes no sense */
292
293 return *this;
294 }
295
296 CompRect &
297 CompRect::operator= (const CompRect &rect)
298 {
299 mRegion.extents.x1 = rect.mRegion.extents.x1;
300 mRegion.extents.y1 = rect.mRegion.extents.y1;
301 mRegion.extents.x2 = rect.mRegion.extents.x2;
302 mRegion.extents.y2 = rect.mRegion.extents.y2;
303
304 return *this;
305 }