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