]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/region.cpp
Shouldn't call SetFont(wxNullFont) any more
[wxWidgets.git] / src / gtk / region.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
5fc7ede9 2// Name: gtk/region.cpp
c801d85f
KB
3// Purpose:
4// Author: Robert Roebling
1e6feb95 5// Modified: VZ at 05.10.00: use Unshare(), comparison fixed
f96aa4d9
RR
6// Id: $Id$
7// Copyright: (c) 1998 Robert Roebling
5fc7ede9 8// Licence: wxWindows licence
c801d85f
KB
9/////////////////////////////////////////////////////////////////////////////
10
1e6feb95
VZ
11// ============================================================================
12// declarations
13// ============================================================================
14
c801d85f 15#ifdef __GNUG__
1e6feb95 16 #pragma implementation "region.h"
c801d85f
KB
17#endif
18
1e6feb95
VZ
19// ----------------------------------------------------------------------------
20// headers
21// ----------------------------------------------------------------------------
22
c801d85f
KB
23#include "wx/region.h"
24
aed8ac3f
RR
25#include <gdk/gdk.h>
26#include <gtk/gtk.h>
bbe0af5b 27
d52e91c9
JS
28// Unfortunately the new way of implementing the region iterator
29// doesn't work with GTK+ 2.0 or above (can't access a Region in
30// GdkPrivateRegion)
31#ifdef __WXGTK20__
32#define OLDCODE 1
33#else
3d0c4d2e 34#define OLDCODE 0
d52e91c9 35#endif
864e8bd0 36
1e6feb95
VZ
37#include "wx/log.h"
38
39// ----------------------------------------------------------------------------
40// wxRegionRefData: private class containing the information about the region
41// ----------------------------------------------------------------------------
c801d85f 42
1e6feb95 43class wxRegionRefData : public wxObjectRefData
c801d85f 44{
864e8bd0 45public:
bf57d1ad 46 wxRegionRefData();
1e6feb95
VZ
47 wxRegionRefData(const wxRegionRefData& refData);
48 virtual ~wxRegionRefData();
5fc7ede9 49
c801d85f 50 GdkRegion *m_region;
3d0c4d2e 51#if OLDCODE
8429bec1 52 wxList m_rects;
3d0c4d2e 53#endif
c801d85f
KB
54};
55
1e6feb95
VZ
56// ----------------------------------------------------------------------------
57// macros
58// ----------------------------------------------------------------------------
59
60#define M_REGIONDATA ((wxRegionRefData *)m_refData)
61#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
62
63IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject);
64IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject);
65
66// ============================================================================
67// implementation
68// ============================================================================
69
70// ----------------------------------------------------------------------------
71// wxRegionRefData
72// ----------------------------------------------------------------------------
73
bf57d1ad 74wxRegionRefData::wxRegionRefData()
c801d85f 75{
bbe0af5b 76 m_region = (GdkRegion *) NULL;
ff7b1510 77}
c801d85f 78
1e6feb95
VZ
79wxRegionRefData::wxRegionRefData(const wxRegionRefData& refData)
80{
81#ifdef __WXGTK20__
82 m_region = gdk_region_copy(refData.m_region);
83#else
84 m_region = gdk_region_new();
85 GdkRegion *regCopy = gdk_regions_union(m_region, refData.m_region);
86 gdk_region_destroy(m_region);
87 m_region = regCopy;
88#endif
89
29149a64 90#if OLDCODE
1e6feb95
VZ
91 wxNode *node = refData.m_rects.First();
92 while (node)
93 {
94 wxRect *r = (wxRect*)node->Data();
95 m_rects.Append( (wxObject*) new wxRect(*r) );
96 node = node->Next();
97 }
29149a64 98#endif
1e6feb95
VZ
99}
100
bf57d1ad 101wxRegionRefData::~wxRegionRefData()
c801d85f 102{
bbe0af5b 103 if (m_region) gdk_region_destroy( m_region );
5fc7ede9 104
3d0c4d2e 105#if OLDCODE
bbe0af5b
RR
106 wxNode *node = m_rects.First();
107 while (node)
108 {
109 wxRect *r = (wxRect*)node->Data();
110 delete r;
111 node = node->Next();
112 }
3d0c4d2e 113#endif
ff7b1510 114}
c801d85f 115
1e6feb95
VZ
116// ----------------------------------------------------------------------------
117// wxRegion construction
118// ----------------------------------------------------------------------------
c801d85f
KB
119
120#define M_REGIONDATA ((wxRegionRefData *)m_refData)
121
1e6feb95
VZ
122wxRegion::wxRegion()
123{
124}
125
5fc7ede9 126wxRegion::wxRegion( wxCoord x, wxCoord y, wxCoord w, wxCoord h )
c801d85f 127{
bbe0af5b
RR
128 m_refData = new wxRegionRefData();
129 GdkRegion *reg = gdk_region_new();
130 GdkRectangle rect;
131 rect.x = x;
132 rect.y = y;
133 rect.width = w;
134 rect.height = h;
b7c2d6ff
OK
135#ifdef __WXGTK20__
136 gdk_region_union_with_rect( reg, &rect );
137 M_REGIONDATA->m_region = reg;
138#else
bbe0af5b
RR
139 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
140 gdk_region_destroy( reg );
b7c2d6ff 141#endif
3d0c4d2e 142#if OLDCODE
bbe0af5b 143 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,w,h) );
3d0c4d2e 144#endif
ff7b1510 145}
c801d85f
KB
146
147wxRegion::wxRegion( const wxPoint& topLeft, const wxPoint& bottomRight )
148{
bbe0af5b
RR
149 m_refData = new wxRegionRefData();
150 GdkRegion *reg = gdk_region_new();
151 GdkRectangle rect;
152 rect.x = topLeft.x;
153 rect.y = topLeft.y;
154 rect.width = bottomRight.x - rect.x;
155 rect.height = bottomRight.y - rect.y;
b7c2d6ff
OK
156#ifdef __WXGTK20__
157 gdk_region_union_with_rect( reg, &rect );
158 M_REGIONDATA->m_region = reg;
159#else
bbe0af5b
RR
160 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
161 gdk_region_destroy( reg );
b7c2d6ff 162#endif
3d0c4d2e 163#if OLDCODE
bbe0af5b 164 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(topLeft,bottomRight) );
3d0c4d2e 165#endif
ff7b1510 166}
c801d85f
KB
167
168wxRegion::wxRegion( const wxRect& rect )
169{
bbe0af5b
RR
170 m_refData = new wxRegionRefData();
171 GdkRegion *reg = gdk_region_new();
172 GdkRectangle g_rect;
173 g_rect.x = rect.x;
174 g_rect.y = rect.y;
175 g_rect.width = rect.width;
176 g_rect.height = rect.height;
b7c2d6ff
OK
177#ifdef __WXGTK20__
178 gdk_region_union_with_rect( reg, &g_rect );
179 M_REGIONDATA->m_region = reg;
180#else
bbe0af5b
RR
181 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &g_rect );
182 gdk_region_destroy( reg );
b7c2d6ff 183#endif
3d0c4d2e 184#if OLDCODE
e1208c31 185 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(rect.x,rect.y,rect.width,rect.height) );
3d0c4d2e 186#endif
ff7b1510 187}
c801d85f 188
5549e9f7
VZ
189wxRegion::wxRegion( size_t n, const wxPoint *points, int fillStyle )
190{
191 GdkPoint *gdkpoints = new GdkPoint[n];
192 for ( size_t i = 0 ; i < n ; i++ )
193 {
194 gdkpoints[i].x = points[i].x;
195 gdkpoints[i].y = points[i].y;
196 }
197
198 m_refData = new wxRegionRefData();
199
200 GdkRegion* reg = gdk_region_polygon
201 (
202 gdkpoints,
203 n,
204 fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
205 : GDK_EVEN_ODD_RULE
206 );
207
208 M_REGIONDATA->m_region = reg;
209
210 delete [] gdkpoints;
211}
212
1e6feb95 213wxRegion::~wxRegion()
c801d85f 214{
ff7b1510 215}
c801d85f 216
1e6feb95 217bool wxRegion::operator==( const wxRegion& region )
c801d85f 218{
1e6feb95
VZ
219 // VZ: compare the regions themselves, not the pointers to ref data!
220 return gdk_region_equal(M_REGIONDATA->m_region,
221 M_REGIONDATA_OF(region)->m_region);
ff7b1510 222}
c801d85f 223
1e6feb95 224bool wxRegion::operator != ( const wxRegion& region )
76ed8f8d 225{
1e6feb95 226 return !(*this == region);
76ed8f8d
RR
227}
228
1e6feb95 229void wxRegion::Unshare()
76ed8f8d 230{
1e6feb95
VZ
231 if ( !m_refData )
232 {
233 m_refData = new wxRegionRefData;
234 M_REGIONDATA->m_region = gdk_region_new();
235 }
236 else if ( m_refData->GetRefCount() > 1 )
237 {
238 wxRegionRefData *refData = new wxRegionRefData(*M_REGIONDATA);
239 UnRef();
240 m_refData = refData;
241 }
242 //else: we're not shared
76ed8f8d
RR
243}
244
1e6feb95
VZ
245// ----------------------------------------------------------------------------
246// wxRegion operations
247// ----------------------------------------------------------------------------
248
bf57d1ad 249void wxRegion::Clear()
c801d85f 250{
bbe0af5b 251 UnRef();
ff7b1510 252}
c801d85f 253
5fc7ede9 254bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 255{
bbe0af5b
RR
256 GdkRectangle rect;
257 rect.x = x;
258 rect.y = y;
259 rect.width = width;
260 rect.height = height;
e1208c31
RR
261 if (!m_refData)
262 {
263 m_refData = new wxRegionRefData();
264 GdkRegion *reg = gdk_region_new();
b7c2d6ff
OK
265#ifdef __WXGTK20__
266 gdk_region_union_with_rect( reg, &rect );
267 M_REGIONDATA->m_region = reg;
268#else
e1208c31
RR
269 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
270 gdk_region_destroy( reg );
b7c2d6ff 271#endif
e1208c31
RR
272 }
273 else
274 {
1e6feb95
VZ
275 Unshare();
276
b7c2d6ff
OK
277#ifdef __WXGTK20__
278 gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
279#else
e1208c31
RR
280 GdkRegion *reg = gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
281 gdk_region_destroy( M_REGIONDATA->m_region );
282 M_REGIONDATA->m_region = reg;
b7c2d6ff 283#endif
e1208c31 284 }
1e6feb95 285
3d0c4d2e 286#if OLDCODE
bbe0af5b 287 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,width,height) );
3d0c4d2e 288#endif
e1208c31 289
bbe0af5b 290 return TRUE;
ff7b1510 291}
c801d85f
KB
292
293bool wxRegion::Union( const wxRect& rect )
294{
e1208c31 295 return Union( rect.x, rect.y, rect.width, rect.height );
ff7b1510 296}
c801d85f
KB
297
298bool wxRegion::Union( const wxRegion& region )
299{
e1208c31
RR
300 if (region.IsNull())
301 return FALSE;
302
1e6feb95 303 Unshare();
e1208c31 304
b7c2d6ff
OK
305#ifdef __WXGTK20__
306 gdk_region_union( M_REGIONDATA->m_region, region.GetRegion() );
307#else
bbe0af5b
RR
308 GdkRegion *reg = gdk_regions_union( M_REGIONDATA->m_region, region.GetRegion() );
309 gdk_region_destroy( M_REGIONDATA->m_region );
310 M_REGIONDATA->m_region = reg;
b7c2d6ff 311#endif
5fc7ede9 312
3d0c4d2e 313#if OLDCODE
bbe0af5b
RR
314 wxNode *node = region.GetRectList()->First();
315 while (node)
316 {
317 wxRect *r = (wxRect*)node->Data();
318 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
319 node = node->Next();
320 }
3d0c4d2e 321#endif
5fc7ede9 322
bbe0af5b 323 return TRUE;
ff7b1510 324}
c801d85f 325
5fc7ede9 326bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 327{
bbe0af5b 328 wxRegion reg( x, y, width, height );
1e6feb95
VZ
329
330 return Intersect( reg );
ff7b1510 331}
c801d85f
KB
332
333bool wxRegion::Intersect( const wxRect& rect )
334{
bbe0af5b 335 wxRegion reg( rect );
1e6feb95 336 return Intersect( reg );
ff7b1510 337}
c801d85f 338
1e6feb95
VZ
339// this helper function just computes the region intersection without updating
340// the list of rectangles each region maintaints: this allows us to call it
341// from Intersect() itself without going into infinite recursion as we would
342// if we called Intersect() itself recursively
343bool wxRegion::IntersectRegionOnly(const wxRegion& region)
c801d85f 344{
1e6feb95 345 Unshare();
e1208c31 346
b7c2d6ff
OK
347#ifdef __WXGTK20__
348 gdk_region_intersect( M_REGIONDATA->m_region, region.GetRegion() );
349#else
bbe0af5b
RR
350 GdkRegion *reg = gdk_regions_intersect( M_REGIONDATA->m_region, region.GetRegion() );
351 gdk_region_destroy( M_REGIONDATA->m_region );
352 M_REGIONDATA->m_region = reg;
b7c2d6ff 353#endif
1e6feb95 354
bbe0af5b 355 return TRUE;
ff7b1510 356}
c801d85f 357
1e6feb95 358bool wxRegion::Intersect( const wxRegion& region )
c801d85f 359{
1e6feb95
VZ
360 if (region.IsNull())
361 return FALSE;
362
e1208c31
RR
363 if (!m_refData)
364 {
365 m_refData = new wxRegionRefData();
366 M_REGIONDATA->m_region = gdk_region_new();
1e6feb95
VZ
367 return TRUE;
368 }
369
370 if ( !IntersectRegionOnly(region) )
371 {
372 GetRectList()->Clear();
373
374 return FALSE;
375 }
376
377 // we need to update the rect list as well
2a365b7d 378#if OLDCODE
1e6feb95
VZ
379 wxList& list = *GetRectList();
380 wxNode *node = list.First();
381 while (node)
382 {
383 wxRect *r = (wxRect*)node->Data();
384
385 wxRegion regCopy = region;
386 if ( regCopy.IntersectRegionOnly(*r) )
387 {
388 // replace the node with the intersection
389 *r = regCopy.GetBox();
390 }
391 else
392 {
393 // TODO remove the rect from the list
394 r->width = 0;
395 r->height = 0;
396 }
397
398 node = node->Next();
e1208c31 399 }
2a365b7d 400#endif
bbe0af5b 401 return TRUE;
ff7b1510 402}
c801d85f 403
1e6feb95 404bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 405{
1e6feb95
VZ
406 wxRegion reg( x, y, width, height );
407 return Subtract( reg );
408}
e1208c31 409
1e6feb95
VZ
410bool wxRegion::Subtract( const wxRect& rect )
411{
bbe0af5b 412 wxRegion reg( rect );
1e6feb95 413 return Subtract( reg );
ff7b1510 414}
c801d85f
KB
415
416bool wxRegion::Subtract( const wxRegion& region )
417{
e1208c31
RR
418 if (region.IsNull())
419 return FALSE;
420
421 if (!m_refData)
422 {
423 m_refData = new wxRegionRefData();
424 M_REGIONDATA->m_region = gdk_region_new();
425 }
426
1e6feb95
VZ
427 Unshare();
428
b7c2d6ff
OK
429#ifdef __WXGTK20__
430 gdk_region_subtract( M_REGIONDATA->m_region, region.GetRegion() );
431#else
bbe0af5b
RR
432 GdkRegion *reg = gdk_regions_subtract( M_REGIONDATA->m_region, region.GetRegion() );
433 gdk_region_destroy( M_REGIONDATA->m_region );
434 M_REGIONDATA->m_region = reg;
b7c2d6ff 435#endif
1e6feb95 436
bbe0af5b 437 return TRUE;
ff7b1510 438}
c801d85f 439
5fc7ede9 440bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 441{
bbe0af5b 442 wxRegion reg( x, y, width, height );
1e6feb95 443 return Xor( reg );
ff7b1510 444}
c801d85f
KB
445
446bool wxRegion::Xor( const wxRect& rect )
447{
bbe0af5b 448 wxRegion reg( rect );
1e6feb95 449 return Xor( reg );
ff7b1510 450}
c801d85f
KB
451
452bool wxRegion::Xor( const wxRegion& region )
453{
e1208c31 454 if (region.IsNull())
05a11043 455 return FALSE;
e1208c31
RR
456
457 if (!m_refData)
458 {
459 m_refData = new wxRegionRefData();
460 M_REGIONDATA->m_region = gdk_region_new();
461 }
1e6feb95
VZ
462 else
463 {
464 Unshare();
465 }
e1208c31 466
b7c2d6ff
OK
467#ifdef __WXGTK20__
468 gdk_region_xor( M_REGIONDATA->m_region, region.GetRegion() );
469#else
bbe0af5b
RR
470 GdkRegion *reg = gdk_regions_xor( M_REGIONDATA->m_region, region.GetRegion() );
471 gdk_region_destroy( M_REGIONDATA->m_region );
472 M_REGIONDATA->m_region = reg;
b7c2d6ff 473#endif
5fc7ede9 474
3d0c4d2e 475#if OLDCODE
bbe0af5b
RR
476 wxNode *node = region.GetRectList()->First();
477 while (node)
478 {
479 wxRect *r = (wxRect*)node->Data();
480 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
481 node = node->Next();
482 }
3d0c4d2e 483#endif
5fc7ede9 484
bbe0af5b 485 return TRUE;
ff7b1510 486}
c801d85f 487
1e6feb95
VZ
488// ----------------------------------------------------------------------------
489// wxRegion tests
490// ----------------------------------------------------------------------------
491
e1208c31 492void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
c801d85f 493{
1e6feb95
VZ
494 if ( m_refData )
495 {
496 GdkRectangle rect;
497 gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
498 x = rect.x;
499 y = rect.y;
500 w = rect.width;
501 h = rect.height;
502 }
503 else
504 {
505 x = 0;
506 y = 0;
507 w = -1;
508 h = -1;
509 }
ff7b1510 510}
c801d85f 511
bf57d1ad 512wxRect wxRegion::GetBox() const
c801d85f 513{
1e6feb95 514 wxCoord x, y, w, h;
bbe0af5b
RR
515 GetBox( x, y, w, h );
516 return wxRect( x, y, w, h );
ff7b1510 517}
c801d85f 518
35917d22
RR
519bool wxRegion::Offset( wxCoord x, wxCoord y )
520{
521 if (!m_refData)
522 return FALSE;
523
524 gdk_region_offset( M_REGIONDATA->m_region, x, y );
525
526 return TRUE;
527}
528
bf57d1ad 529bool wxRegion::Empty() const
c801d85f 530{
e1208c31
RR
531 if (!m_refData)
532 return TRUE;
533
bbe0af5b 534 return gdk_region_empty( M_REGIONDATA->m_region );
ff7b1510 535}
c801d85f 536
5fc7ede9 537wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
c801d85f 538{
e1208c31
RR
539 if (!m_refData)
540 return wxOutRegion;
541
bbe0af5b
RR
542 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
543 return wxInRegion;
544 else
545 return wxOutRegion;
ff7b1510 546}
c801d85f 547
5fc7ede9 548wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
c801d85f 549{
e1208c31
RR
550 if (!m_refData)
551 return wxOutRegion;
552
bbe0af5b
RR
553 GdkRectangle rect;
554 rect.x = x;
555 rect.y = y;
556 rect.width = w;
557 rect.height = h;
558 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
559 switch (res)
560 {
561 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
562 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
563 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
564 }
565 return wxOutRegion;
ff7b1510 566}
c801d85f 567
8429bec1
RR
568wxRegionContain wxRegion::Contains(const wxPoint& pt) const
569{
bbe0af5b 570 return Contains( pt.x, pt.y );
8429bec1
RR
571}
572
573wxRegionContain wxRegion::Contains(const wxRect& rect) const
574{
bbe0af5b 575 return Contains( rect.x, rect.y, rect.width, rect.height );
8429bec1
RR
576}
577
bf57d1ad 578GdkRegion *wxRegion::GetRegion() const
c801d85f 579{
e1208c31
RR
580 if (!m_refData)
581 return (GdkRegion*) NULL;
582
bbe0af5b 583 return M_REGIONDATA->m_region;
ff7b1510 584}
c801d85f 585
8429bec1
RR
586wxList *wxRegion::GetRectList() const
587{
3d0c4d2e 588#if OLDCODE
e1208c31
RR
589 if (!m_refData)
590 return (wxList*) NULL;
591
bbe0af5b 592 return &(M_REGIONDATA->m_rects);
3d0c4d2e
RR
593#else
594 return (wxList*) NULL;
595#endif
8429bec1
RR
596}
597
1e6feb95 598// ----------------------------------------------------------------------------
3d0c4d2e 599// wxRegionIterator
1e6feb95 600// ----------------------------------------------------------------------------
8429bec1 601
3d0c4d2e
RR
602#if OLDCODE
603
bf57d1ad 604wxRegionIterator::wxRegionIterator()
8429bec1 605{
6f2a55e3 606 Reset();
8429bec1
RR
607}
608
609wxRegionIterator::wxRegionIterator( const wxRegion& region )
610{
6f2a55e3 611 Reset(region);
8429bec1
RR
612}
613
614void wxRegionIterator::Reset( const wxRegion& region )
615{
bbe0af5b 616 m_region = region;
6f2a55e3 617 Reset();
8429bec1
RR
618}
619
5fc7ede9
VZ
620wxRegionIterator::operator bool () const
621{
3d0c4d2e 622 return m_region.GetRectList() && m_current < (size_t)m_region.GetRectList()->Number();
8429bec1
RR
623}
624
5fc7ede9
VZ
625bool wxRegionIterator::HaveRects() const
626{
3d0c4d2e 627 return m_region.GetRectList() && m_current < (size_t)m_region.GetRectList()->Number();
8429bec1
RR
628}
629
bf57d1ad 630void wxRegionIterator::operator ++ ()
8429bec1 631{
3d0c4d2e 632 if (HaveRects()) ++m_current;
8429bec1
RR
633}
634
635void wxRegionIterator::operator ++ (int)
636{
3d0c4d2e 637 if (HaveRects()) ++m_current;
8429bec1
RR
638}
639
bf57d1ad 640wxCoord wxRegionIterator::GetX() const
8429bec1 641{
bbe0af5b
RR
642 wxNode *node = m_region.GetRectList()->Nth( m_current );
643 if (!node) return 0;
644 wxRect *r = (wxRect*)node->Data();
645 return r->x;
8429bec1
RR
646}
647
bf57d1ad 648wxCoord wxRegionIterator::GetY() const
8429bec1 649{
bbe0af5b
RR
650 wxNode *node = m_region.GetRectList()->Nth( m_current );
651 if (!node) return 0;
652 wxRect *r = (wxRect*)node->Data();
653 return r->y;
8429bec1
RR
654}
655
bf57d1ad 656wxCoord wxRegionIterator::GetW() const
8429bec1 657{
bbe0af5b
RR
658 wxNode *node = m_region.GetRectList()->Nth( m_current );
659 if (!node) return 0;
660 wxRect *r = (wxRect*)node->Data();
661 return r->width;
8429bec1
RR
662}
663
bf57d1ad 664wxCoord wxRegionIterator::GetH() const
8429bec1 665{
bbe0af5b
RR
666 wxNode *node = m_region.GetRectList()->Nth( m_current );
667 if (!node) return 0;
668 wxRect *r = (wxRect*)node->Data();
669 return r->height;
8429bec1
RR
670}
671
3d0c4d2e
RR
672#else
673
674// the following structures must match the private structures
675// in X11 region code ( xc/lib/X11/region.h )
676
677// this makes the Region type transparent
678// and we have access to the region rectangles
679
680struct _XBox {
681 short x1, x2, y1, y2;
682};
1e6feb95 683
3d0c4d2e
RR
684struct _XRegion {
685 long size , numRects;
686 _XBox *rects, extents;
687};
688
689class wxRIRefData: public wxObjectRefData
690{
691public:
692
693 wxRIRefData() : m_rects(0), m_numRects(0){}
694 ~wxRIRefData();
695
696 wxRect *m_rects;
697 size_t m_numRects;
698
699 void CreateRects( const wxRegion& r );
700};
701
702wxRIRefData::~wxRIRefData()
703{
704 delete m_rects;
705}
706
707#include <gdk/gdkprivate.h>
708
709void wxRIRefData::CreateRects( const wxRegion& region )
710{
711 if( m_rects )
712 delete m_rects;
713 m_rects = 0;
714 m_numRects= 0;
715 GdkRegion *gdkregion= region.GetRegion();
716 if( gdkregion ){
717 Region r= ((GdkRegionPrivate *)gdkregion)->xregion;
718 if( r ){
719 m_numRects= r->numRects;
720 if( m_numRects )
721 {
722 m_rects= new wxRect[m_numRects];
723 for( size_t i=0; i<m_numRects; ++i )
724 {
725 _XBox &xr= r->rects[i];
726 wxRect&wr= m_rects[i];
727 wr.x = xr.x1;
728 wr.y = xr.y1;
729 wr.width = xr.x2-xr.x1;
730 wr.height= xr.y2-xr.y1;
731 }
732 }
733 }
734 }
735}
736
3d0c4d2e
RR
737wxRegionIterator::wxRegionIterator()
738{
739 m_refData = new wxRIRefData();
740 Reset();
741}
742
743wxRegionIterator::wxRegionIterator( const wxRegion& region )
744{
745 m_refData = new wxRIRefData();
746 Reset(region);
747}
748
749void wxRegionIterator::Reset( const wxRegion& region )
750{
751 m_region = region;
752 ((wxRIRefData*)m_refData)->CreateRects(region);
753 Reset();
754}
755
756bool wxRegionIterator::HaveRects() const
757{
758 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
759}
760
761wxRegionIterator::operator bool () const
762{
763 return HaveRects();
764}
765
766void wxRegionIterator::operator ++ ()
767{
768 if (HaveRects()) ++m_current;
769}
770
771void wxRegionIterator::operator ++ (int)
772{
773 if (HaveRects()) ++m_current;
774}
775
776wxCoord wxRegionIterator::GetX() const
777{
778 if( !HaveRects() ) return 0;
779 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
780}
781
782wxCoord wxRegionIterator::GetY() const
783{
784 if( !HaveRects() ) return 0;
785 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
786}
787
788wxCoord wxRegionIterator::GetW() const
789{
790 if( !HaveRects() ) return -1;
791 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
792}
793
794wxCoord wxRegionIterator::GetH() const
795{
796 if( !HaveRects() ) return -1;
797 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
798}
799
1e6feb95
VZ
800wxRect wxRegionIterator::GetRect() const
801{
802 wxRect r;
3379ed37
VZ
803 if( HaveRects() )
804 r = ((wxRIRefData*)m_refData)->m_rects[m_current];
1e6feb95
VZ
805
806 return r;
807}
808
3d0c4d2e 809#endif
8429bec1 810