1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/region.cpp
4 // Author: Robert Roebling
5 // Modified: VZ at 05.10.00: use AllocExclusive(), comparison fixed
7 // Copyright: (c) 1998 Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
16 #pragma implementation "region.h"
19 // ----------------------------------------------------------------------------
21 // ----------------------------------------------------------------------------
23 #include "wx/region.h"
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
39 // ----------------------------------------------------------------------------
40 // wxRegionRefData: private class containing the information about the region
41 // ----------------------------------------------------------------------------
43 class wxRegionRefData
: public wxObjectRefData
47 wxRegionRefData(const wxRegionRefData
& refData
);
48 virtual ~wxRegionRefData();
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
61 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
63 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
);
64 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
);
66 // ============================================================================
68 // ============================================================================
70 // ----------------------------------------------------------------------------
72 // ----------------------------------------------------------------------------
74 wxRegionRefData::wxRegionRefData()
76 m_region
= (GdkRegion
*) NULL
;
79 wxRegionRefData::wxRegionRefData(const wxRegionRefData
& refData
)
82 m_region
= gdk_region_copy(refData
.m_region
);
84 m_region
= gdk_region_new();
85 GdkRegion
*regCopy
= gdk_regions_union(m_region
, refData
.m_region
);
86 gdk_region_destroy(m_region
);
91 wxNode
*node
= refData
.m_rects
.First();
94 wxRect
*r
= (wxRect
*)node
->Data();
95 m_rects
.Append( (wxObject
*) new wxRect(*r
) );
101 wxRegionRefData::~wxRegionRefData()
104 gdk_region_destroy( m_region
);
107 wxNode
*node
= m_rects
.First();
110 wxRect
*r
= (wxRect
*)node
->Data();
117 // ----------------------------------------------------------------------------
118 // wxRegion construction
119 // ----------------------------------------------------------------------------
121 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
123 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
125 m_refData
= new wxRegionRefData();
126 GdkRegion
*reg
= gdk_region_new();
133 gdk_region_union_with_rect( reg
, &rect
);
134 M_REGIONDATA
->m_region
= reg
;
136 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( reg
, &rect
);
137 gdk_region_destroy( reg
);
141 M_REGIONDATA
->m_rects
.Append( (wxObject
*) new wxRect(x
, y
, w
, h
) );
145 wxRegion::wxRegion( size_t n
, const wxPoint
*points
, int fillStyle
)
147 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
148 for ( size_t i
= 0 ; i
< n
; i
++ )
150 gdkpoints
[i
].x
= points
[i
].x
;
151 gdkpoints
[i
].y
= points
[i
].y
;
154 m_refData
= new wxRegionRefData();
156 GdkRegion
* reg
= gdk_region_polygon
160 fillStyle
== wxWINDING_RULE
? GDK_WINDING_RULE
164 M_REGIONDATA
->m_region
= reg
;
169 wxRegion::~wxRegion()
171 // m_refData unrefed in ~wxObject
174 wxObjectRefData
*wxRegion::CreateRefData() const
176 return new wxRegionRefData
;
179 wxObjectRefData
*wxRegion::CloneRefData(const wxObjectRefData
*data
) const
181 return new wxRegionRefData(*(wxRegionRefData
*)data
);
183 // ----------------------------------------------------------------------------
184 // wxRegion comparison
185 // ----------------------------------------------------------------------------
187 bool wxRegion::operator==( const wxRegion
& region
)
189 // compare the regions themselves, not the pointers to ref data!
190 return gdk_region_equal(M_REGIONDATA
->m_region
,
191 M_REGIONDATA_OF(region
)->m_region
);
194 bool wxRegion::operator != ( const wxRegion
& region
)
196 return !(*this == region
);
199 // ----------------------------------------------------------------------------
200 // wxRegion operations
201 // ----------------------------------------------------------------------------
203 void wxRegion::Clear()
208 bool wxRegion::Union( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
214 rect
.height
= height
;
218 m_refData
= new wxRegionRefData();
219 GdkRegion
*reg
= gdk_region_new();
221 gdk_region_union_with_rect( reg
, &rect
);
222 M_REGIONDATA
->m_region
= reg
;
224 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( reg
, &rect
);
225 gdk_region_destroy( reg
);
233 gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
235 GdkRegion
*reg
= gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
236 gdk_region_destroy( M_REGIONDATA
->m_region
);
237 M_REGIONDATA
->m_region
= reg
;
242 M_REGIONDATA
->m_rects
.Append( (wxObject
*) new wxRect(x
,y
,width
,height
) );
248 bool wxRegion::Union( const wxRect
& rect
)
250 return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
253 bool wxRegion::Union( const wxRegion
& region
)
261 gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
263 GdkRegion
*reg
= gdk_regions_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
264 gdk_region_destroy( M_REGIONDATA
->m_region
);
265 M_REGIONDATA
->m_region
= reg
;
269 wxNode
*node
= region
.GetRectList()->First();
272 wxRect
*r
= (wxRect
*)node
->Data();
273 M_REGIONDATA
->m_rects
.Append( (wxObject
*) new wxRect(r
->x
,r
->y
,r
->width
,r
->height
) );
281 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
283 wxRegion
reg( x
, y
, width
, height
);
285 return Intersect( reg
);
288 bool wxRegion::Intersect( const wxRect
& rect
)
290 wxRegion
reg( rect
);
292 return Intersect( reg
);
295 // this helper function just computes the region intersection without updating
296 // the list of rectangles each region maintaints: this allows us to call it
297 // from Intersect() itself without going into infinite recursion as we would
298 // if we called Intersect() itself recursively
299 bool wxRegion::IntersectRegionOnly(const wxRegion
& region
)
304 gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
306 GdkRegion
*reg
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
307 gdk_region_destroy( M_REGIONDATA
->m_region
);
308 M_REGIONDATA
->m_region
= reg
;
314 bool wxRegion::Intersect( const wxRegion
& region
)
321 m_refData
= new wxRegionRefData();
322 M_REGIONDATA
->m_region
= gdk_region_new();
326 if ( !IntersectRegionOnly(region
) )
328 GetRectList()->Clear();
333 // we need to update the rect list as well
335 wxList
& list
= *GetRectList();
336 wxNode
*node
= list
.First();
339 wxRect
*r
= (wxRect
*)node
->Data();
341 wxRegion regCopy
= region
;
342 if ( regCopy
.IntersectRegionOnly(*r
) )
344 // replace the node with the intersection
345 *r
= regCopy
.GetBox();
349 // TODO remove the rect from the list
361 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
363 wxRegion
reg( x
, y
, width
, height
);
364 return Subtract( reg
);
367 bool wxRegion::Subtract( const wxRect
& rect
)
369 wxRegion
reg( rect
);
370 return Subtract( reg
);
373 bool wxRegion::Subtract( const wxRegion
& region
)
380 m_refData
= new wxRegionRefData();
381 M_REGIONDATA
->m_region
= gdk_region_new();
387 gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
389 GdkRegion
*reg
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
390 gdk_region_destroy( M_REGIONDATA
->m_region
);
391 M_REGIONDATA
->m_region
= reg
;
397 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
399 wxRegion
reg( x
, y
, width
, height
);
403 bool wxRegion::Xor( const wxRect
& rect
)
405 wxRegion
reg( rect
);
409 bool wxRegion::Xor( const wxRegion
& region
)
416 m_refData
= new wxRegionRefData();
417 M_REGIONDATA
->m_region
= gdk_region_new();
425 gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
427 GdkRegion
*reg
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
428 gdk_region_destroy( M_REGIONDATA
->m_region
);
429 M_REGIONDATA
->m_region
= reg
;
433 wxNode
*node
= region
.GetRectList()->First();
436 wxRect
*r
= (wxRect
*)node
->Data();
437 M_REGIONDATA
->m_rects
.Append( (wxObject
*) new wxRect(r
->x
,r
->y
,r
->width
,r
->height
) );
445 // ----------------------------------------------------------------------------
447 // ----------------------------------------------------------------------------
449 void wxRegion::GetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
454 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
469 wxRect
wxRegion::GetBox() const
472 GetBox( x
, y
, w
, h
);
473 return wxRect( x
, y
, w
, h
);
476 bool wxRegion::Offset( wxCoord x
, wxCoord y
)
483 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
488 bool wxRegion::Empty() const
493 return gdk_region_empty( M_REGIONDATA
->m_region
);
496 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
) const
501 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
507 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
517 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
520 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
521 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
522 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
527 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
529 return Contains( pt
.x
, pt
.y
);
532 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
534 return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
537 GdkRegion
*wxRegion::GetRegion() const
540 return (GdkRegion
*) NULL
;
542 return M_REGIONDATA
->m_region
;
545 wxList
*wxRegion::GetRectList() const
549 return (wxList
*) NULL
;
551 return &(M_REGIONDATA
->m_rects
);
553 return (wxList
*) NULL
;
557 // ----------------------------------------------------------------------------
559 // ----------------------------------------------------------------------------
563 wxRegionIterator::wxRegionIterator()
568 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
573 void wxRegionIterator::Reset( const wxRegion
& region
)
579 wxRegionIterator::operator bool () const
581 return m_region
.GetRectList() && m_current
< (size_t)m_region
.GetRectList()->Number();
584 bool wxRegionIterator::HaveRects() const
586 return m_region
.GetRectList() && m_current
< (size_t)m_region
.GetRectList()->Number();
589 void wxRegionIterator::operator ++ ()
591 if (HaveRects()) ++m_current
;
594 void wxRegionIterator::operator ++ (int)
596 if (HaveRects()) ++m_current
;
599 wxCoord
wxRegionIterator::GetX() const
601 wxNode
*node
= m_region
.GetRectList()->Nth( m_current
);
603 wxRect
*r
= (wxRect
*)node
->Data();
607 wxCoord
wxRegionIterator::GetY() const
609 wxNode
*node
= m_region
.GetRectList()->Nth( m_current
);
611 wxRect
*r
= (wxRect
*)node
->Data();
615 wxCoord
wxRegionIterator::GetW() const
617 wxNode
*node
= m_region
.GetRectList()->Nth( m_current
);
619 wxRect
*r
= (wxRect
*)node
->Data();
623 wxCoord
wxRegionIterator::GetH() const
625 wxNode
*node
= m_region
.GetRectList()->Nth( m_current
);
627 wxRect
*r
= (wxRect
*)node
->Data();
633 // the following structures must match the private structures
634 // in X11 region code ( xc/lib/X11/region.h )
636 // this makes the Region type transparent
637 // and we have access to the region rectangles
640 short x1
, x2
, y1
, y2
;
644 long size
, numRects
;
645 _XBox
*rects
, extents
;
648 class wxRIRefData
: public wxObjectRefData
652 wxRIRefData() : m_rects(0), m_numRects(0){}
658 void CreateRects( const wxRegion
& r
);
661 wxRIRefData::~wxRIRefData()
666 #include <gdk/gdkprivate.h>
668 void wxRIRefData::CreateRects( const wxRegion
& region
)
674 GdkRegion
*gdkregion
= region
.GetRegion();
676 Region r
= ((GdkRegionPrivate
*)gdkregion
)->xregion
;
678 m_numRects
= r
->numRects
;
681 m_rects
= new wxRect
[m_numRects
];
682 for( size_t i
=0; i
<m_numRects
; ++i
)
684 _XBox
&xr
= r
->rects
[i
];
685 wxRect
&wr
= m_rects
[i
];
688 wr
.width
= xr
.x2
-xr
.x1
;
689 wr
.height
= xr
.y2
-xr
.y1
;
696 wxRegionIterator::wxRegionIterator()
698 m_refData
= new wxRIRefData();
702 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
704 m_refData
= new wxRIRefData();
708 void wxRegionIterator::Reset( const wxRegion
& region
)
711 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
715 bool wxRegionIterator::HaveRects() const
717 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
720 wxRegionIterator::operator bool () const
725 void wxRegionIterator::operator ++ ()
727 if (HaveRects()) ++m_current
;
730 void wxRegionIterator::operator ++ (int)
732 if (HaveRects()) ++m_current
;
735 wxCoord
wxRegionIterator::GetX() const
737 if( !HaveRects() ) return 0;
738 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
741 wxCoord
wxRegionIterator::GetY() const
743 if( !HaveRects() ) return 0;
744 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
747 wxCoord
wxRegionIterator::GetW() const
749 if( !HaveRects() ) return -1;
750 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
753 wxCoord
wxRegionIterator::GetH() const
755 if( !HaveRects() ) return -1;
756 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;
759 wxRect
wxRegionIterator::GetRect() const
763 r
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];
768 #endif // OLDCODE/!OLDCODE