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"
26 #include "wx/region.h"
27 #include "wx/gtk/private.h"
30 // ----------------------------------------------------------------------------
31 // wxRegionRefData: private class containing the information about the region
32 // ----------------------------------------------------------------------------
34 class wxRegionRefData
: public wxObjectRefData
42 wxRegionRefData(const wxRegionRefData
& refData
)
45 m_region
= gdk_region_copy(refData
.m_region
);
51 gdk_region_destroy( m_region
);
57 // ----------------------------------------------------------------------------
59 // ----------------------------------------------------------------------------
61 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
62 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
64 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
)
65 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
)
67 // ----------------------------------------------------------------------------
68 // wxRegion construction
69 // ----------------------------------------------------------------------------
71 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
73 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
81 m_refData
= new wxRegionRefData();
83 M_REGIONDATA
->m_region
= gdk_region_rectangle( &rect
);
86 wxRegion::wxRegion( GdkRegion
*region
)
88 m_refData
= new wxRegionRefData();
89 M_REGIONDATA
->m_region
= gdk_region_copy( region
);
92 wxRegion::wxRegion( size_t n
, const wxPoint
*points
, int fillStyle
)
94 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
95 for ( size_t i
= 0 ; i
< n
; i
++ )
97 gdkpoints
[i
].x
= points
[i
].x
;
98 gdkpoints
[i
].y
= points
[i
].y
;
101 m_refData
= new wxRegionRefData();
103 GdkRegion
* reg
= gdk_region_polygon
107 fillStyle
== wxWINDING_RULE
? GDK_WINDING_RULE
111 M_REGIONDATA
->m_region
= reg
;
116 wxRegion::~wxRegion()
118 // m_refData unrefed in ~wxObject
121 wxObjectRefData
*wxRegion::CreateRefData() const
123 return new wxRegionRefData
;
126 wxObjectRefData
*wxRegion::CloneRefData(const wxObjectRefData
*data
) const
128 return new wxRegionRefData(*(wxRegionRefData
*)data
);
131 // ----------------------------------------------------------------------------
132 // wxRegion comparison
133 // ----------------------------------------------------------------------------
135 bool wxRegion::operator==( const wxRegion
& region
) const
137 if (m_refData
== region
.m_refData
) return TRUE
;
139 if (!m_refData
|| !region
.m_refData
) return FALSE
;
141 // compare the regions themselves, not the pointers to ref data!
142 return gdk_region_equal(M_REGIONDATA
->m_region
,
143 M_REGIONDATA_OF(region
)->m_region
);
146 // ----------------------------------------------------------------------------
147 // wxRegion operations
148 // ----------------------------------------------------------------------------
150 void wxRegion::Clear()
155 bool wxRegion::Union( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
157 // workaround for a strange GTK/X11 bug: taking union with an empty
158 // rectangle results in an empty region which is definitely not what we
160 if ( !width
|| !height
)
165 InitRect(x
, y
, width
, height
);
175 rect
.height
= height
;
177 gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
183 bool wxRegion::Union( const wxRect
& rect
)
185 return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
188 bool wxRegion::Union( const wxRegion
& region
)
195 m_refData
= new wxRegionRefData();
196 M_REGIONDATA
->m_region
= gdk_region_new();
203 gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
208 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
210 wxRegion
reg( x
, y
, width
, height
);
212 return Intersect( reg
);
215 bool wxRegion::Intersect( const wxRect
& rect
)
217 wxRegion
reg( rect
);
219 return Intersect( reg
);
222 bool wxRegion::Intersect( const wxRegion
& region
)
229 // intersecting with invalid region doesn't make sense
235 gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
240 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
242 wxRegion
reg( x
, y
, width
, height
);
243 return Subtract( reg
);
246 bool wxRegion::Subtract( const wxRect
& rect
)
248 wxRegion
reg( rect
);
249 return Subtract( reg
);
252 bool wxRegion::Subtract( const wxRegion
& region
)
259 // subtracting from an invalid region doesn't make sense
265 gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
270 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
272 wxRegion
reg( x
, y
, width
, height
);
276 bool wxRegion::Xor( const wxRect
& rect
)
278 wxRegion
reg( rect
);
282 bool wxRegion::Xor( const wxRegion
& region
)
294 gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
299 bool wxRegion::Offset( wxCoord x
, wxCoord y
)
306 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
311 // ----------------------------------------------------------------------------
313 // ----------------------------------------------------------------------------
315 void wxRegion::GetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
320 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
335 wxRect
wxRegion::GetBox() const
338 GetBox( x
, y
, w
, h
);
339 return wxRect( x
, y
, w
, h
);
342 bool wxRegion::Empty() const
347 return gdk_region_empty( M_REGIONDATA
->m_region
);
350 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
) const
355 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
361 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
371 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
374 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
375 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
376 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
381 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
383 return Contains( pt
.x
, pt
.y
);
386 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
388 return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
391 GdkRegion
*wxRegion::GetRegion() const
394 return (GdkRegion
*) NULL
;
396 return M_REGIONDATA
->m_region
;
399 // ----------------------------------------------------------------------------
401 // ----------------------------------------------------------------------------
403 class wxRIRefData
: public wxObjectRefData
406 wxRIRefData() { Init(); }
407 virtual ~wxRIRefData();
409 void CreateRects( const wxRegion
& r
);
411 void Init() { m_rects
= NULL
; m_numRects
= 0; }
417 wxRIRefData::~wxRIRefData()
422 void wxRIRefData::CreateRects( const wxRegion
& region
)
428 GdkRegion
*gdkregion
= region
.GetRegion();
432 GdkRectangle
*gdkrects
= NULL
;
434 gdk_region_get_rectangles( gdkregion
, &gdkrects
, &numRects
);
436 m_numRects
= numRects
;
439 m_rects
= new wxRect
[m_numRects
];
440 for (size_t i
=0; i
< m_numRects
; ++i
)
442 GdkRectangle
&gr
= gdkrects
[i
];
443 wxRect
&wr
= m_rects
[i
];
447 wr
.height
= gr
.height
;
453 wxRegionIterator::wxRegionIterator()
455 m_refData
= new wxRIRefData();
459 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
461 m_refData
= new wxRIRefData();
465 void wxRegionIterator::Reset( const wxRegion
& region
)
468 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
472 bool wxRegionIterator::HaveRects() const
474 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
477 wxRegionIterator
& wxRegionIterator::operator ++ ()
485 wxRegionIterator
wxRegionIterator::operator ++ (int)
487 wxRegionIterator tmp
= *this;
494 wxCoord
wxRegionIterator::GetX() const
496 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
498 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
501 wxCoord
wxRegionIterator::GetY() const
503 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
505 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
508 wxCoord
wxRegionIterator::GetW() const
510 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
512 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
515 wxCoord
wxRegionIterator::GetH() const
517 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
519 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;
522 wxRect
wxRegionIterator::GetRect() const
526 r
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];