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;
CID 10891 - UNINIT_CTOR
Non-static class member field "mRegion.size" is not initialized in this constructor nor in any functions that it calls.
 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 {
 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 }