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