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