1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/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 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
22 #include "wx/region.h"
28 #include "wx/gtk/private.h"
31 // ----------------------------------------------------------------------------
32 // wxRegionRefData: private class containing the information about the region
33 // ----------------------------------------------------------------------------
35 class wxRegionRefData
: public wxGDIRefData
43 wxRegionRefData(const wxRegionRefData
& refData
)
46 m_region
= gdk_region_copy(refData
.m_region
);
49 virtual ~wxRegionRefData()
52 gdk_region_destroy( m_region
);
58 // ----------------------------------------------------------------------------
60 // ----------------------------------------------------------------------------
62 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
63 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
65 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
)
66 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
)
68 // ----------------------------------------------------------------------------
69 // wxRegion construction
70 // ----------------------------------------------------------------------------
72 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
74 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
82 m_refData
= new wxRegionRefData();
84 M_REGIONDATA
->m_region
= gdk_region_rectangle( &rect
);
87 wxRegion::wxRegion( GdkRegion
*region
)
89 m_refData
= new wxRegionRefData();
90 M_REGIONDATA
->m_region
= gdk_region_copy( region
);
93 wxRegion::wxRegion( size_t n
, const wxPoint
*points
,
94 wxPolygonFillMode fillStyle
)
96 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
97 for ( size_t i
= 0 ; i
< n
; i
++ )
99 gdkpoints
[i
].x
= points
[i
].x
;
100 gdkpoints
[i
].y
= points
[i
].y
;
103 m_refData
= new wxRegionRefData();
105 GdkRegion
* reg
= gdk_region_polygon
109 fillStyle
== wxWINDING_RULE
? GDK_WINDING_RULE
113 M_REGIONDATA
->m_region
= reg
;
118 wxRegion::~wxRegion()
120 // m_refData unrefed in ~wxObject
123 wxGDIRefData
*wxRegion::CreateGDIRefData() const
125 return new wxRegionRefData
;
128 wxGDIRefData
*wxRegion::CloneGDIRefData(const wxGDIRefData
*data
) const
130 return new wxRegionRefData(*(wxRegionRefData
*)data
);
133 // ----------------------------------------------------------------------------
134 // wxRegion comparison
135 // ----------------------------------------------------------------------------
137 bool wxRegion::DoIsEqual(const wxRegion
& region
) const
139 return gdk_region_equal(M_REGIONDATA
->m_region
,
140 M_REGIONDATA_OF(region
)->m_region
);
143 // ----------------------------------------------------------------------------
144 // wxRegion operations
145 // ----------------------------------------------------------------------------
147 void wxRegion::Clear()
152 bool wxRegion::DoUnionWithRect(const wxRect
& r
)
154 // workaround for a strange GTK/X11 bug: taking union with an empty
155 // rectangle results in an empty region which is definitely not what we
162 InitRect(r
.x
, r
.y
, r
.width
, r
.height
);
171 rect
.width
= r
.width
;
172 rect
.height
= r
.height
;
174 gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
180 bool wxRegion::DoUnionWithRegion( const wxRegion
& region
)
182 wxCHECK_MSG( region
.IsOk(), false, wxT("invalid region") );
186 m_refData
= new wxRegionRefData(*M_REGIONDATA_OF(region
));
191 gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
197 bool wxRegion::DoIntersect( const wxRegion
& region
)
199 wxCHECK_MSG( region
.IsOk(), false, wxT("invalid region") );
203 // intersecting with invalid region doesn't make sense
209 gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
214 bool wxRegion::DoSubtract( const wxRegion
& region
)
216 wxCHECK_MSG( region
.IsOk(), false, wxT("invalid region") );
220 // subtracting from an invalid region doesn't make sense
226 gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
231 bool wxRegion::DoXor( const wxRegion
& region
)
233 wxCHECK_MSG( region
.IsOk(), false, wxT("invalid region") );
237 // XOR-ing with an invalid region is the same as XOR-ing with an empty
238 // one, i.e. it is simply a copy.
239 m_refData
= new wxRegionRefData(*M_REGIONDATA_OF(region
));
245 gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
251 bool wxRegion::DoOffset( wxCoord x
, wxCoord y
)
253 wxCHECK_MSG( m_refData
, false, wxS("invalid region") );
257 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
262 // ----------------------------------------------------------------------------
264 // ----------------------------------------------------------------------------
266 bool wxRegion::DoGetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
271 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
290 bool wxRegion::IsEmpty() const
295 return gdk_region_empty( M_REGIONDATA
->m_region
);
298 wxRegionContain
wxRegion::DoContainsPoint( wxCoord x
, wxCoord y
) const
303 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
309 wxRegionContain
wxRegion::DoContainsRect(const wxRect
& r
) const
317 rect
.width
= r
.width
;
318 rect
.height
= r
.height
;
319 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
322 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
323 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
324 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
329 GdkRegion
*wxRegion::GetRegion() const
334 return M_REGIONDATA
->m_region
;
337 // ----------------------------------------------------------------------------
339 // ----------------------------------------------------------------------------
341 wxRegionIterator::wxRegionIterator()
347 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
353 void wxRegionIterator::Init()
359 wxRegionIterator::~wxRegionIterator()
364 void wxRegionIterator::CreateRects( const wxRegion
& region
)
369 GdkRegion
*gdkregion
= region
.GetRegion();
373 GdkRectangle
* gdkrects
;
374 gdk_region_get_rectangles(gdkregion
, &gdkrects
, &m_numRects
);
378 m_rects
= new wxRect
[m_numRects
];
379 for (int i
= 0; i
< m_numRects
; ++i
)
381 GdkRectangle
&gr
= gdkrects
[i
];
382 wxRect
&wr
= m_rects
[i
];
386 wr
.height
= gr
.height
;
392 void wxRegionIterator::Reset( const wxRegion
& region
)
399 bool wxRegionIterator::HaveRects() const
401 return m_current
< m_numRects
;
404 wxRegionIterator
& wxRegionIterator::operator ++ ()
412 wxRegionIterator
wxRegionIterator::operator ++ (int)
414 wxRegionIterator tmp
= *this;
422 wxCoord
wxRegionIterator::GetX() const
424 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
426 return m_rects
[m_current
].x
;
429 wxCoord
wxRegionIterator::GetY() const
431 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
433 return m_rects
[m_current
].y
;
436 wxCoord
wxRegionIterator::GetW() const
438 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
440 return m_rects
[m_current
].width
;
443 wxCoord
wxRegionIterator::GetH() const
445 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
447 return m_rects
[m_current
].height
;
450 wxRect
wxRegionIterator::GetRect() const
454 r
= m_rects
[m_current
];
459 wxRegionIterator
& wxRegionIterator::operator=(const wxRegionIterator
& ri
)
465 m_current
= ri
.m_current
;
466 m_numRects
= ri
.m_numRects
;
469 m_rects
= new wxRect
[m_numRects
];
470 memcpy(m_rects
, ri
.m_rects
, m_numRects
* sizeof m_rects
[0]);