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