]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/region.cpp
Missing header.
[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
e4db172a
WS
22#ifndef WX_PRECOMP
23 #include "wx/log.h"
24#endif
25
9e691f46 26#include "wx/region.h"
9e691f46 27#include "wx/gtk/private.h"
1e6feb95 28
57f2b902 29
1e6feb95
VZ
30// ----------------------------------------------------------------------------
31// wxRegionRefData: private class containing the information about the region
32// ----------------------------------------------------------------------------
c801d85f 33
1e6feb95 34class wxRegionRefData : public wxObjectRefData
c801d85f 35{
864e8bd0 36public:
48850fa7
RR
37 wxRegionRefData()
38 {
39 m_region = NULL;
40 }
57f2b902 41
48850fa7 42 wxRegionRefData(const wxRegionRefData& refData)
d84afea9 43 : wxObjectRefData()
48850fa7 44 {
48850fa7 45 m_region = gdk_region_copy(refData.m_region);
48850fa7 46 }
57f2b902 47
48850fa7
RR
48 ~wxRegionRefData()
49 {
50 if (m_region)
51 gdk_region_destroy( m_region );
52 }
5fc7ede9 53
c801d85f
KB
54 GdkRegion *m_region;
55};
56
1e6feb95
VZ
57// ----------------------------------------------------------------------------
58// macros
59// ----------------------------------------------------------------------------
60
61#define M_REGIONDATA ((wxRegionRefData *)m_refData)
62#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
63
d84afea9
GD
64IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
65IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject)
1e6feb95 66
1e6feb95
VZ
67// ----------------------------------------------------------------------------
68// wxRegion construction
69// ----------------------------------------------------------------------------
c801d85f
KB
70
71#define M_REGIONDATA ((wxRegionRefData *)m_refData)
72
9fe4c99c 73void wxRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
c801d85f 74{
bbe0af5b
RR
75 GdkRectangle rect;
76 rect.x = x;
77 rect.y = y;
78 rect.width = w;
79 rect.height = h;
57f2b902 80
48850fa7 81 m_refData = new wxRegionRefData();
57f2b902 82
9e691f46 83 M_REGIONDATA->m_region = gdk_region_rectangle( &rect );
ff7b1510 84}
c801d85f 85
b15ed747
RR
86wxRegion::wxRegion( GdkRegion *region )
87{
88 m_refData = new wxRegionRefData();
89 M_REGIONDATA->m_region = gdk_region_copy( region );
90}
91
5549e9f7
VZ
92wxRegion::wxRegion( size_t n, const wxPoint *points, int fillStyle )
93{
94 GdkPoint *gdkpoints = new GdkPoint[n];
95 for ( size_t i = 0 ; i < n ; i++ )
96 {
97 gdkpoints[i].x = points[i].x;
98 gdkpoints[i].y = points[i].y;
99 }
100
101 m_refData = new wxRegionRefData();
102
103 GdkRegion* reg = gdk_region_polygon
104 (
105 gdkpoints,
106 n,
107 fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
108 : GDK_EVEN_ODD_RULE
109 );
110
111 M_REGIONDATA->m_region = reg;
112
113 delete [] gdkpoints;
114}
115
1e6feb95 116wxRegion::~wxRegion()
c801d85f 117{
e0f0b197 118 // m_refData unrefed in ~wxObject
ff7b1510 119}
c801d85f 120
e0f0b197
RR
121wxObjectRefData *wxRegion::CreateRefData() const
122{
123 return new wxRegionRefData;
124}
125
126wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
127{
128 return new wxRegionRefData(*(wxRegionRefData *)data);
129}
c89f5c02 130
9fe4c99c
VZ
131// ----------------------------------------------------------------------------
132// wxRegion comparison
133// ----------------------------------------------------------------------------
134
fbfb8bcc 135bool wxRegion::operator==( const wxRegion& region ) const
c801d85f 136{
c89f5c02
RR
137 if (m_refData == region.m_refData) return TRUE;
138
139 if (!m_refData || !region.m_refData) return FALSE;
57f2b902 140
9fe4c99c 141 // compare the regions themselves, not the pointers to ref data!
1e6feb95
VZ
142 return gdk_region_equal(M_REGIONDATA->m_region,
143 M_REGIONDATA_OF(region)->m_region);
ff7b1510 144}
c801d85f 145
1e6feb95
VZ
146// ----------------------------------------------------------------------------
147// wxRegion operations
148// ----------------------------------------------------------------------------
149
bf57d1ad 150void wxRegion::Clear()
c801d85f 151{
bbe0af5b 152 UnRef();
ff7b1510 153}
c801d85f 154
5fc7ede9 155bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 156{
57351df0
VZ
157 // workaround for a strange GTK/X11 bug: taking union with an empty
158 // rectangle results in an empty region which is definitely not what we
159 // want
160 if ( !width || !height )
161 return TRUE;
162
2b5f62a0 163 if ( !m_refData )
e1208c31 164 {
2b5f62a0 165 InitRect(x, y, width, height);
e1208c31
RR
166 }
167 else
168 {
9fe4c99c 169 AllocExclusive();
1e6feb95 170
2b5f62a0
VZ
171 GdkRectangle rect;
172 rect.x = x;
173 rect.y = y;
174 rect.width = width;
175 rect.height = height;
176
b7c2d6ff 177 gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
e1208c31 178 }
1e6feb95 179
bbe0af5b 180 return TRUE;
ff7b1510 181}
c801d85f
KB
182
183bool wxRegion::Union( const wxRect& rect )
184{
e1208c31 185 return Union( rect.x, rect.y, rect.width, rect.height );
ff7b1510 186}
c801d85f
KB
187
188bool wxRegion::Union( const wxRegion& region )
189{
e1208c31
RR
190 if (region.IsNull())
191 return FALSE;
192
48850fa7
RR
193 if (!m_refData)
194 {
195 m_refData = new wxRegionRefData();
196 M_REGIONDATA->m_region = gdk_region_new();
197 }
198 else
199 {
200 AllocExclusive();
201 }
e1208c31 202
b7c2d6ff 203 gdk_region_union( M_REGIONDATA->m_region, region.GetRegion() );
5fc7ede9 204
bbe0af5b 205 return TRUE;
ff7b1510 206}
c801d85f 207
5fc7ede9 208bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 209{
bbe0af5b 210 wxRegion reg( x, y, width, height );
1e6feb95
VZ
211
212 return Intersect( reg );
ff7b1510 213}
c801d85f
KB
214
215bool wxRegion::Intersect( const wxRect& rect )
216{
bbe0af5b 217 wxRegion reg( rect );
57f2b902 218
1e6feb95 219 return Intersect( reg );
ff7b1510 220}
c801d85f 221
1e6feb95 222bool wxRegion::Intersect( const wxRegion& region )
c801d85f 223{
1e6feb95
VZ
224 if (region.IsNull())
225 return FALSE;
226
e1208c31
RR
227 if (!m_refData)
228 {
2b5f62a0
VZ
229 // intersecting with invalid region doesn't make sense
230 return FALSE;
1e6feb95
VZ
231 }
232
2b5f62a0
VZ
233 AllocExclusive();
234
48850fa7 235 gdk_region_intersect( M_REGIONDATA->m_region, region.GetRegion() );
9fe4c99c 236
bbe0af5b 237 return TRUE;
ff7b1510 238}
c801d85f 239
1e6feb95 240bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 241{
1e6feb95
VZ
242 wxRegion reg( x, y, width, height );
243 return Subtract( reg );
244}
e1208c31 245
1e6feb95
VZ
246bool wxRegion::Subtract( const wxRect& rect )
247{
bbe0af5b 248 wxRegion reg( rect );
1e6feb95 249 return Subtract( reg );
ff7b1510 250}
c801d85f
KB
251
252bool wxRegion::Subtract( const wxRegion& region )
253{
e1208c31
RR
254 if (region.IsNull())
255 return FALSE;
256
257 if (!m_refData)
258 {
2b5f62a0
VZ
259 // subtracting from an invalid region doesn't make sense
260 return FALSE;
48850fa7 261 }
1e6feb95 262
2b5f62a0
VZ
263 AllocExclusive();
264
b7c2d6ff 265 gdk_region_subtract( M_REGIONDATA->m_region, region.GetRegion() );
1e6feb95 266
bbe0af5b 267 return TRUE;
ff7b1510 268}
c801d85f 269
5fc7ede9 270bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 271{
bbe0af5b 272 wxRegion reg( x, y, width, height );
1e6feb95 273 return Xor( reg );
ff7b1510 274}
c801d85f
KB
275
276bool wxRegion::Xor( const wxRect& rect )
277{
bbe0af5b 278 wxRegion reg( rect );
1e6feb95 279 return Xor( reg );
ff7b1510 280}
c801d85f
KB
281
282bool wxRegion::Xor( const wxRegion& region )
283{
e1208c31 284 if (region.IsNull())
05a11043 285 return FALSE;
e1208c31
RR
286
287 if (!m_refData)
288 {
2b5f62a0 289 return FALSE;
1e6feb95 290 }
e1208c31 291
2b5f62a0
VZ
292 AllocExclusive();
293
b7c2d6ff 294 gdk_region_xor( M_REGIONDATA->m_region, region.GetRegion() );
5fc7ede9 295
bbe0af5b 296 return TRUE;
ff7b1510 297}
c801d85f 298
2b5f62a0
VZ
299bool wxRegion::Offset( wxCoord x, wxCoord y )
300{
301 if (!m_refData)
302 return FALSE;
303
304 AllocExclusive();
305
306 gdk_region_offset( M_REGIONDATA->m_region, x, y );
307
308 return TRUE;
309}
310
1e6feb95
VZ
311// ----------------------------------------------------------------------------
312// wxRegion tests
313// ----------------------------------------------------------------------------
314
e1208c31 315void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
c801d85f 316{
1e6feb95
VZ
317 if ( m_refData )
318 {
319 GdkRectangle rect;
320 gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
321 x = rect.x;
322 y = rect.y;
323 w = rect.width;
324 h = rect.height;
325 }
326 else
327 {
328 x = 0;
329 y = 0;
330 w = -1;
331 h = -1;
332 }
ff7b1510 333}
c801d85f 334
bf57d1ad 335wxRect wxRegion::GetBox() const
c801d85f 336{
1e6feb95 337 wxCoord x, y, w, h;
bbe0af5b
RR
338 GetBox( x, y, w, h );
339 return wxRect( x, y, w, h );
ff7b1510 340}
c801d85f 341
bf57d1ad 342bool wxRegion::Empty() const
c801d85f 343{
e1208c31
RR
344 if (!m_refData)
345 return TRUE;
346
bbe0af5b 347 return gdk_region_empty( M_REGIONDATA->m_region );
ff7b1510 348}
c801d85f 349
5fc7ede9 350wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
c801d85f 351{
e1208c31
RR
352 if (!m_refData)
353 return wxOutRegion;
354
bbe0af5b
RR
355 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
356 return wxInRegion;
357 else
358 return wxOutRegion;
ff7b1510 359}
c801d85f 360
5fc7ede9 361wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
c801d85f 362{
e1208c31
RR
363 if (!m_refData)
364 return wxOutRegion;
365
bbe0af5b
RR
366 GdkRectangle rect;
367 rect.x = x;
368 rect.y = y;
369 rect.width = w;
370 rect.height = h;
371 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
372 switch (res)
373 {
374 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
375 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
376 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
377 }
378 return wxOutRegion;
ff7b1510 379}
c801d85f 380
8429bec1
RR
381wxRegionContain wxRegion::Contains(const wxPoint& pt) const
382{
bbe0af5b 383 return Contains( pt.x, pt.y );
8429bec1
RR
384}
385
386wxRegionContain wxRegion::Contains(const wxRect& rect) const
387{
bbe0af5b 388 return Contains( rect.x, rect.y, rect.width, rect.height );
8429bec1
RR
389}
390
bf57d1ad 391GdkRegion *wxRegion::GetRegion() const
c801d85f 392{
e1208c31
RR
393 if (!m_refData)
394 return (GdkRegion*) NULL;
395
bbe0af5b 396 return M_REGIONDATA->m_region;
ff7b1510 397}
c801d85f 398
1e6feb95 399// ----------------------------------------------------------------------------
3d0c4d2e 400// wxRegionIterator
1e6feb95 401// ----------------------------------------------------------------------------
8429bec1 402
3d0c4d2e
RR
403class wxRIRefData: public wxObjectRefData
404{
405public:
3f0fb1d4
VZ
406 wxRIRefData() { Init(); }
407 virtual ~wxRIRefData();
3d0c4d2e 408
3f0fb1d4
VZ
409 void CreateRects( const wxRegion& r );
410
411 void Init() { m_rects = NULL; m_numRects = 0; }
3d0c4d2e
RR
412
413 wxRect *m_rects;
414 size_t m_numRects;
3d0c4d2e
RR
415};
416
417wxRIRefData::~wxRIRefData()
418{
64423153 419 delete [] m_rects;
3d0c4d2e
RR
420}
421
3d0c4d2e
RR
422void wxRIRefData::CreateRects( const wxRegion& region )
423{
64423153 424 delete [] m_rects;
48850fa7 425
3f0fb1d4 426 Init();
57f2b902 427
48850fa7 428 GdkRegion *gdkregion = region.GetRegion();
3f0fb1d4
VZ
429 if (!gdkregion)
430 return;
57f2b902 431
9e691f46 432 GdkRectangle *gdkrects = NULL;
48850fa7 433 gint numRects = 0;
9e691f46 434 gdk_region_get_rectangles( gdkregion, &gdkrects, &numRects );
57f2b902 435
48850fa7
RR
436 m_numRects = numRects;
437 if (numRects)
438 {
439 m_rects = new wxRect[m_numRects];
440 for (size_t i=0; i < m_numRects; ++i)
3d0c4d2e 441 {
48850fa7
RR
442 GdkRectangle &gr = gdkrects[i];
443 wxRect &wr = m_rects[i];
444 wr.x = gr.x;
445 wr.y = gr.y;
446 wr.width = gr.width;
447 wr.height = gr.height;
3d0c4d2e 448 }
3d0c4d2e 449 }
9e691f46 450 g_free( gdkrects );
3d0c4d2e
RR
451}
452
3d0c4d2e
RR
453wxRegionIterator::wxRegionIterator()
454{
455 m_refData = new wxRIRefData();
456 Reset();
457}
458
459wxRegionIterator::wxRegionIterator( const wxRegion& region )
460{
461 m_refData = new wxRIRefData();
462 Reset(region);
463}
464
465void wxRegionIterator::Reset( const wxRegion& region )
466{
467 m_region = region;
468 ((wxRIRefData*)m_refData)->CreateRects(region);
469 Reset();
470}
471
472bool wxRegionIterator::HaveRects() const
473{
474 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
475}
476
2b5f62a0 477wxRegionIterator& wxRegionIterator::operator ++ ()
3d0c4d2e 478{
2b5f62a0
VZ
479 if (HaveRects())
480 ++m_current;
3d0c4d2e 481
2b5f62a0 482 return *this;
3d0c4d2e
RR
483}
484
2b5f62a0 485wxRegionIterator wxRegionIterator::operator ++ (int)
3d0c4d2e 486{
2b5f62a0
VZ
487 wxRegionIterator tmp = *this;
488 if (HaveRects())
489 ++m_current;
490
491 return tmp;
3d0c4d2e
RR
492}
493
494wxCoord wxRegionIterator::GetX() const
495{
2b5f62a0
VZ
496 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
497
3d0c4d2e
RR
498 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
499}
500
501wxCoord wxRegionIterator::GetY() const
502{
2b5f62a0
VZ
503 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
504
3d0c4d2e
RR
505 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
506}
507
508wxCoord wxRegionIterator::GetW() const
509{
2b5f62a0
VZ
510 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
511
3d0c4d2e
RR
512 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
513}
514
515wxCoord wxRegionIterator::GetH() const
516{
2b5f62a0
VZ
517 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
518
3d0c4d2e
RR
519 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
520}
521
1e6feb95
VZ
522wxRect wxRegionIterator::GetRect() const
523{
524 wxRect r;
3379ed37
VZ
525 if( HaveRects() )
526 r = ((wxRIRefData*)m_refData)->m_rects[m_current];
1e6feb95
VZ
527
528 return r;
529}