]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/x11/region.cpp
deal with the situation when a (dynamic) event handler disconnects itself during...
[wxWidgets.git] / src / x11 / region.cpp
... / ...
CommitLineData
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#include "wx/gdicmn.h"
16#include "wx/log.h"
17
18#ifdef __VMS__
19#pragma message disable nosimpint
20#endif
21#include "wx/x11/private.h"
22#include "X11/Xutil.h"
23#ifdef __VMS__
24#pragma message enable nosimpint
25#endif
26
27// ----------------------------------------------------------------------------
28// wxRegionRefData: private class containing the information about the region
29// ----------------------------------------------------------------------------
30
31class wxRegionRefData : public wxObjectRefData
32{
33public:
34 wxRegionRefData()
35 {
36 m_region = NULL;
37 }
38
39 wxRegionRefData(const wxRegionRefData& refData)
40 {
41 m_region = XCreateRegion();
42 XUnionRegion( refData.m_region, m_region, m_region );
43 }
44
45 ~wxRegionRefData()
46 {
47 if (m_region)
48 XDestroyRegion( m_region );
49 }
50
51 Region m_region;
52};
53
54// ----------------------------------------------------------------------------
55// macros
56// ----------------------------------------------------------------------------
57
58#define M_REGIONDATA ((wxRegionRefData *)m_refData)
59#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
60
61IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
62IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject)
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;
73 rect.x = (short)x;
74 rect.y = (short)y;
75 rect.width = (unsigned short)w;
76 rect.height = (unsigned short)h;
77
78 m_refData = new wxRegionRefData();
79
80 M_REGIONDATA->m_region = XCreateRegion();
81 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
82}
83
84wxRegion::wxRegion( size_t WXUNUSED(n), const wxPoint *WXUNUSED(points), int WXUNUSED(fillStyle) )
85{
86#if 0
87 XPoint *xpoints = new XPoint[n];
88 for ( size_t i = 0 ; i < n ; i++ )
89 {
90 xpoints[i].x = points[i].x;
91 xpoints[i].y = points[i].y;
92 }
93
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
108}
109
110wxRegion::~wxRegion()
111{
112 // m_refData unrefed in ~wxObject
113}
114
115wxObjectRefData *wxRegion::CreateRefData() const
116{
117 return new wxRegionRefData;
118}
119
120wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
121{
122 return new wxRegionRefData(*(wxRegionRefData *)data);
123}
124
125// ----------------------------------------------------------------------------
126// wxRegion comparison
127// ----------------------------------------------------------------------------
128
129bool wxRegion::operator==( const wxRegion& region ) const
130{
131 if (m_refData == region.m_refData) return true;
132
133 if (!m_refData || !region.m_refData) return false;
134
135 // compare the regions themselves, not the pointers to ref data!
136 return XEqualRegion( M_REGIONDATA->m_region,
137 M_REGIONDATA_OF(region)->m_region ) == True;
138}
139
140// ----------------------------------------------------------------------------
141// wxRegion operations
142// ----------------------------------------------------------------------------
143
144void wxRegion::Clear()
145{
146 UnRef();
147}
148
149bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
150{
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 )
155 return true;
156
157 XRectangle rect;
158 rect.x = (short)x;
159 rect.y = (short)y;
160 rect.width = (unsigned short)width;
161 rect.height = (unsigned short)height;
162
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
176 return true;
177}
178
179bool wxRegion::Union( const wxRect& rect )
180{
181 return Union( rect.x, rect.y, rect.width, rect.height );
182}
183
184bool wxRegion::Union( const wxRegion& region )
185{
186 if (region.IsNull())
187 return false;
188
189 if (!m_refData)
190 {
191 m_refData = new wxRegionRefData();
192 M_REGIONDATA->m_region = XCreateRegion();
193 }
194 else
195 {
196 AllocExclusive();
197 }
198
199 XUnionRegion( M_REGIONDATA->m_region,
200 M_REGIONDATA_OF(region)->m_region,
201 M_REGIONDATA->m_region );
202
203 return true;
204}
205
206bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
207{
208 wxRegion reg( x, y, width, height );
209
210 return Intersect( reg );
211}
212
213bool wxRegion::Intersect( const wxRect& rect )
214{
215 wxRegion reg( rect );
216
217 return Intersect( reg );
218}
219
220bool wxRegion::Intersect( const wxRegion& region )
221{
222 if (region.IsNull())
223 return false;
224
225 if (!m_refData)
226 {
227 m_refData = new wxRegionRefData();
228 M_REGIONDATA->m_region = XCreateRegion();
229
230 // leave here
231 return true;
232 }
233 else
234 {
235 AllocExclusive();
236 }
237
238 XIntersectRegion( M_REGIONDATA->m_region,
239 M_REGIONDATA_OF(region)->m_region,
240 M_REGIONDATA->m_region );
241
242 return true;
243}
244
245bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
246{
247 wxRegion reg( x, y, width, height );
248 return Subtract( reg );
249}
250
251bool wxRegion::Subtract( const wxRect& rect )
252{
253 wxRegion reg( rect );
254 return Subtract( reg );
255}
256
257bool wxRegion::Subtract( const wxRegion& region )
258{
259 if (region.IsNull())
260 return false;
261
262 if (!m_refData)
263 {
264 m_refData = new wxRegionRefData();
265 M_REGIONDATA->m_region = XCreateRegion();
266 }
267 else
268 {
269 AllocExclusive();
270 }
271
272 XSubtractRegion( M_REGIONDATA->m_region,
273 M_REGIONDATA_OF(region)->m_region,
274 M_REGIONDATA->m_region );
275
276 return true;
277}
278
279bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
280{
281 wxRegion reg( x, y, width, height );
282 return Xor( reg );
283}
284
285bool wxRegion::Xor( const wxRect& rect )
286{
287 wxRegion reg( rect );
288 return Xor( reg );
289}
290
291bool wxRegion::Xor( const wxRegion& region )
292{
293 if (region.IsNull())
294 return false;
295
296 if (!m_refData)
297 {
298 m_refData = new wxRegionRefData();
299 M_REGIONDATA->m_region = XCreateRegion();
300 }
301 else
302 {
303 AllocExclusive();
304 }
305
306 XXorRegion( M_REGIONDATA->m_region,
307 M_REGIONDATA_OF(region)->m_region,
308 M_REGIONDATA->m_region );
309
310 return true;
311}
312
313// ----------------------------------------------------------------------------
314// wxRegion tests
315// ----------------------------------------------------------------------------
316
317void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
318{
319 if (m_refData)
320 {
321 XRectangle rect;
322 XClipBox( M_REGIONDATA->m_region, &rect );
323 x = rect.x;
324 y = rect.y;
325 w = rect.width;
326 h = rect.height;
327 }
328 else
329 {
330 x = 0;
331 y = 0;
332 w = -1;
333 h = -1;
334 }
335}
336
337wxRect wxRegion::GetBox() const
338{
339 wxCoord x, y, w, h;
340 GetBox( x, y, w, h );
341 return wxRect( x, y, w, h );
342}
343
344bool wxRegion::Offset( wxCoord x, wxCoord y )
345{
346 if (!m_refData)
347 return false;
348
349 AllocExclusive();
350
351 XOffsetRegion( M_REGIONDATA->m_region, x, y );
352
353 return true;
354}
355
356bool wxRegion::Empty() const
357{
358 if (!m_refData)
359 return true;
360
361 return XEmptyRegion( M_REGIONDATA->m_region ) == True;
362}
363
364wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
365{
366 if (!m_refData)
367 return wxOutRegion;
368
369 if (XPointInRegion( M_REGIONDATA->m_region, x, y ))
370 return wxInRegion;
371 else
372 return wxOutRegion;
373}
374
375wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
376{
377 if (!m_refData)
378 return wxOutRegion;
379
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;
385 case RectanglePart: return wxPartRegion;
386 }
387 return wxOutRegion;
388}
389
390wxRegionContain wxRegion::Contains(const wxPoint& pt) const
391{
392 return Contains( pt.x, pt.y );
393}
394
395wxRegionContain wxRegion::Contains(const wxRect& rect) const
396{
397 return Contains( rect.x, rect.y, rect.width, rect.height );
398}
399
400WXRegion *wxRegion::GetX11Region() const
401{
402 if (!m_refData)
403 return (WXRegion*) NULL;
404
405 return (WXRegion*) M_REGIONDATA->m_region;
406}
407
408// ----------------------------------------------------------------------------
409// wxRegionIterator
410// ----------------------------------------------------------------------------
411
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
417
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
428{
429public:
430
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};
439
440wxRIRefData::~wxRIRefData()
441{
442 delete [] m_rects;
443}
444
445void wxRIRefData::CreateRects( const wxRegion& region )
446{
447 if (m_rects)
448 delete [] m_rects;
449
450 m_rects = 0;
451 m_numRects = 0;
452
453 if (region.IsEmpty()) return;
454
455 Region r = (Region) region.GetX11Region();
456 if (r)
457 {
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
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 }
482#endif
483 }
484}
485
486wxRegionIterator::wxRegionIterator()
487{
488 m_refData = new wxRIRefData();
489 Reset();
490}
491
492wxRegionIterator::wxRegionIterator( const wxRegion& region )
493{
494 m_refData = new wxRIRefData();
495 Reset(region);
496}
497
498void wxRegionIterator::Reset( const wxRegion& region )
499{
500 m_region = region;
501 ((wxRIRefData*)m_refData)->CreateRects(region);
502 Reset();
503}
504
505bool wxRegionIterator::HaveRects() const
506{
507 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
508}
509
510wxRegionIterator::operator bool () const
511{
512 return HaveRects();
513}
514
515void wxRegionIterator::operator ++ ()
516{
517 if (HaveRects()) ++m_current;
518}
519
520void wxRegionIterator::operator ++ (int)
521{
522 if (HaveRects()) ++m_current;
523}
524
525wxCoord wxRegionIterator::GetX() const
526{
527 if( !HaveRects() ) return 0;
528 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
529}
530
531wxCoord wxRegionIterator::GetY() const
532{
533 if( !HaveRects() ) return 0;
534 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
535}
536
537wxCoord wxRegionIterator::GetW() const
538{
539 if( !HaveRects() ) return -1;
540 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
541}
542
543wxCoord wxRegionIterator::GetH() const
544{
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;
556}