]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/region.cpp
Use the black pen for the border on Windows now too.
[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
bf57d1ad 519bool wxRegion::Empty() const
c801d85f 520{
e1208c31
RR
521 if (!m_refData)
522 return TRUE;
523
bbe0af5b 524 return gdk_region_empty( M_REGIONDATA->m_region );
ff7b1510 525}
c801d85f 526
5fc7ede9 527wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
c801d85f 528{
e1208c31
RR
529 if (!m_refData)
530 return wxOutRegion;
531
bbe0af5b
RR
532 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
533 return wxInRegion;
534 else
535 return wxOutRegion;
ff7b1510 536}
c801d85f 537
5fc7ede9 538wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
c801d85f 539{
e1208c31
RR
540 if (!m_refData)
541 return wxOutRegion;
542
bbe0af5b
RR
543 GdkRectangle rect;
544 rect.x = x;
545 rect.y = y;
546 rect.width = w;
547 rect.height = h;
548 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
549 switch (res)
550 {
551 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
552 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
553 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
554 }
555 return wxOutRegion;
ff7b1510 556}
c801d85f 557
8429bec1
RR
558wxRegionContain wxRegion::Contains(const wxPoint& pt) const
559{
bbe0af5b 560 return Contains( pt.x, pt.y );
8429bec1
RR
561}
562
563wxRegionContain wxRegion::Contains(const wxRect& rect) const
564{
bbe0af5b 565 return Contains( rect.x, rect.y, rect.width, rect.height );
8429bec1
RR
566}
567
bf57d1ad 568GdkRegion *wxRegion::GetRegion() const
c801d85f 569{
e1208c31
RR
570 if (!m_refData)
571 return (GdkRegion*) NULL;
572
bbe0af5b 573 return M_REGIONDATA->m_region;
ff7b1510 574}
c801d85f 575
8429bec1
RR
576wxList *wxRegion::GetRectList() const
577{
3d0c4d2e 578#if OLDCODE
e1208c31
RR
579 if (!m_refData)
580 return (wxList*) NULL;
581
bbe0af5b 582 return &(M_REGIONDATA->m_rects);
3d0c4d2e
RR
583#else
584 return (wxList*) NULL;
585#endif
8429bec1
RR
586}
587
1e6feb95 588// ----------------------------------------------------------------------------
3d0c4d2e 589// wxRegionIterator
1e6feb95 590// ----------------------------------------------------------------------------
8429bec1 591
3d0c4d2e
RR
592#if OLDCODE
593
bf57d1ad 594wxRegionIterator::wxRegionIterator()
8429bec1 595{
6f2a55e3 596 Reset();
8429bec1
RR
597}
598
599wxRegionIterator::wxRegionIterator( const wxRegion& region )
600{
6f2a55e3 601 Reset(region);
8429bec1
RR
602}
603
604void wxRegionIterator::Reset( const wxRegion& region )
605{
bbe0af5b 606 m_region = region;
6f2a55e3 607 Reset();
8429bec1
RR
608}
609
5fc7ede9
VZ
610wxRegionIterator::operator bool () const
611{
3d0c4d2e 612 return m_region.GetRectList() && m_current < (size_t)m_region.GetRectList()->Number();
8429bec1
RR
613}
614
5fc7ede9
VZ
615bool wxRegionIterator::HaveRects() const
616{
3d0c4d2e 617 return m_region.GetRectList() && m_current < (size_t)m_region.GetRectList()->Number();
8429bec1
RR
618}
619
bf57d1ad 620void wxRegionIterator::operator ++ ()
8429bec1 621{
3d0c4d2e 622 if (HaveRects()) ++m_current;
8429bec1
RR
623}
624
625void wxRegionIterator::operator ++ (int)
626{
3d0c4d2e 627 if (HaveRects()) ++m_current;
8429bec1
RR
628}
629
bf57d1ad 630wxCoord wxRegionIterator::GetX() const
8429bec1 631{
bbe0af5b
RR
632 wxNode *node = m_region.GetRectList()->Nth( m_current );
633 if (!node) return 0;
634 wxRect *r = (wxRect*)node->Data();
635 return r->x;
8429bec1
RR
636}
637
bf57d1ad 638wxCoord wxRegionIterator::GetY() const
8429bec1 639{
bbe0af5b
RR
640 wxNode *node = m_region.GetRectList()->Nth( m_current );
641 if (!node) return 0;
642 wxRect *r = (wxRect*)node->Data();
643 return r->y;
8429bec1
RR
644}
645
bf57d1ad 646wxCoord wxRegionIterator::GetW() const
8429bec1 647{
bbe0af5b
RR
648 wxNode *node = m_region.GetRectList()->Nth( m_current );
649 if (!node) return 0;
650 wxRect *r = (wxRect*)node->Data();
651 return r->width;
8429bec1
RR
652}
653
bf57d1ad 654wxCoord wxRegionIterator::GetH() const
8429bec1 655{
bbe0af5b
RR
656 wxNode *node = m_region.GetRectList()->Nth( m_current );
657 if (!node) return 0;
658 wxRect *r = (wxRect*)node->Data();
659 return r->height;
8429bec1
RR
660}
661
3d0c4d2e
RR
662#else
663
664// the following structures must match the private structures
665// in X11 region code ( xc/lib/X11/region.h )
666
667// this makes the Region type transparent
668// and we have access to the region rectangles
669
670struct _XBox {
671 short x1, x2, y1, y2;
672};
1e6feb95 673
3d0c4d2e
RR
674struct _XRegion {
675 long size , numRects;
676 _XBox *rects, extents;
677};
678
679class wxRIRefData: public wxObjectRefData
680{
681public:
682
683 wxRIRefData() : m_rects(0), m_numRects(0){}
684 ~wxRIRefData();
685
686 wxRect *m_rects;
687 size_t m_numRects;
688
689 void CreateRects( const wxRegion& r );
690};
691
692wxRIRefData::~wxRIRefData()
693{
694 delete m_rects;
695}
696
697#include <gdk/gdkprivate.h>
698
699void wxRIRefData::CreateRects( const wxRegion& region )
700{
701 if( m_rects )
702 delete m_rects;
703 m_rects = 0;
704 m_numRects= 0;
705 GdkRegion *gdkregion= region.GetRegion();
706 if( gdkregion ){
707 Region r= ((GdkRegionPrivate *)gdkregion)->xregion;
708 if( r ){
709 m_numRects= r->numRects;
710 if( m_numRects )
711 {
712 m_rects= new wxRect[m_numRects];
713 for( size_t i=0; i<m_numRects; ++i )
714 {
715 _XBox &xr= r->rects[i];
716 wxRect&wr= m_rects[i];
717 wr.x = xr.x1;
718 wr.y = xr.y1;
719 wr.width = xr.x2-xr.x1;
720 wr.height= xr.y2-xr.y1;
721 }
722 }
723 }
724 }
725}
726
3d0c4d2e
RR
727wxRegionIterator::wxRegionIterator()
728{
729 m_refData = new wxRIRefData();
730 Reset();
731}
732
733wxRegionIterator::wxRegionIterator( const wxRegion& region )
734{
735 m_refData = new wxRIRefData();
736 Reset(region);
737}
738
739void wxRegionIterator::Reset( const wxRegion& region )
740{
741 m_region = region;
742 ((wxRIRefData*)m_refData)->CreateRects(region);
743 Reset();
744}
745
746bool wxRegionIterator::HaveRects() const
747{
748 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
749}
750
751wxRegionIterator::operator bool () const
752{
753 return HaveRects();
754}
755
756void wxRegionIterator::operator ++ ()
757{
758 if (HaveRects()) ++m_current;
759}
760
761void wxRegionIterator::operator ++ (int)
762{
763 if (HaveRects()) ++m_current;
764}
765
766wxCoord wxRegionIterator::GetX() const
767{
768 if( !HaveRects() ) return 0;
769 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
770}
771
772wxCoord wxRegionIterator::GetY() const
773{
774 if( !HaveRects() ) return 0;
775 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
776}
777
778wxCoord wxRegionIterator::GetW() const
779{
780 if( !HaveRects() ) return -1;
781 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
782}
783
784wxCoord wxRegionIterator::GetH() const
785{
786 if( !HaveRects() ) return -1;
787 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
788}
789
1e6feb95
VZ
790wxRect wxRegionIterator::GetRect() const
791{
792 wxRect r;
3379ed37
VZ
793 if( HaveRects() )
794 r = ((wxRIRefData*)m_refData)->m_rects[m_current];
1e6feb95
VZ
795
796 return r;
797}
798
3d0c4d2e 799#endif
8429bec1 800