1 /********************************************************************************
2 *                                                                               *
3 *                      C l i p p i n g   R e g i o n                            *
4 *                                                                               *
5 *********************************************************************************
6 * Copyright (C) 2000,2021 by Jeroen van der Zijp.   All Rights Reserved.        *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or modify          *
9 * it under the terms of the GNU Lesser General Public License as published by   *
10 * the Free Software Foundation; either version 3 of the License, or             *
11 * (at your option) any later version.                                           *
12 *                                                                               *
13 * This library is distributed in the hope that it will be useful,               *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 *
16 * GNU Lesser General Public License for more details.                           *
17 *                                                                               *
18 * You should have received a copy of the GNU Lesser General Public License      *
19 * along with this program.  If not, see <http://www.gnu.org/licenses/>          *
20 ********************************************************************************/
21 #include "xincs.h"
22 #include "fxver.h"
23 #include "fxdefs.h"
24 #include "fxmath.h"
25 #include "FXArray.h"
26 #include "FXHash.h"
27 #include "FXStream.h"
28 #include "FXSize.h"
29 #include "FXPoint.h"
30 #include "FXRectangle.h"
31 #include "FXRegion.h"
32 
33 
34 /*
35   Notes:
36   - Add some more ways to create regions
37 */
38 
39 
40 using namespace FX;
41 
42 /*******************************************************************************/
43 
44 namespace FX {
45 
46 // Construct new empty region
FXRegion()47 FXRegion::FXRegion(){
48 #ifdef WIN32
49   region=(void*)CreateRectRgn(0,0,0,0);
50 #else
51   region=XCreateRegion();
52 #endif
53   }
54 
55 
56 // Construct rectangle region
FXRegion(FXint x,FXint y,FXint w,FXint h)57 FXRegion::FXRegion(FXint x,FXint y,FXint w,FXint h){
58 #ifdef WIN32
59   region=(void*)CreateRectRgn(x,y,x+w,y+h);
60 #else
61   XRectangle r;
62   r.x=x; r.y=y; r.width=w; r.height=h;
63   region=XCreateRegion();
64   XUnionRectWithRegion(&r,(Region)region,(Region)region);
65 #endif
66   }
67 
68 
69 // Construct new region from rectangle rect
FXRegion(const FXRectangle & rect)70 FXRegion::FXRegion(const FXRectangle& rect){
71 #ifdef WIN32
72   region=(void*)CreateRectRgn(rect.x,rect.y,rect.x+rect.w,rect.y+rect.h);
73 #else
74   region=XCreateRegion();
75   XUnionRectWithRegion((XRectangle*)&rect,(Region)region,(Region)region);
76 #endif
77   }
78 
79 
80 // Construct polygon region
FXRegion(const FXPoint * points,FXuint npoints,FXbool winding)81 FXRegion::FXRegion(const FXPoint* points,FXuint npoints,FXbool winding){
82 #ifdef WIN32
83   FXuint i;
84   POINT pts[1024];
85   for(i=0; i<npoints; i++){
86     pts[i].x=points[i].x;
87     pts[i].y=points[i].y;
88     }
89   region=(void*)CreatePolygonRgn(pts,npoints,winding?WINDING:ALTERNATE);
90 #else
91   region=XPolygonRegion((XPoint*)points,npoints,winding?WindingRule:EvenOddRule);
92 #endif
93   }
94 
95 
96 // Construct new region copied from region r
FXRegion(const FXRegion & r)97 FXRegion::FXRegion(const FXRegion& r){
98 #ifdef WIN32
99   region=(void*)CreateRectRgn(0,0,0,0);
100   CombineRgn((HRGN)region,(HRGN)r.region,(HRGN)region,RGN_COPY);
101 #else
102   region=XCreateRegion();
103   XUnionRegion((Region)r.region,(Region)region,(Region)region);
104 #endif
105   }
106 
107 
108 // Assign region r to this one
operator =(const FXRegion & r)109 FXRegion& FXRegion::operator=(const FXRegion& r){
110 #ifdef WIN32
111   CombineRgn((HRGN)region,(HRGN)r.region,(HRGN)r.region,RGN_COPY);
112 #else
113   if(region!=r.region){
114     XDestroyRegion((Region)region);
115     region=XCreateRegion();
116     XUnionRegion((Region)r.region,(Region)region,(Region)region);
117     }
118 #endif
119   return *this;
120   }
121 
122 
123 // Return true if region is empty
empty() const124 FXbool FXRegion::empty() const {
125 #ifdef WIN32
126   return OffsetRgn((HRGN)region,0,0)==NULLREGION;
127 #else
128   return XEmptyRegion((Region)region);
129 #endif
130   }
131 
132 
133 // Return true if region contains point
contains(FXint x,FXint y) const134 FXbool FXRegion::contains(FXint x,FXint y) const {
135 #ifdef WIN32
136   return region && PtInRegion((HRGN)region,x,y);
137 #else
138   return XPointInRegion((Region)region,x,y);
139 #endif
140   }
141 
142 // Return true if region contains rectangle
143 // Contributed by Daniel Gehriger <gehriger@linkcad.com>.
contains(FXint x,FXint y,FXint w,FXint h) const144 FXbool FXRegion::contains(FXint x,FXint y,FXint w,FXint h) const {
145 #ifdef WIN32
146   RECT rect;
147   rect.left   = x;
148   rect.top    = y;
149   rect.right  = x + w;
150   rect.bottom = y + h;
151   return region && RectInRegion((HRGN)region,&rect);
152 #else
153   return XRectInRegion((Region)region,x,y,w,h);
154 #endif
155   }
156 
157 
158 // Return bounding box
bounds() const159 FXRectangle FXRegion::bounds() const {
160 #ifdef WIN32
161   RECT rect;
162   GetRgnBox((HRGN)region,&rect);
163   return FXRectangle((FXshort)rect.left,(FXshort)rect.top,(FXshort)(rect.right-rect.left),(FXshort)(rect.bottom-rect.top));
164 #else
165   XRectangle rect;
166   XClipBox((Region)region,&rect);
167   return FXRectangle(rect.x,rect.y,rect.width,rect.height);
168 #endif
169   }
170 
171 
172 // Offset region by dx,dy
offset(FXint dx,FXint dy)173 FXRegion& FXRegion::offset(FXint dx,FXint dy){
174 #ifdef WIN32
175   OffsetRgn((HRGN)region,dx,dy);
176 #else
177   XOffsetRegion((Region)region,dx,dy);
178 #endif
179   return *this;
180   }
181 
182 
183 // Return true if region equal to this one
operator ==(const FXRegion & r) const184 FXbool FXRegion::operator==(const FXRegion& r) const {
185 #ifdef WIN32
186   return EqualRgn((HRGN)region,(HRGN)r.region)!=0;
187 #else
188   return XEqualRegion((Region)region,(Region)r.region);
189 #endif
190   }
191 
192 
193 // Return true if region not equal to this one
operator !=(const FXRegion & r) const194 FXbool FXRegion::operator!=(const FXRegion& r) const {
195 #ifdef WIN32
196   return EqualRgn((HRGN)region,(HRGN)r.region)==0;
197 #else
198   return !XEqualRegion((Region)region,(Region)r.region);
199 #endif
200   }
201 
202 
203 // Union region r with this one
operator +=(const FXRegion & r)204 FXRegion& FXRegion::operator+=(const FXRegion& r){
205 #ifdef WIN32
206   CombineRgn((HRGN)region,(HRGN)region,(HRGN)r.region,RGN_OR);
207 #else
208   Region res=XCreateRegion();
209   XUnionRegion((Region)region,(Region)r.region,res);
210   XDestroyRegion((Region)region);
211   region=res;
212 #endif
213   return *this;
214   }
215 
216 
217 // Intersect region r with this one
operator *=(const FXRegion & r)218 FXRegion& FXRegion::operator*=(const FXRegion& r){
219 #ifdef WIN32
220   CombineRgn((HRGN)region,(HRGN)region,(HRGN)r.region,RGN_AND);
221 #else
222   Region res=XCreateRegion();
223   XIntersectRegion((Region)region,(Region)r.region,res);
224   XDestroyRegion((Region)region);
225   region=res;
226 #endif
227   return *this;
228   }
229 
230 
231 // Subtract region r from this one
operator -=(const FXRegion & r)232 FXRegion& FXRegion::operator-=(const FXRegion& r){
233 #ifdef WIN32
234   CombineRgn((HRGN)region,(HRGN)region,(HRGN)r.region,RGN_DIFF);
235 #else
236   Region res=XCreateRegion();
237   XSubtractRegion((Region)region,(Region)r.region,res);
238   XDestroyRegion((Region)region);
239   region=res;
240 #endif
241   return *this;
242   }
243 
244 
245 // Xor region r with this one
operator ^=(const FXRegion & r)246 FXRegion& FXRegion::operator^=(const FXRegion& r){
247 #ifdef WIN32
248   CombineRgn((HRGN)region,(HRGN)region,(HRGN)r.region,RGN_XOR);
249 #else
250   Region res=XCreateRegion();
251   XXorRegion((Region)region,(Region)r.region,res);
252   XDestroyRegion((Region)region);
253   region=res;
254 #endif
255   return *this;
256   }
257 
258 
259 // Union region r with this one
operator +(const FXRegion & r) const260 FXRegion FXRegion::operator+(const FXRegion& r) const {
261   FXRegion res;
262 #ifdef WIN32
263   CombineRgn((HRGN)res.region,(HRGN)region,(HRGN)r.region,RGN_OR);
264 #else
265   XUnionRegion((Region)region,(Region)r.region,(Region)res.region);
266 #endif
267   return res;
268   }
269 
270 
271 // Intersect region r with this one
operator *(const FXRegion & r) const272 FXRegion FXRegion::operator*(const FXRegion& r) const {
273   FXRegion res;
274 #ifdef WIN32
275   CombineRgn((HRGN)res.region,(HRGN)region,(HRGN)r.region,RGN_AND);
276 #else
277   XIntersectRegion((Region)region,(Region)r.region,(Region)res.region);
278 #endif
279   return res;
280   }
281 
282 
283 // Subtract region r from this one
operator -(const FXRegion & r) const284 FXRegion FXRegion::operator-(const FXRegion& r) const {
285   FXRegion res;
286 #ifdef WIN32
287   CombineRgn((HRGN)res.region,(HRGN)region,(HRGN)r.region,RGN_DIFF);
288 #else
289   XSubtractRegion((Region)region,(Region)r.region,(Region)res.region);
290 #endif
291   return res;
292   }
293 
294 
295 // Xor region r with this one
operator ^(const FXRegion & r) const296 FXRegion FXRegion::operator^(const FXRegion& r) const {
297   FXRegion res;
298 #ifdef WIN32
299   CombineRgn((HRGN)res.region,(HRGN)region,(HRGN)r.region,RGN_XOR);
300 #else
301   XXorRegion((Region)region,(Region)r.region,(Region)res.region);
302 #endif
303   return res;
304   }
305 
306 
307 // Reset region to empty
reset()308 void FXRegion::reset(){
309 #ifdef WIN32
310   DeleteObject((HRGN)region);
311   region=(void*)CreateRectRgn(0,0,0,0);
312 #else
313   XDestroyRegion((Region)region);
314   region=XCreateRegion();
315 #endif
316   }
317 
318 
319 // Destroy region
~FXRegion()320 FXRegion::~FXRegion(){
321 #ifdef WIN32
322   DeleteObject((HRGN)region);
323 #else
324   XDestroyRegion((Region)region);
325 #endif
326   }
327 
328 }
329 
330