]> git.saurik.com Git - wxWidgets.git/blob - src/x11/region.cpp
parenthesize macro replacement containing operator
[wxWidgets.git] / src / x11 / region.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // File: src/x11/region.cpp
3 // Purpose: Region class
4 // Author: Julian Smart, Robert Roebling
5 // Created: Fri Oct 24 10:46:34 MET 1997
6 // RCS-ID: $Id$
7 // Copyright: (c) 1997 Julian Smart, Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // for compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #include "wx/region.h"
15
16 #ifndef WX_PRECOMP
17 #include "wx/log.h"
18 #endif
19
20 #include "wx/gdicmn.h"
21
22 #ifdef __VMS__
23 #pragma message disable nosimpint
24 #endif
25 #include "wx/x11/private.h"
26 #include "X11/Xutil.h"
27 #ifdef __VMS__
28 #pragma message enable nosimpint
29 #endif
30
31 // ----------------------------------------------------------------------------
32 // wxRegionRefData: private class containing the information about the region
33 // ----------------------------------------------------------------------------
34
35 class wxRegionRefData : public wxObjectRefData
36 {
37 public:
38 wxRegionRefData()
39 {
40 m_region = NULL;
41 }
42
43 wxRegionRefData(const wxRegionRefData& refData)
44 {
45 m_region = XCreateRegion();
46 XUnionRegion( refData.m_region, m_region, m_region );
47 }
48
49 ~wxRegionRefData()
50 {
51 if (m_region)
52 XDestroyRegion( m_region );
53 }
54
55 Region m_region;
56 };
57
58 // ----------------------------------------------------------------------------
59 // macros
60 // ----------------------------------------------------------------------------
61
62 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
63 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
64
65 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
66 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject)
67
68 // ----------------------------------------------------------------------------
69 // wxRegion construction
70 // ----------------------------------------------------------------------------
71
72 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
73
74 void wxRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
75 {
76 XRectangle rect;
77 rect.x = (short)x;
78 rect.y = (short)y;
79 rect.width = (unsigned short)w;
80 rect.height = (unsigned short)h;
81
82 m_refData = new wxRegionRefData();
83
84 M_REGIONDATA->m_region = XCreateRegion();
85 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
86 }
87
88 wxRegion::wxRegion( size_t WXUNUSED(n), const wxPoint *WXUNUSED(points), int WXUNUSED(fillStyle) )
89 {
90 #if 0
91 XPoint *xpoints = new XPoint[n];
92 for ( size_t i = 0 ; i < n ; i++ )
93 {
94 xpoints[i].x = points[i].x;
95 xpoints[i].y = points[i].y;
96 }
97
98 m_refData = new wxRegionRefData();
99
100 Region* reg = gdk_region_polygon
101 (
102 gdkpoints,
103 n,
104 fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
105 : GDK_EVEN_ODD_RULE
106 );
107
108 M_REGIONDATA->m_region = reg;
109
110 delete [] xpoints;
111 #endif
112 }
113
114 wxRegion::~wxRegion()
115 {
116 // m_refData unrefed in ~wxObject
117 }
118
119 wxObjectRefData *wxRegion::CreateRefData() const
120 {
121 return new wxRegionRefData;
122 }
123
124 wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
125 {
126 return new wxRegionRefData(*(wxRegionRefData *)data);
127 }
128
129 // ----------------------------------------------------------------------------
130 // wxRegion comparison
131 // ----------------------------------------------------------------------------
132
133 bool wxRegion::operator==( const wxRegion& region ) const
134 {
135 if (m_refData == region.m_refData) return true;
136
137 if (!m_refData || !region.m_refData) return false;
138
139 // compare the regions themselves, not the pointers to ref data!
140 return XEqualRegion( M_REGIONDATA->m_region,
141 M_REGIONDATA_OF(region)->m_region ) == True;
142 }
143
144 // ----------------------------------------------------------------------------
145 // wxRegion operations
146 // ----------------------------------------------------------------------------
147
148 void wxRegion::Clear()
149 {
150 UnRef();
151 }
152
153 bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
154 {
155 // work around for XUnionRectWithRegion() bug: taking a union with an empty
156 // rect results in an empty region (at least XFree 3.3.6 and 4.0 have this
157 // problem)
158 if ( !width || !height )
159 return true;
160
161 XRectangle rect;
162 rect.x = (short)x;
163 rect.y = (short)y;
164 rect.width = (unsigned short)width;
165 rect.height = (unsigned short)height;
166
167 if (!m_refData)
168 {
169 m_refData = new wxRegionRefData();
170 M_REGIONDATA->m_region = XCreateRegion();
171 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
172 }
173 else
174 {
175 AllocExclusive();
176
177 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
178 }
179
180 return true;
181 }
182
183 bool wxRegion::Union( const wxRect& rect )
184 {
185 return Union( rect.x, rect.y, rect.width, rect.height );
186 }
187
188 bool wxRegion::Union( const wxRegion& region )
189 {
190 if (region.IsNull())
191 return false;
192
193 if (!m_refData)
194 {
195 m_refData = new wxRegionRefData();
196 M_REGIONDATA->m_region = XCreateRegion();
197 }
198 else
199 {
200 AllocExclusive();
201 }
202
203 XUnionRegion( M_REGIONDATA->m_region,
204 M_REGIONDATA_OF(region)->m_region,
205 M_REGIONDATA->m_region );
206
207 return true;
208 }
209
210 bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
211 {
212 wxRegion reg( x, y, width, height );
213
214 return Intersect( reg );
215 }
216
217 bool wxRegion::Intersect( const wxRect& rect )
218 {
219 wxRegion reg( rect );
220
221 return Intersect( reg );
222 }
223
224 bool wxRegion::Intersect( const wxRegion& region )
225 {
226 if (region.IsNull())
227 return false;
228
229 if (!m_refData)
230 {
231 m_refData = new wxRegionRefData();
232 M_REGIONDATA->m_region = XCreateRegion();
233
234 // leave here
235 return true;
236 }
237 else
238 {
239 AllocExclusive();
240 }
241
242 XIntersectRegion( M_REGIONDATA->m_region,
243 M_REGIONDATA_OF(region)->m_region,
244 M_REGIONDATA->m_region );
245
246 return true;
247 }
248
249 bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
250 {
251 wxRegion reg( x, y, width, height );
252 return Subtract( reg );
253 }
254
255 bool wxRegion::Subtract( const wxRect& rect )
256 {
257 wxRegion reg( rect );
258 return Subtract( reg );
259 }
260
261 bool wxRegion::Subtract( const wxRegion& region )
262 {
263 if (region.IsNull())
264 return false;
265
266 if (!m_refData)
267 {
268 m_refData = new wxRegionRefData();
269 M_REGIONDATA->m_region = XCreateRegion();
270 }
271 else
272 {
273 AllocExclusive();
274 }
275
276 XSubtractRegion( M_REGIONDATA->m_region,
277 M_REGIONDATA_OF(region)->m_region,
278 M_REGIONDATA->m_region );
279
280 return true;
281 }
282
283 bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
284 {
285 wxRegion reg( x, y, width, height );
286 return Xor( reg );
287 }
288
289 bool wxRegion::Xor( const wxRect& rect )
290 {
291 wxRegion reg( rect );
292 return Xor( reg );
293 }
294
295 bool wxRegion::Xor( const wxRegion& region )
296 {
297 if (region.IsNull())
298 return false;
299
300 if (!m_refData)
301 {
302 m_refData = new wxRegionRefData();
303 M_REGIONDATA->m_region = XCreateRegion();
304 }
305 else
306 {
307 AllocExclusive();
308 }
309
310 XXorRegion( M_REGIONDATA->m_region,
311 M_REGIONDATA_OF(region)->m_region,
312 M_REGIONDATA->m_region );
313
314 return true;
315 }
316
317 // ----------------------------------------------------------------------------
318 // wxRegion tests
319 // ----------------------------------------------------------------------------
320
321 void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
322 {
323 if (m_refData)
324 {
325 XRectangle rect;
326 XClipBox( M_REGIONDATA->m_region, &rect );
327 x = rect.x;
328 y = rect.y;
329 w = rect.width;
330 h = rect.height;
331 }
332 else
333 {
334 x = 0;
335 y = 0;
336 w = -1;
337 h = -1;
338 }
339 }
340
341 wxRect wxRegion::GetBox() const
342 {
343 wxCoord x, y, w, h;
344 GetBox( x, y, w, h );
345 return wxRect( x, y, w, h );
346 }
347
348 bool wxRegion::Offset( wxCoord x, wxCoord y )
349 {
350 if (!m_refData)
351 return false;
352
353 AllocExclusive();
354
355 XOffsetRegion( M_REGIONDATA->m_region, x, y );
356
357 return true;
358 }
359
360 bool wxRegion::Empty() const
361 {
362 if (!m_refData)
363 return true;
364
365 return XEmptyRegion( M_REGIONDATA->m_region ) == True;
366 }
367
368 wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
369 {
370 if (!m_refData)
371 return wxOutRegion;
372
373 if (XPointInRegion( M_REGIONDATA->m_region, x, y ))
374 return wxInRegion;
375 else
376 return wxOutRegion;
377 }
378
379 wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
380 {
381 if (!m_refData)
382 return wxOutRegion;
383
384 int res = XRectInRegion( M_REGIONDATA->m_region, x, y, w, h );
385 switch (res)
386 {
387 case RectangleIn: return wxInRegion;
388 case RectangleOut: return wxOutRegion;
389 case RectanglePart: return wxPartRegion;
390 }
391 return wxOutRegion;
392 }
393
394 wxRegionContain wxRegion::Contains(const wxPoint& pt) const
395 {
396 return Contains( pt.x, pt.y );
397 }
398
399 wxRegionContain wxRegion::Contains(const wxRect& rect) const
400 {
401 return Contains( rect.x, rect.y, rect.width, rect.height );
402 }
403
404 WXRegion *wxRegion::GetX11Region() const
405 {
406 if (!m_refData)
407 return (WXRegion*) NULL;
408
409 return (WXRegion*) M_REGIONDATA->m_region;
410 }
411
412 // ----------------------------------------------------------------------------
413 // wxRegionIterator
414 // ----------------------------------------------------------------------------
415
416 // the following structures must match the private structures
417 // in X11 region code ( xc/lib/X11/region.h )
418
419 // this makes the Region type transparent
420 // and we have access to the region rectangles
421
422 struct _XBox {
423 short x1, x2, y1, y2;
424 };
425
426 struct _XRegion {
427 long size , numRects;
428 _XBox *rects, extents;
429 };
430
431 class wxRIRefData: public wxObjectRefData
432 {
433 public:
434
435 wxRIRefData() : m_rects(0), m_numRects(0){}
436 ~wxRIRefData();
437
438 wxRect *m_rects;
439 size_t m_numRects;
440
441 void CreateRects( const wxRegion& r );
442 };
443
444 wxRIRefData::~wxRIRefData()
445 {
446 delete [] m_rects;
447 }
448
449 void wxRIRefData::CreateRects( const wxRegion& region )
450 {
451 if (m_rects)
452 delete [] m_rects;
453
454 m_rects = 0;
455 m_numRects = 0;
456
457 if (region.IsEmpty()) return;
458
459 Region r = (Region) region.GetX11Region();
460 if (r)
461 {
462 #if wxUSE_NANOX
463 GR_RECT rect;
464 GrGetRegionBox(r, & rect);
465 m_numRects = 1;
466 m_rects = new wxRect[1];
467 m_rects[0].x = rect.x;
468 m_rects[0].y = rect.y;
469 m_rects[0].width = rect.width;
470 m_rects[0].height = rect.height;
471 #else
472 m_numRects = r->numRects;
473 if (m_numRects)
474 {
475 m_rects = new wxRect[m_numRects];
476 for (size_t i=0; i < m_numRects; ++i)
477 {
478 _XBox &xr = r->rects[i];
479 wxRect &wr = m_rects[i];
480 wr.x = xr.x1;
481 wr.y = xr.y1;
482 wr.width = xr.x2-xr.x1;
483 wr.height = xr.y2-xr.y1;
484 }
485 }
486 #endif
487 }
488 }
489
490 wxRegionIterator::wxRegionIterator()
491 {
492 m_refData = new wxRIRefData();
493 Reset();
494 }
495
496 wxRegionIterator::wxRegionIterator( const wxRegion& region )
497 {
498 m_refData = new wxRIRefData();
499 Reset(region);
500 }
501
502 void wxRegionIterator::Reset( const wxRegion& region )
503 {
504 m_region = region;
505 ((wxRIRefData*)m_refData)->CreateRects(region);
506 Reset();
507 }
508
509 bool wxRegionIterator::HaveRects() const
510 {
511 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
512 }
513
514 wxRegionIterator::operator bool () const
515 {
516 return HaveRects();
517 }
518
519 void wxRegionIterator::operator ++ ()
520 {
521 if (HaveRects()) ++m_current;
522 }
523
524 void wxRegionIterator::operator ++ (int)
525 {
526 if (HaveRects()) ++m_current;
527 }
528
529 wxCoord wxRegionIterator::GetX() const
530 {
531 if( !HaveRects() ) return 0;
532 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
533 }
534
535 wxCoord wxRegionIterator::GetY() const
536 {
537 if( !HaveRects() ) return 0;
538 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
539 }
540
541 wxCoord wxRegionIterator::GetW() const
542 {
543 if( !HaveRects() ) return -1;
544 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
545 }
546
547 wxCoord wxRegionIterator::GetH() const
548 {
549 if( !HaveRects() ) return -1;
550 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
551 }
552
553 wxRect wxRegionIterator::GetRect() const
554 {
555 wxRect r;
556 if( HaveRects() )
557 r = ((wxRIRefData*)m_refData)->m_rects[m_current];
558
559 return r;
560 }