1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:   Region handling for wxWindows/MGL 
   4 // Author:    Vaclav Slavik 
   6 // Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com) 
   7 // Licence:   wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  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" 
  24 #include "wx/module.h" 
  28 #include "wx/listimpl.cpp" 
  29 WX_DEFINE_LIST(wxRegionRectList
) 
  31 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
) 
  32 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
, wxObject
) 
  34 //----------------------------------------------------------------------------- 
  35 // wxRegionRefData implementation 
  36 //----------------------------------------------------------------------------- 
  38 class WXDLLEXPORT wxRegionRefData 
: public wxGDIRefData
 
  43     wxRegionRefData(const wxRegionRefData
& data
) 
  45         m_region 
= data
.m_region
; 
  53 #define M_REGION       (((wxRegionRefData*)m_refData)->m_region) 
  54 #define M_REGION_OF(r) (((wxRegionRefData*)(r.m_refData))->m_region) 
  56 //----------------------------------------------------------------------------- 
  58 //----------------------------------------------------------------------------- 
  60 wxObjectRefData 
*wxRegion::CreateRefData() const 
  62     return new wxRegionRefData
; 
  65 wxObjectRefData 
*wxRegion::CloneRefData(const wxObjectRefData 
*data
) const 
  67     return new wxRegionRefData(*(wxRegionRefData 
*)data
); 
  71  * Create an empty region. 
  78 wxRegion::wxRegion(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) 
  80     m_refData 
= new wxRegionRefData
; 
  81     MGLRect 
rect(x
, y
, x 
+ w
, y 
+ h
); 
  85 wxRegion::wxRegion(const wxPoint
& topLeft
, const wxPoint
& bottomRight
) 
  87     m_refData 
= new wxRegionRefData
; 
  88     MGLRect 
rect(topLeft
.x
, topLeft
.y
, bottomRight
.x
+1, bottomRight
.y
+1); 
  92 wxRegion::wxRegion(const wxRect
& r
) 
  94     m_refData 
= new wxRegionRefData
; 
  95     MGLRect 
rect(r
.GetLeft(), r
.GetTop(), r
.GetRight()+1, r
.GetBottom()+1); 
  99 wxRegion::wxRegion(const MGLRegion
& region
) 
 101     m_refData 
= new wxRegionRefData
; 
 105 wxRegion::~wxRegion() 
 107     // m_refData unrefed in ~wxObject 
 110 const MGLRegion
& wxRegion::GetMGLRegion() const 
 115 //----------------------------------------------------------------------------- 
 117 //----------------------------------------------------------------------------- 
 119 // Clear current region 
 120 void wxRegion::Clear() 
 126 //----------------------------------------------------------------------------- 
 127 // Information on region 
 128 //----------------------------------------------------------------------------- 
 130 // Outer bounds of region 
 131 void wxRegion::GetBox(wxCoord
& x
, wxCoord
& y
, wxCoord
&w
, wxCoord 
&h
) const 
 136         rect 
= M_REGION
.getBounds(); 
 139         w 
= rect
.right 
- rect
.left
; 
 140         h 
= rect
.bottom 
- rect
.top
; 
 148 wxRect 
wxRegion::GetBox() const 
 152     return wxRect(x
, y
, w
, h
); 
 156 bool wxRegion::Empty() const 
 158     if (!m_refData
) return TRUE
; 
 159     return M_REGION
.isEmpty(); 
 162 //----------------------------------------------------------------------------- 
 164 //----------------------------------------------------------------------------- 
 166 bool wxRegion::Offset(wxCoord x
, wxCoord y
) 
 169     M_REGION
.offset(x
, y
); 
 173 // Union rectangle or region with this. 
 174 bool wxRegion::Union(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
 177     M_REGION 
+= MGLRect(x
, y
, x 
+ width
, y 
+ height
); 
 181 bool wxRegion::Union(const wxRegion
& region
) 
 184     M_REGION 
+= M_REGION_OF(region
); 
 188 // Intersect rectangle or region with this. 
 189 bool wxRegion::Intersect(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
 192     M_REGION 
&= MGLRect(x
, y
, x 
+ width
, y 
+ height
); 
 196 bool wxRegion::Intersect(const wxRegion
& region
) 
 199     M_REGION 
&= M_REGION_OF(region
); 
 203 // Subtract rectangle or region from this: 
 204 // Combines the parts of 'this' that are not part of the second region. 
 205 bool wxRegion::Subtract(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
 208     M_REGION 
-= MGLRect(x
, y
, x 
+ width
, y 
+ height
); 
 212 bool wxRegion::Subtract(const wxRegion
& region
) 
 215     M_REGION 
-= M_REGION_OF(region
); 
 219 // XOR: the union of two combined regions except for any overlapping areas. 
 220 bool wxRegion::Xor(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
) 
 223     MGLRect 
rect(x
, y
, x 
+ width
, y 
+ height
); 
 224     MGLRegion rg1 
= M_REGION 
+ rect
, 
 225               rg2 
= M_REGION 
& rect
; 
 226     M_REGION 
= rg1 
- rg2
; 
 230 bool wxRegion::Xor(const wxRegion
& region
) 
 233     MGLRegion rg1 
= M_REGION 
+ M_REGION_OF(region
), 
 234               rg2 
= M_REGION 
& M_REGION_OF(region
); 
 235     M_REGION 
= rg1 
- rg2
; 
 240 //----------------------------------------------------------------------------- 
 242 //----------------------------------------------------------------------------- 
 244 // Does the region contain the point (x,y)? 
 245 wxRegionContain 
wxRegion::Contains(wxCoord x
, wxCoord y
) const 
 250     if (M_REGION
.includes((int)x
, (int)y
)) 
 256 // Does the region contain the point pt? 
 257 wxRegionContain 
wxRegion::Contains(const wxPoint
& pt
) const 
 259     return Contains(pt
.x
, pt
.y
); 
 262 // Does the region contain the rectangle (x, y, w, h)? 
 263 wxRegionContain 
wxRegion::Contains(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const 
 268     MGLRect 
rect(x
, y
, x 
+ w
, y 
+ h
); 
 271     // 1) is the rectangle entirely covered by the region? 
 272     rg 
= MGLRegion(rect
) - M_REGION
; 
 273     if (rg
.isEmpty()) return wxInRegion
; 
 275     // 2) is the rectangle completely outside the region? 
 276     rg 
= M_REGION 
& rect
; // intersection 
 277     if (rg
.isEmpty()) return wxOutRegion
; 
 279     // 3) neither case happened => it is partially covered: 
 283 // Does the region contain the rectangle rect 
 284 wxRegionContain 
wxRegion::Contains(const wxRect
& rect
) const 
 286     return Contains(rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
 290 /////////////////////////////////////////////////////////////////////////////// 
 291 //                               wxRegionIterator                                 // 
 292 /////////////////////////////////////////////////////////////////////////////// 
 295 static wxMutex 
*gs_mutexIterator
; 
 297 class wxMglRegionModule 
: public wxModule
 
 300     virtual bool OnInit() 
 302         gs_mutexIterator 
= new wxMutex(); 
 305     virtual void OnExit() 
 307         wxDELETE(gs_mutexIterator
); 
 310     DECLARE_DYNAMIC_CLASS(wxMglRegionModule
) 
 312 IMPLEMENT_DYNAMIC_CLASS(wxMglRegionModule
, wxModule
) 
 316  * Initialize empty iterator 
 318 wxRegionIterator::wxRegionIterator() : m_currentNode(NULL
) 
 320     m_rects
.DeleteContents(TRUE
); 
 323 wxRegionIterator::~wxRegionIterator() 
 328  * Initialize iterator for region 
 330 wxRegionIterator::wxRegionIterator(const wxRegion
& region
) 
 332     m_rects
.DeleteContents(TRUE
); 
 337  * Reset iterator for a new /e region. 
 341 static wxRegionRectList 
*gs_rectList
; 
 343 static void MGLAPI 
wxMGL_region_callback(const rect_t 
*r
) 
 345     gs_rectList
->Append(new wxRect(r
->left
, r
->top
,  
 346                                    r
->right 
- r
->left
, r
->bottom 
- r
->top
)); 
 349 void wxRegionIterator::Reset(const wxRegion
& region
) 
 351     m_currentNode 
= NULL
; 
 357         wxMutexLocker(*gs_mutexIterator
); 
 359         gs_rectList 
= &m_rects
; 
 360         M_REGION_OF(region
).traverse(wxMGL_region_callback
); 
 361         m_currentNode 
= m_rects
.GetFirst(); 
 366  * Increment iterator. The rectangle returned is the one after the 
 369 void wxRegionIterator::operator ++ () 
 372         m_currentNode 
= m_currentNode
->GetNext(); 
 376  * Increment iterator. The rectangle returned is the one before the 
 379 void wxRegionIterator::operator ++ (int) 
 382         m_currentNode 
= m_currentNode
->GetNext(); 
 385 wxCoord 
wxRegionIterator::GetX() const 
 388         return m_currentNode
->GetData()->x
; 
 393 wxCoord 
wxRegionIterator::GetY() const 
 396         return m_currentNode
->GetData()->y
; 
 401 wxCoord 
wxRegionIterator::GetW() const 
 404         return m_currentNode
->GetData()->width
; 
 409 wxCoord 
wxRegionIterator::GetH() const 
 412         return m_currentNode
->GetData()->height
;