1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:   Region class 
   4 // Author:    Stefan Csomor 
   5 // Created:   Fri Oct 24 10:46:34 MET 1997 
   7 // Copyright: (c) 1997 Stefan Csomor 
   8 // Licence:   wxWindows licence 
   9 ///////////////////////////////////////////////////////////////////////////// 
  11 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  12 #pragma implementation "region.h" 
  15 #include "wx/wxprec.h" 
  17 #include "wx/region.h" 
  18 #include "wx/gdicmn.h" 
  19 #include "wx/mac/uma.h" 
  21 #if !USE_SHARED_LIBRARY 
  22     IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
) 
  23     IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
, wxObject
) 
  26 //----------------------------------------------------------------------------- 
  27 // wxRegionRefData implementation 
  28 //----------------------------------------------------------------------------- 
  30 class WXDLLEXPORT wxRegionRefData 
: public wxGDIRefData 
{ 
  37     wxRegionRefData(const wxRegionRefData
& data
) 
  41         CopyRgn( data
.m_macRgn 
, m_macRgn 
) ; 
  46         DisposeRgn( m_macRgn 
) ; 
  51 #define M_REGION (((wxRegionRefData*)m_refData)->m_macRgn) 
  52 #define OTHER_M_REGION(a) (((wxRegionRefData*)(a.m_refData))->m_macRgn) 
  54 //----------------------------------------------------------------------------- 
  56 //----------------------------------------------------------------------------- 
  59  * Create an empty region. 
  63     m_refData 
= new wxRegionRefData
; 
  66 wxRegion::wxRegion(WXHRGN hRegion 
) 
  68     m_refData 
= new wxRegionRefData
; 
  69     CopyRgn( (RgnHandle
) hRegion 
, (RgnHandle
) M_REGION 
) ; 
  72 wxRegion::wxRegion(long x
, long y
, long w
, long h
) 
  74     m_refData 
= new wxRegionRefData
; 
  75     SetRectRgn( (RgnHandle
) M_REGION 
, x 
, y 
, x
+w 
, y
+h 
) ; 
  78 wxRegion::wxRegion(const wxPoint
& topLeft
, const wxPoint
& bottomRight
) 
  80     m_refData 
= new wxRegionRefData
; 
  81     SetRectRgn( (RgnHandle
) M_REGION 
, topLeft
.x 
, topLeft
.y 
, bottomRight
.x 
, bottomRight
.y 
) ; 
  84 wxRegion::wxRegion(const wxRect
& rect
) 
  86     m_refData 
= new wxRegionRefData
; 
  87     SetRectRgn( (RgnHandle
) M_REGION 
, rect
.x 
, rect
.y 
, rect
.x
+rect
.width 
, rect
.y
+rect
.height 
) ; 
  90 wxRegion::wxRegion(size_t n
, const wxPoint 
*points
, int WXUNUSED(fillStyle
)) 
  92     m_refData 
= new wxRegionRefData
; 
  96     wxCoord x1
, x2 
, y1 
, y2 
; 
  97     x2 
= x1 
= points
[0].x 
; 
  98     y2 
= y1 
= points
[0].y 
; 
 100     for (size_t i 
= 1; i 
< n
; i
++) 
 106     // close the polyline if necessary 
 107     if ( x1 
!= x2 
|| y1 
!= y2 
) 
 112     CloseRgn( M_REGION 
) ; 
 116  * Destroy the region. 
 118 wxRegion::~wxRegion() 
 120     // m_refData unrefed in ~wxObject 
 123 //----------------------------------------------------------------------------- 
 125 //----------------------------------------------------------------------------- 
 127 //! Clear current region 
 128 void wxRegion::Clear() 
 134 bool wxRegion::Offset(wxCoord x
, wxCoord y
) 
 136     wxCHECK_MSG( M_REGION
, false, _T("invalid wxRegion") ); 
 144     OffsetRgn( M_REGION 
, x 
, y 
) ; 
 149 //! Combine rectangle (x, y, w, h) with this. 
 150 bool wxRegion::Combine(long x
, long y
, long width
, long height
, wxRegionOp op
) 
 152     // Don't change shared data 
 155         m_refData 
= new wxRegionRefData(); 
 157     else if (m_refData
->GetRefCount() > 1)  
 159         wxRegionRefData
* ref 
= (wxRegionRefData
*)m_refData
; 
 161         m_refData 
= new wxRegionRefData(*ref
); 
 163     RgnHandle rgn 
= NewRgn() ; 
 164         SetRectRgn( rgn 
, x 
, y
, x
+width
,y 
+ height 
) ; 
 169             SectRgn( M_REGION 
, rgn 
, M_REGION 
) ; 
 172             UnionRgn( M_REGION 
, rgn 
, M_REGION 
) ; 
 175              XorRgn( M_REGION 
, rgn 
, M_REGION 
) ; 
 178             DiffRgn( M_REGION 
, rgn 
, M_REGION 
) ; 
 182                    CopyRgn( rgn 
,M_REGION 
) ; 
 191 //! Union /e region with this. 
 192 bool wxRegion::Combine(const wxRegion
& region
, wxRegionOp op
) 
 197     // Don't change shared data 
 199         m_refData 
= new wxRegionRefData(); 
 201     else    if (m_refData
->GetRefCount() > 1)  
 203         wxRegionRefData
* ref 
= (wxRegionRefData
*)m_refData
; 
 205         m_refData 
= new wxRegionRefData(*ref
); 
 211             SectRgn( M_REGION 
, OTHER_M_REGION(region
) , M_REGION 
) ; 
 214             UnionRgn( M_REGION 
, OTHER_M_REGION(region
) , M_REGION 
) ; 
 217              XorRgn( M_REGION 
, OTHER_M_REGION(region
) , M_REGION 
) ; 
 220             DiffRgn( M_REGION 
, OTHER_M_REGION(region
) , M_REGION 
) ; 
 224                    CopyRgn( OTHER_M_REGION(region
) ,M_REGION 
) ; 
 231 bool wxRegion::Combine(const wxRect
& rect
, wxRegionOp op
) 
 233     return Combine(rect
.GetLeft(), rect
.GetTop(), rect
.GetWidth(), rect
.GetHeight(), op
); 
 236 //----------------------------------------------------------------------------- 
 237 //# Information on region 
 238 //----------------------------------------------------------------------------- 
 240 // Outer bounds of region 
 241 void wxRegion::GetBox(wxCoord
& x
, wxCoord
& y
, wxCoord
& w
, wxCoord
& h
) const 
 246         GetRegionBounds( M_REGION 
, &box 
) ; 
 249         w 
= box
.right 
- box
.left 
; 
 250         h 
= box
.bottom 
- box
.top 
; 
 258 wxRect 
wxRegion::GetBox() const 
 262     return wxRect(x
, y
, w
, h
); 
 266 bool wxRegion::Empty() const 
 268     return EmptyRgn( M_REGION 
) ; 
 271 const WXHRGN 
wxRegion::GetWXHRGN() const 
 276 //----------------------------------------------------------------------------- 
 278 //----------------------------------------------------------------------------- 
 280 // Does the region contain the point (x,y)? 
 281 wxRegionContain 
wxRegion::Contains(long x
, long y
) const 
 286     // TODO. Return wxInRegion if within region. 
 292 // Does the region contain the point pt? 
 293 wxRegionContain 
wxRegion::Contains(const wxPoint
& pt
) const 
 298     Point p 
= { pt
.y 
, pt
.x 
} ; 
 299     if (PtInRgn( p 
, M_REGION 
) ) 
 305 // Does the region contain the rectangle (x, y, w, h)? 
 306 wxRegionContain 
wxRegion::Contains(long x
, long y
, long w
, long h
) const 
 311     Rect rect 
= { y 
, x 
, y 
+ h 
, x 
+ w 
} ; 
 312     if (RectInRgn( &rect 
, M_REGION 
) ) 
 318 // Does the region contain the rectangle rect 
 319 wxRegionContain 
wxRegion::Contains(const wxRect
& rect
) const 
 328     h 
= rect
.GetHeight(); 
 329     return Contains(x
, y
, w
, h
); 
 332 /////////////////////////////////////////////////////////////////////////////// 
 334 //                               wxRegionIterator                            // 
 336 /////////////////////////////////////////////////////////////////////////////// 
 339  * Initialize empty iterator 
 341 wxRegionIterator::wxRegionIterator() 
 342     : m_current(0), m_numRects(0), m_rects(NULL
) 
 346 wxRegionIterator::~wxRegionIterator() 
 354 wxRegionIterator::wxRegionIterator(const wxRegionIterator
& iterator
) 
 356     , m_current(iterator
.m_current
) 
 360     SetRects(iterator
.m_numRects
, iterator
.m_rects
); 
 363 wxRegionIterator
& wxRegionIterator::operator=(const wxRegionIterator
& iterator
) 
 365     m_current  
= iterator
.m_current
; 
 366     SetRects(iterator
.m_numRects
, iterator
.m_rects
); 
 371  * Set iterator rects for region 
 373 void wxRegionIterator::SetRects(long numRects
, wxRect 
*rects
) 
 382         m_rects 
= new wxRect
[numRects
]; 
 383         for (i 
= 0; i 
< numRects
; i
++) 
 384             m_rects
[i
] = rects
[i
]; 
 386     m_numRects 
= numRects
; 
 390  * Initialize iterator for region 
 392 wxRegionIterator::wxRegionIterator(const wxRegion
& region
) 
 400  * Reset iterator for a new /e region. 
 403 OSStatus 
wxMacRegionToRectsCounterCallback ( 
 404     UInt16 message
, RgnHandle region
, const Rect 
*rect
, void *data
) 
 406     long *m_numRects 
= (long*) data 
; 
 407     if ( message 
== kQDRegionToRectsMsgInit 
) 
 411     else if (message 
== kQDRegionToRectsMsgParse
) 
 418 class RegionToRectsCallbackData 
 
 425 OSStatus 
wxMacRegionToRectsSetterCallback ( 
 426     UInt16 message
, RgnHandle region
, const Rect 
*rect
, void *data
) 
 428     if (message 
== kQDRegionToRectsMsgParse
) 
 430         RegionToRectsCallbackData 
*cb 
= (RegionToRectsCallbackData
*) data 
; 
 431         cb
->m_rects
[cb
->m_current
] = wxRect( rect
->left 
, rect
->top 
, rect
->right 
- rect
->left 
, rect
->bottom 
- rect
->top 
) ; 
 436 void wxRegionIterator::Reset(const wxRegion
& region
) 
 446     if (m_region
.Empty()) 
 450         RegionToRectsUPP proc 
= NewRegionToRectsUPP (wxMacRegionToRectsCounterCallback
); 
 452         OSStatus err 
= noErr
; 
 453         err 
= QDRegionToRects (OTHER_M_REGION( region 
) , kQDParseRegionFromTopLeft
, proc
, (void*)&m_numRects
);  
 456             DisposeRegionToRectsUPP (proc
); 
 457             proc 
= NewRegionToRectsUPP (wxMacRegionToRectsSetterCallback
); 
 458             m_rects 
= new wxRect
[m_numRects
]; 
 459             RegionToRectsCallbackData data 
; 
 460             data
.m_rects 
= m_rects 
; 
 462             QDRegionToRects (OTHER_M_REGION( region 
) , kQDParseRegionFromTopLeft
, proc
, (void*)&data
);  
 468         DisposeRegionToRectsUPP (proc
); 
 473  * Increment iterator. The rectangle returned is the one after the 
 476 wxRegionIterator
& wxRegionIterator::operator ++ () 
 478     if (m_current 
< m_numRects
) 
 484  * Increment iterator. The rectangle returned is the one before the 
 487 wxRegionIterator 
wxRegionIterator::operator ++ (int) 
 489     wxRegionIterator 
previous(*this); 
 491     if (m_current 
< m_numRects
) 
 497 long wxRegionIterator::GetX() const 
 499     if (m_current 
< m_numRects
) 
 500         return m_rects
[m_current
].x
; 
 504 long wxRegionIterator::GetY() const 
 506     if (m_current 
< m_numRects
) 
 507         return m_rects
[m_current
].y
; 
 511 long wxRegionIterator::GetW() const 
 513     if (m_current 
< m_numRects
) 
 514         return m_rects
[m_current
].width 
; 
 518 long wxRegionIterator::GetH() const 
 520     if (m_current 
< m_numRects
) 
 521         return m_rects
[m_current
].height
;