1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mgl/region.cpp
3 // Purpose: Region handling for wxWidgets/MGL
4 // Author: Vaclav Slavik
6 // Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
17 #include "wx/region.h"
18 #include "wx/gdicmn.h"
19 #include "wx/thread.h"
20 #include "wx/module.h"
24 #include "wx/listimpl.cpp"
25 WX_DEFINE_LIST(wxRegionRectList
)
27 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
)
28 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
, wxObject
)
30 //-----------------------------------------------------------------------------
31 // wxRegionRefData implementation
32 //-----------------------------------------------------------------------------
34 class WXDLLEXPORT wxRegionRefData
: public wxGDIRefData
39 wxRegionRefData(const wxRegionRefData
& data
)
41 m_region
= data
.m_region
;
49 #define M_REGION (((wxRegionRefData*)m_refData)->m_region)
50 #define M_REGION_OF(r) (((wxRegionRefData*)(r.m_refData))->m_region)
52 //-----------------------------------------------------------------------------
54 //-----------------------------------------------------------------------------
56 wxObjectRefData
*wxRegion::CreateRefData() const
58 return new wxRegionRefData
;
61 wxObjectRefData
*wxRegion::CloneRefData(const wxObjectRefData
*data
) const
63 return new wxRegionRefData(*(wxRegionRefData
*)data
);
67 * Create an empty region.
74 wxRegion::wxRegion(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
76 m_refData
= new wxRegionRefData
;
77 MGLRect
rect(x
, y
, x
+ w
, y
+ h
);
81 wxRegion::wxRegion(const wxPoint
& topLeft
, const wxPoint
& bottomRight
)
83 m_refData
= new wxRegionRefData
;
84 MGLRect
rect(topLeft
.x
, topLeft
.y
, bottomRight
.x
+1, bottomRight
.y
+1);
88 wxRegion::wxRegion(const wxRect
& r
)
90 m_refData
= new wxRegionRefData
;
91 MGLRect
rect(r
.GetLeft(), r
.GetTop(), r
.GetRight()+1, r
.GetBottom()+1);
95 wxRegion::wxRegion(const MGLRegion
& region
)
97 m_refData
= new wxRegionRefData
;
101 wxRegion::~wxRegion()
103 // m_refData unrefed in ~wxObject
106 const MGLRegion
& wxRegion::GetMGLRegion() const
111 //-----------------------------------------------------------------------------
113 //-----------------------------------------------------------------------------
115 // Clear current region
116 void wxRegion::Clear()
122 //-----------------------------------------------------------------------------
123 // Information on region
124 //-----------------------------------------------------------------------------
126 // Outer bounds of region
127 void wxRegion::GetBox(wxCoord
& x
, wxCoord
& y
, wxCoord
&w
, wxCoord
&h
) const
132 rect
= M_REGION
.getBounds();
135 w
= rect
.right
- rect
.left
;
136 h
= rect
.bottom
- rect
.top
;
144 wxRect
wxRegion::GetBox() const
148 return wxRect(x
, y
, w
, h
);
152 bool wxRegion::Empty() const
157 return (bool)(M_REGION
.isEmpty());
160 //-----------------------------------------------------------------------------
162 //-----------------------------------------------------------------------------
164 bool wxRegion::Offset(wxCoord x
, wxCoord y
)
167 M_REGION
.offset(x
, y
);
171 // Union rectangle or region with this.
172 bool wxRegion::Union(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
175 M_REGION
+= MGLRect(x
, y
, x
+ width
, y
+ height
);
179 bool wxRegion::Union(const wxRegion
& region
)
182 M_REGION
+= M_REGION_OF(region
);
186 // Intersect rectangle or region with this.
187 bool wxRegion::Intersect(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
190 M_REGION
&= MGLRect(x
, y
, x
+ width
, y
+ height
);
194 bool wxRegion::Intersect(const wxRegion
& region
)
197 M_REGION
&= M_REGION_OF(region
);
201 // Subtract rectangle or region from this:
202 // Combines the parts of 'this' that are not part of the second region.
203 bool wxRegion::Subtract(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
206 M_REGION
-= MGLRect(x
, y
, x
+ width
, y
+ height
);
210 bool wxRegion::Subtract(const wxRegion
& region
)
213 M_REGION
-= M_REGION_OF(region
);
217 // XOR: the union of two combined regions except for any overlapping areas.
218 bool wxRegion::Xor(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
221 MGLRect
rect(x
, y
, x
+ width
, y
+ height
);
222 MGLRegion rg1
= M_REGION
+ rect
,
223 rg2
= M_REGION
& rect
;
224 M_REGION
= rg1
- rg2
;
228 bool wxRegion::Xor(const wxRegion
& region
)
231 MGLRegion rg1
= M_REGION
+ M_REGION_OF(region
),
232 rg2
= M_REGION
& M_REGION_OF(region
);
233 M_REGION
= rg1
- rg2
;
238 //-----------------------------------------------------------------------------
240 //-----------------------------------------------------------------------------
242 // Does the region contain the point (x,y)?
243 wxRegionContain
wxRegion::Contains(wxCoord x
, wxCoord y
) const
248 if (M_REGION
.includes((int)x
, (int)y
))
254 // Does the region contain the point pt?
255 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
257 return Contains(pt
.x
, pt
.y
);
260 // Does the region contain the rectangle (x, y, w, h)?
261 wxRegionContain
wxRegion::Contains(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
266 MGLRect
rect(x
, y
, x
+ w
, y
+ h
);
269 // 1) is the rectangle entirely covered by the region?
270 rg
= MGLRegion(rect
) - M_REGION
;
271 if (rg
.isEmpty()) return wxInRegion
;
273 // 2) is the rectangle completely outside the region?
274 rg
= M_REGION
& rect
; // intersection
275 if (rg
.isEmpty()) return wxOutRegion
;
277 // 3) neither case happened => it is partially covered:
281 // Does the region contain the rectangle rect
282 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
284 return Contains(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
288 ///////////////////////////////////////////////////////////////////////////////
289 // wxRegionIterator //
290 ///////////////////////////////////////////////////////////////////////////////
293 static wxMutex
*gs_mutexIterator
;
295 class wxMglRegionModule
: public wxModule
298 virtual bool OnInit()
300 gs_mutexIterator
= new wxMutex();
303 virtual void OnExit()
305 wxDELETE(gs_mutexIterator
);
308 DECLARE_DYNAMIC_CLASS(wxMglRegionModule
)
310 IMPLEMENT_DYNAMIC_CLASS(wxMglRegionModule
, wxModule
)
314 * Initialize empty iterator
316 wxRegionIterator::wxRegionIterator() : m_currentNode(NULL
)
318 m_rects
.DeleteContents(true);
321 wxRegionIterator::~wxRegionIterator()
326 * Initialize iterator for region
328 wxRegionIterator::wxRegionIterator(const wxRegion
& region
)
330 m_rects
.DeleteContents(true);
335 * Reset iterator for a new /e region.
339 static wxRegionRectList
*gs_rectList
;
341 static void MGLAPI
wxMGL_region_callback(const rect_t
*r
)
343 gs_rectList
->Append(new wxRect(r
->left
, r
->top
,
344 r
->right
- r
->left
, r
->bottom
- r
->top
));
347 void wxRegionIterator::Reset(const wxRegion
& region
)
349 m_currentNode
= NULL
;
355 wxMutexLocker
lock(*gs_mutexIterator
);
357 gs_rectList
= &m_rects
;
358 M_REGION_OF(region
).traverse(wxMGL_region_callback
);
359 m_currentNode
= m_rects
.GetFirst();
364 * Increment iterator. The rectangle returned is the one after the
367 void wxRegionIterator::operator ++ ()
370 m_currentNode
= m_currentNode
->GetNext();
374 * Increment iterator. The rectangle returned is the one before the
377 void wxRegionIterator::operator ++ (int)
380 m_currentNode
= m_currentNode
->GetNext();
383 wxCoord
wxRegionIterator::GetX() const
386 return m_currentNode
->GetData()->x
;
391 wxCoord
wxRegionIterator::GetY() const
394 return m_currentNode
->GetData()->y
;
399 wxCoord
wxRegionIterator::GetW() const
402 return m_currentNode
->GetData()->width
;
407 wxCoord
wxRegionIterator::GetH() const
410 return m_currentNode
->GetData()->height
;