]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/region.cpp
remove run-time check for now-required GTK 2.4
[wxWidgets.git] / src / gtk / region.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
e4db172a 2// Name: src/gtk/region.cpp
c801d85f
KB
3// Purpose:
4// Author: Robert Roebling
9fe4c99c 5// Modified: VZ at 05.10.00: use AllocExclusive(), comparison fixed
f96aa4d9
RR
6// Id: $Id$
7// Copyright: (c) 1998 Robert Roebling
65571936 8// Licence: wxWindows licence
c801d85f
KB
9/////////////////////////////////////////////////////////////////////////////
10
1e6feb95
VZ
11// ============================================================================
12// declarations
13// ============================================================================
14
1e6feb95
VZ
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
14f355c2
VS
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
b3a44e05
WS
22#include "wx/region.h"
23
e4db172a
WS
24#ifndef WX_PRECOMP
25 #include "wx/log.h"
26#endif
27
9e691f46 28#include "wx/gtk/private.h"
1e6feb95 29
57f2b902 30
1e6feb95
VZ
31// ----------------------------------------------------------------------------
32// wxRegionRefData: private class containing the information about the region
33// ----------------------------------------------------------------------------
c801d85f 34
8f884a0d 35class wxRegionRefData : public wxGDIRefData
c801d85f 36{
864e8bd0 37public:
48850fa7
RR
38 wxRegionRefData()
39 {
40 m_region = NULL;
41 }
57f2b902 42
48850fa7 43 wxRegionRefData(const wxRegionRefData& refData)
8f884a0d 44 : wxGDIRefData()
48850fa7 45 {
48850fa7 46 m_region = gdk_region_copy(refData.m_region);
48850fa7 47 }
57f2b902 48
d3c7fc99 49 virtual ~wxRegionRefData()
48850fa7
RR
50 {
51 if (m_region)
52 gdk_region_destroy( m_region );
53 }
5fc7ede9 54
c801d85f
KB
55 GdkRegion *m_region;
56};
57
1e6feb95
VZ
58// ----------------------------------------------------------------------------
59// macros
60// ----------------------------------------------------------------------------
61
62#define M_REGIONDATA ((wxRegionRefData *)m_refData)
63#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
64
d84afea9
GD
65IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
66IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject)
1e6feb95 67
1e6feb95
VZ
68// ----------------------------------------------------------------------------
69// wxRegion construction
70// ----------------------------------------------------------------------------
c801d85f
KB
71
72#define M_REGIONDATA ((wxRegionRefData *)m_refData)
73
9fe4c99c 74void wxRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
c801d85f 75{
bbe0af5b
RR
76 GdkRectangle rect;
77 rect.x = x;
78 rect.y = y;
79 rect.width = w;
80 rect.height = h;
57f2b902 81
48850fa7 82 m_refData = new wxRegionRefData();
57f2b902 83
9e691f46 84 M_REGIONDATA->m_region = gdk_region_rectangle( &rect );
ff7b1510 85}
c801d85f 86
b15ed747
RR
87wxRegion::wxRegion( GdkRegion *region )
88{
89 m_refData = new wxRegionRefData();
90 M_REGIONDATA->m_region = gdk_region_copy( region );
91}
92
03647350 93wxRegion::wxRegion( size_t n, const wxPoint *points,
89efaf2b 94 wxPolygonFillMode fillStyle )
5549e9f7
VZ
95{
96 GdkPoint *gdkpoints = new GdkPoint[n];
97 for ( size_t i = 0 ; i < n ; i++ )
98 {
99 gdkpoints[i].x = points[i].x;
100 gdkpoints[i].y = points[i].y;
101 }
102
103 m_refData = new wxRegionRefData();
104
105 GdkRegion* reg = gdk_region_polygon
106 (
107 gdkpoints,
108 n,
109 fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
110 : GDK_EVEN_ODD_RULE
111 );
112
113 M_REGIONDATA->m_region = reg;
114
115 delete [] gdkpoints;
116}
117
1e6feb95 118wxRegion::~wxRegion()
c801d85f 119{
e0f0b197 120 // m_refData unrefed in ~wxObject
ff7b1510 121}
c801d85f 122
8f884a0d 123wxGDIRefData *wxRegion::CreateGDIRefData() const
e0f0b197
RR
124{
125 return new wxRegionRefData;
126}
127
8f884a0d 128wxGDIRefData *wxRegion::CloneGDIRefData(const wxGDIRefData *data) const
e0f0b197
RR
129{
130 return new wxRegionRefData(*(wxRegionRefData *)data);
131}
c89f5c02 132
9fe4c99c
VZ
133// ----------------------------------------------------------------------------
134// wxRegion comparison
135// ----------------------------------------------------------------------------
136
8a16d737 137bool wxRegion::DoIsEqual(const wxRegion& region) const
c801d85f 138{
1e6feb95
VZ
139 return gdk_region_equal(M_REGIONDATA->m_region,
140 M_REGIONDATA_OF(region)->m_region);
ff7b1510 141}
c801d85f 142
1e6feb95
VZ
143// ----------------------------------------------------------------------------
144// wxRegion operations
145// ----------------------------------------------------------------------------
146
bf57d1ad 147void wxRegion::Clear()
c801d85f 148{
bbe0af5b 149 UnRef();
ff7b1510 150}
c801d85f 151
8a16d737 152bool wxRegion::DoUnionWithRect(const wxRect& r)
c801d85f 153{
57351df0
VZ
154 // workaround for a strange GTK/X11 bug: taking union with an empty
155 // rectangle results in an empty region which is definitely not what we
156 // want
8a16d737 157 if ( r.IsEmpty() )
b3a44e05 158 return true;
57351df0 159
2b5f62a0 160 if ( !m_refData )
e1208c31 161 {
8a16d737 162 InitRect(r.x, r.y, r.width, r.height);
e1208c31
RR
163 }
164 else
165 {
9fe4c99c 166 AllocExclusive();
1e6feb95 167
2b5f62a0 168 GdkRectangle rect;
8a16d737
VZ
169 rect.x = r.x;
170 rect.y = r.y;
171 rect.width = r.width;
172 rect.height = r.height;
2b5f62a0 173
b7c2d6ff 174 gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
e1208c31 175 }
1e6feb95 176
b3a44e05 177 return true;
ff7b1510 178}
c801d85f 179
8a16d737 180bool wxRegion::DoUnionWithRegion( const wxRegion& region )
c801d85f 181{
a1b806b9 182 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
e1208c31 183
48850fa7
RR
184 if (!m_refData)
185 {
dd4eefcb 186 m_refData = new wxRegionRefData(*M_REGIONDATA_OF(region));
48850fa7
RR
187 }
188 else
189 {
190 AllocExclusive();
dd4eefcb 191 gdk_region_union( M_REGIONDATA->m_region, region.GetRegion() );
48850fa7 192 }
e1208c31 193
b3a44e05 194 return true;
ff7b1510 195}
c801d85f 196
8a16d737 197bool wxRegion::DoIntersect( const wxRegion& region )
c801d85f 198{
a1b806b9 199 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
1e6feb95 200
e1208c31
RR
201 if (!m_refData)
202 {
2b5f62a0 203 // intersecting with invalid region doesn't make sense
b3a44e05 204 return false;
1e6feb95
VZ
205 }
206
2b5f62a0
VZ
207 AllocExclusive();
208
48850fa7 209 gdk_region_intersect( M_REGIONDATA->m_region, region.GetRegion() );
9fe4c99c 210
b3a44e05 211 return true;
ff7b1510 212}
c801d85f 213
8a16d737 214bool wxRegion::DoSubtract( const wxRegion& region )
c801d85f 215{
a1b806b9 216 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
e1208c31
RR
217
218 if (!m_refData)
219 {
2b5f62a0 220 // subtracting from an invalid region doesn't make sense
b3a44e05 221 return false;
48850fa7 222 }
1e6feb95 223
2b5f62a0
VZ
224 AllocExclusive();
225
b7c2d6ff 226 gdk_region_subtract( M_REGIONDATA->m_region, region.GetRegion() );
1e6feb95 227
b3a44e05 228 return true;
ff7b1510 229}
c801d85f 230
8a16d737 231bool wxRegion::DoXor( const wxRegion& region )
c801d85f 232{
a1b806b9 233 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
e1208c31
RR
234
235 if (!m_refData)
236 {
dd4eefcb
VZ
237 // XOR-ing with an invalid region is the same as XOR-ing with an empty
238 // one, i.e. it is simply a copy.
239 m_refData = new wxRegionRefData(*M_REGIONDATA_OF(region));
1e6feb95 240 }
dd4eefcb
VZ
241 else
242 {
243 AllocExclusive();
e1208c31 244
dd4eefcb
VZ
245 gdk_region_xor( M_REGIONDATA->m_region, region.GetRegion() );
246 }
5fc7ede9 247
b3a44e05 248 return true;
ff7b1510 249}
c801d85f 250
8a16d737 251bool wxRegion::DoOffset( wxCoord x, wxCoord y )
2b5f62a0 252{
dd4eefcb 253 wxCHECK_MSG( m_refData, false, wxS("invalid region") );
2b5f62a0
VZ
254
255 AllocExclusive();
256
257 gdk_region_offset( M_REGIONDATA->m_region, x, y );
258
b3a44e05 259 return true;
2b5f62a0
VZ
260}
261
1e6feb95
VZ
262// ----------------------------------------------------------------------------
263// wxRegion tests
264// ----------------------------------------------------------------------------
265
8a16d737 266bool wxRegion::DoGetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
c801d85f 267{
1e6feb95
VZ
268 if ( m_refData )
269 {
270 GdkRectangle rect;
271 gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
272 x = rect.x;
273 y = rect.y;
274 w = rect.width;
275 h = rect.height;
8a16d737
VZ
276
277 return true;
1e6feb95
VZ
278 }
279 else
280 {
281 x = 0;
282 y = 0;
283 w = -1;
284 h = -1;
c801d85f 285
8a16d737
VZ
286 return false;
287 }
ff7b1510 288}
c801d85f 289
8a16d737 290bool wxRegion::IsEmpty() const
c801d85f 291{
e1208c31 292 if (!m_refData)
b3a44e05 293 return true;
e1208c31 294
bbe0af5b 295 return gdk_region_empty( M_REGIONDATA->m_region );
ff7b1510 296}
c801d85f 297
8a16d737 298wxRegionContain wxRegion::DoContainsPoint( wxCoord x, wxCoord y ) const
c801d85f 299{
e1208c31
RR
300 if (!m_refData)
301 return wxOutRegion;
302
bbe0af5b
RR
303 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
304 return wxInRegion;
305 else
306 return wxOutRegion;
ff7b1510 307}
c801d85f 308
8a16d737 309wxRegionContain wxRegion::DoContainsRect(const wxRect& r) const
c801d85f 310{
e1208c31
RR
311 if (!m_refData)
312 return wxOutRegion;
313
bbe0af5b 314 GdkRectangle rect;
8a16d737
VZ
315 rect.x = r.x;
316 rect.y = r.y;
317 rect.width = r.width;
318 rect.height = r.height;
bbe0af5b
RR
319 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
320 switch (res)
321 {
322 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
323 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
324 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
325 }
326 return wxOutRegion;
ff7b1510 327}
c801d85f 328
bf57d1ad 329GdkRegion *wxRegion::GetRegion() const
c801d85f 330{
e1208c31 331 if (!m_refData)
d3b9f782 332 return NULL;
e1208c31 333
bbe0af5b 334 return M_REGIONDATA->m_region;
ff7b1510 335}
c801d85f 336
1e6feb95 337// ----------------------------------------------------------------------------
3d0c4d2e 338// wxRegionIterator
1e6feb95 339// ----------------------------------------------------------------------------
8429bec1 340
55ccdb93 341wxRegionIterator::wxRegionIterator()
3d0c4d2e 342{
55ccdb93
VZ
343 Init();
344 Reset();
345}
3d0c4d2e 346
55ccdb93
VZ
347wxRegionIterator::wxRegionIterator( const wxRegion& region )
348{
349 Init();
350 Reset(region);
351}
3d0c4d2e 352
55ccdb93 353void wxRegionIterator::Init()
3d0c4d2e 354{
55ccdb93
VZ
355 m_rects = NULL;
356 m_numRects = 0;
3d0c4d2e
RR
357}
358
55ccdb93 359wxRegionIterator::~wxRegionIterator()
3d0c4d2e 360{
55ccdb93
VZ
361 wxDELETEA(m_rects);
362}
48850fa7 363
55ccdb93
VZ
364void wxRegionIterator::CreateRects( const wxRegion& region )
365{
366 wxDELETEA(m_rects);
367 m_numRects = 0;
57f2b902 368
48850fa7 369 GdkRegion *gdkregion = region.GetRegion();
3f0fb1d4
VZ
370 if (!gdkregion)
371 return;
57f2b902 372
46a1983a
PC
373 GdkRectangle* gdkrects;
374 gdk_region_get_rectangles(gdkregion, &gdkrects, &m_numRects);
57f2b902 375
46a1983a 376 if (m_numRects)
48850fa7
RR
377 {
378 m_rects = new wxRect[m_numRects];
46a1983a 379 for (int i = 0; i < m_numRects; ++i)
3d0c4d2e 380 {
48850fa7
RR
381 GdkRectangle &gr = gdkrects[i];
382 wxRect &wr = m_rects[i];
383 wr.x = gr.x;
384 wr.y = gr.y;
385 wr.width = gr.width;
386 wr.height = gr.height;
3d0c4d2e 387 }
3d0c4d2e 388 }
9e691f46 389 g_free( gdkrects );
3d0c4d2e
RR
390}
391
3d0c4d2e
RR
392void wxRegionIterator::Reset( const wxRegion& region )
393{
394 m_region = region;
55ccdb93 395 CreateRects(region);
3d0c4d2e
RR
396 Reset();
397}
398
399bool wxRegionIterator::HaveRects() const
400{
55ccdb93 401 return m_current < m_numRects;
3d0c4d2e
RR
402}
403
2b5f62a0 404wxRegionIterator& wxRegionIterator::operator ++ ()
3d0c4d2e 405{
2b5f62a0
VZ
406 if (HaveRects())
407 ++m_current;
3d0c4d2e 408
2b5f62a0 409 return *this;
3d0c4d2e
RR
410}
411
2b5f62a0 412wxRegionIterator wxRegionIterator::operator ++ (int)
3d0c4d2e 413{
2b5f62a0 414 wxRegionIterator tmp = *this;
55ccdb93 415
2b5f62a0
VZ
416 if (HaveRects())
417 ++m_current;
418
419 return tmp;
3d0c4d2e
RR
420}
421
422wxCoord wxRegionIterator::GetX() const
423{
9a83f860 424 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
2b5f62a0 425
55ccdb93 426 return m_rects[m_current].x;
3d0c4d2e
RR
427}
428
429wxCoord wxRegionIterator::GetY() const
430{
9a83f860 431 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
2b5f62a0 432
55ccdb93 433 return m_rects[m_current].y;
3d0c4d2e
RR
434}
435
436wxCoord wxRegionIterator::GetW() const
437{
9a83f860 438 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
2b5f62a0 439
55ccdb93 440 return m_rects[m_current].width;
3d0c4d2e
RR
441}
442
443wxCoord wxRegionIterator::GetH() const
444{
9a83f860 445 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
2b5f62a0 446
55ccdb93 447 return m_rects[m_current].height;
3d0c4d2e
RR
448}
449
1e6feb95
VZ
450wxRect wxRegionIterator::GetRect() const
451{
452 wxRect r;
3379ed37 453 if( HaveRects() )
55ccdb93 454 r = m_rects[m_current];
1e6feb95
VZ
455
456 return r;
457}
ac7d3dd1
RR
458
459wxRegionIterator& wxRegionIterator::operator=(const wxRegionIterator& ri)
460{
701871dc 461 if (this != &ri)
ac7d3dd1 462 {
701871dc 463 wxDELETEA(m_rects);
ac7d3dd1 464
701871dc
PC
465 m_current = ri.m_current;
466 m_numRects = ri.m_numRects;
467 if ( m_numRects )
468 {
469 m_rects = new wxRect[m_numRects];
470 memcpy(m_rects, ri.m_rects, m_numRects * sizeof m_rects[0]);
471 }
472 }
ac7d3dd1
RR
473 return *this;
474}