1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Region handling for wxWindows/MGL
4 // Author: Vaclav Slavik
6 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "region.h"
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
21 #include "wx/region.h"
22 #include "wx/gdicmn.h"
23 #include "wx/thread.h"
27 #include "wx/listimpl.cpp"
28 WX_DEFINE_LIST(wxRegionRectList
)
30 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
)
31 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
, wxObject
)
33 //-----------------------------------------------------------------------------
34 // wxRegionRefData implementation
35 //-----------------------------------------------------------------------------
37 class WXDLLEXPORT wxRegionRefData
: public wxGDIRefData
44 wxRegionRefData(const wxRegionRefData
& data
)
46 m_region
= data
.m_region
;
56 #define M_REGION (((wxRegionRefData*)m_refData)->m_region)
57 #define M_REGION_OF(r) (((wxRegionRefData*)(r.m_refData))->m_region)
59 //-----------------------------------------------------------------------------
61 //-----------------------------------------------------------------------------
64 * Create an empty region.
68 m_refData
= (wxRegionRefData
*)NULL
;
71 wxRegion::wxRegion(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
73 m_refData
= new wxRegionRefData
;
74 MGLRect
rect(x
, y
, x
+ w
, y
+ h
);
78 wxRegion::wxRegion(const wxPoint
& topLeft
, const wxPoint
& bottomRight
)
80 m_refData
= new wxRegionRefData
;
81 MGLRect
rect(topLeft
.x
, topLeft
.y
, bottomRight
.x
, bottomRight
.y
);
85 wxRegion::wxRegion(const wxRect
& r
)
87 m_refData
= new wxRegionRefData
;
88 MGLRect
rect(r
.GetLeft(), r
.GetTop(), r
.GetRight(), r
.GetBottom());
92 wxRegion::wxRegion(const MGLRegion
& region
)
94 m_refData
= new wxRegionRefData
;
100 // m_refData unrefed in ~wxObject
103 const MGLRegion
& wxRegion::GetMGLRegion() const
108 //-----------------------------------------------------------------------------
110 //-----------------------------------------------------------------------------
112 // Clear current region
113 void wxRegion::Clear()
119 //-----------------------------------------------------------------------------
120 // Information on region
121 //-----------------------------------------------------------------------------
123 // Outer bounds of region
124 void wxRegion::GetBox(wxCoord
& x
, wxCoord
& y
, wxCoord
&w
, wxCoord
&h
) const
129 rect
= M_REGION
.getBounds();
132 w
= rect
.right
- rect
.left
;
133 h
= rect
.bottom
- rect
.top
;
141 wxRect
wxRegion::GetBox() const
145 return wxRect(x
, y
, w
, h
);
149 bool wxRegion::Empty() const
151 if (!m_refData
) return TRUE
;
152 return M_REGION
.isEmpty();
155 //-----------------------------------------------------------------------------
157 //-----------------------------------------------------------------------------
159 // Union rectangle or region with this.
160 bool wxRegion::Union(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
163 M_REGION
+= MGLRect(x
, y
, x
+ width
, y
+ height
);
167 bool wxRegion::Union(const wxRegion
& region
)
170 M_REGION
+= M_REGION_OF(region
);
174 // Intersect rectangle or region with this.
175 bool wxRegion::Intersect(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
178 M_REGION
&= MGLRect(x
, y
, x
+ width
, y
+ height
);
182 bool wxRegion::Intersect(const wxRegion
& region
)
185 M_REGION
&= M_REGION_OF(region
);
189 // Subtract rectangle or region from this:
190 // Combines the parts of 'this' that are not part of the second region.
191 bool wxRegion::Subtract(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
194 M_REGION
-= MGLRect(x
, y
, x
+ width
, y
+ height
);
198 bool wxRegion::Subtract(const wxRegion
& region
)
201 M_REGION
-= M_REGION_OF(region
);
205 // XOR: the union of two combined regions except for any overlapping areas.
206 bool wxRegion::Xor(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
209 MGLRect
rect(x
, y
, x
+ width
, y
+ height
);
210 MGLRegion rg1
= M_REGION
+ rect
,
211 rg2
= M_REGION
& rect
;
212 M_REGION
= rg1
- rg2
;
216 bool wxRegion::Xor(const wxRegion
& region
)
219 MGLRegion rg1
= M_REGION
+ M_REGION_OF(region
),
220 rg2
= M_REGION
& M_REGION_OF(region
);
221 M_REGION
= rg1
- rg2
;
226 //-----------------------------------------------------------------------------
228 //-----------------------------------------------------------------------------
230 // Does the region contain the point (x,y)?
231 wxRegionContain
wxRegion::Contains(wxCoord x
, wxCoord y
) const
236 if (M_REGION
.includes((int)x
, (int)y
))
242 // Does the region contain the point pt?
243 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
245 return Contains(pt
.x
, pt
.y
);
248 // Does the region contain the rectangle (x, y, w, h)?
249 wxRegionContain
wxRegion::Contains(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
254 MGLRect
rect(x
, y
, x
+ w
, y
+ h
);
257 // 1) is the rectangle entirely covered by the region?
258 rg
= MGLRegion(rect
) - M_REGION
;
259 if (rg
.isEmpty()) return wxInRegion
;
261 // 2) is the rectangle completely outside the region?
262 rg
= M_REGION
& rect
; // intersection
263 if (rg
.isEmpty()) return wxOutRegion
;
265 // 3) neither case happened => it is partially covered:
269 // Does the region contain the rectangle rect
270 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
272 return Contains(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
277 void wxRegion::Unshare()
281 m_refData
= new wxRegionRefData();
285 wxRegionRefData
* ref
= new wxRegionRefData(*(wxRegionRefData
*)m_refData
);
295 ///////////////////////////////////////////////////////////////////////////////
296 // wxRegionIterator //
297 ///////////////////////////////////////////////////////////////////////////////
300 * Initialize empty iterator
302 wxRegionIterator::wxRegionIterator() : m_currentNode(NULL
)
304 m_rects
.DeleteContents(TRUE
);
307 wxRegionIterator::~wxRegionIterator()
312 * Initialize iterator for region
314 wxRegionIterator::wxRegionIterator(const wxRegion
& region
)
316 m_rects
.DeleteContents(TRUE
);
321 * Reset iterator for a new /e region.
325 static wxRegionRectList
*gs_rectList
;
327 static void wxMGL_region_callback(const rect_t
*r
)
329 gs_rectList
->Append(new wxRect(r
->left
, r
->top
,
330 r
->right
- r
->left
, r
->bottom
- r
->top
));
333 void wxRegionIterator::Reset(const wxRegion
& region
)
335 m_currentNode
= NULL
;
341 gs_rectList
= &m_rects
;
342 M_REGION_OF(region
).traverse(wxMGL_region_callback
);
344 m_currentNode
= m_rects
.GetFirst();
349 * Increment iterator. The rectangle returned is the one after the
352 void wxRegionIterator::operator ++ ()
355 m_currentNode
= m_currentNode
->GetNext();
359 * Increment iterator. The rectangle returned is the one before the
362 void wxRegionIterator::operator ++ (int)
365 m_currentNode
= m_currentNode
->GetNext();
368 wxCoord
wxRegionIterator::GetX() const
371 return m_currentNode
->GetData()->x
;
376 wxCoord
wxRegionIterator::GetY() const
379 return m_currentNode
->GetData()->y
;
384 wxCoord
wxRegionIterator::GetW() const
387 return m_currentNode
->GetData()->width
;
392 wxCoord
wxRegionIterator::GetH() const
395 return m_currentNode
->GetData()->height
;