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