1 ///////////////////////////////////////////////////////////////////////////// 
   2 // File:      src/mac/carbon/region.cpp 
   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 #include "wx/wxprec.h" 
  13 #include "wx/region.h" 
  16     #include "wx/gdicmn.h" 
  19 #include "wx/mac/uma.h" 
  21 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
) 
  22 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
, wxObject
) 
  24 //----------------------------------------------------------------------------- 
  25 // wxRegionRefData implementation 
  26 //----------------------------------------------------------------------------- 
  28 class WXDLLEXPORT wxRegionRefData 
: public wxGDIRefData
 
  32     { m_macRgn 
= NewRgn(); } 
  34     wxRegionRefData(const wxRegionRefData
& data
) 
  38         CopyRgn( data
.m_macRgn 
, m_macRgn 
); 
  41     virtual ~wxRegionRefData() 
  42     { DisposeRgn( m_macRgn 
); } 
  47 #define M_REGION (((wxRegionRefData*)m_refData)->m_macRgn) 
  48 #define OTHER_M_REGION(a) (((wxRegionRefData*)(a.m_refData))->m_macRgn) 
  50 //----------------------------------------------------------------------------- 
  52 //----------------------------------------------------------------------------- 
  55  * Create an empty region. 
  59     m_refData 
= new wxRegionRefData
; 
  62 wxRegion::wxRegion(WXHRGN hRegion 
) 
  64     m_refData 
= new wxRegionRefData
; 
  65     CopyRgn( (RgnHandle
) hRegion 
, (RgnHandle
) M_REGION 
) ; 
  68 wxRegion::wxRegion(long x
, long y
, long w
, long h
) 
  70     m_refData 
= new wxRegionRefData
; 
  71     SetRectRgn( (RgnHandle
) M_REGION 
, x 
, y 
, x 
+ w 
, y 
+ h 
) ; 
  74 wxRegion::wxRegion(const wxPoint
& topLeft
, const wxPoint
& bottomRight
) 
  76     m_refData 
= new wxRegionRefData
; 
  77     SetRectRgn( (RgnHandle
) M_REGION 
, topLeft
.x 
, topLeft
.y 
, bottomRight
.x 
, bottomRight
.y 
) ; 
  80 wxRegion::wxRegion(const wxRect
& rect
) 
  82     m_refData 
= new wxRegionRefData
; 
  83     SetRectRgn( (RgnHandle
) M_REGION 
, rect
.x 
, rect
.y 
, rect
.x 
+ rect
.width 
, rect
.y 
+ rect
.height 
) ; 
  86 wxRegion::wxRegion(size_t n
, const wxPoint 
*points
, int WXUNUSED(fillStyle
)) 
  88     m_refData 
= new wxRegionRefData
; 
  92     // OS X somehow does not collect the region invisibly as before, so sometimes things 
  93     // get drawn on screen instead of just being combined into a region, therefore we allocate a temp gworld now 
  95     GWorldPtr gWorld 
= NULL
; 
  99     Rect destRect 
= { 0, 0, 1, 1 }; 
 101     ::GetGWorld( &oldWorld
, &oldGDHandle 
); 
 102     err 
= ::NewGWorld( &gWorld
, 32, &destRect
, NULL
, NULL
, 0 ); 
 105         ::SetGWorld( gWorld
, GetGDevice() ); 
 109         wxCoord x1
, x2 
, y1 
, y2 
; 
 110         x2 
= x1 
= points
[0].x 
; 
 111         y2 
= y1 
= points
[0].y 
; 
 114         for (size_t i 
= 1; i 
< n
; i
++) 
 121         // close the polyline if necessary 
 122         if ( x1 
!= x2 
|| y1 
!= y2 
) 
 125         CloseRgn( M_REGION 
) ; 
 127         ::SetGWorld( oldWorld
, oldGDHandle 
); 
 132 wxRegion::~wxRegion() 
 134     // m_refData unrefed in ~wxObject 
 137 //----------------------------------------------------------------------------- 
 139 //----------------------------------------------------------------------------- 
 141 //! Clear current region 
 142 void wxRegion::Clear() 
 148 bool wxRegion::DoOffset(wxCoord x
, wxCoord y
) 
 150     wxCHECK_MSG( M_REGION
, false, _T("invalid wxRegion") ); 
 156     OffsetRgn( M_REGION 
, x 
, y 
) ; 
 162 //! Union /e region with this. 
 163 bool wxRegion::DoCombine(const wxRegion
& region
, wxRegionOp op
) 
 165     wxCHECK_MSG( region
.Ok(), false, _T("invalid wxRegion") ); 
 167     // Don't change shared data 
 170         m_refData 
= new wxRegionRefData(); 
 172     else if (m_refData
->GetRefCount() > 1) 
 174         wxRegionRefData
* ref 
= (wxRegionRefData
*)m_refData
; 
 176         m_refData 
= new wxRegionRefData(*ref
); 
 182             SectRgn( M_REGION 
, OTHER_M_REGION(region
) , M_REGION 
) ; 
 186             UnionRgn( M_REGION 
, OTHER_M_REGION(region
) , M_REGION 
) ; 
 190              XorRgn( M_REGION 
, OTHER_M_REGION(region
) , M_REGION 
) ; 
 194             DiffRgn( M_REGION 
, OTHER_M_REGION(region
) , M_REGION 
) ; 
 199             CopyRgn( OTHER_M_REGION(region
) , M_REGION 
) ; 
 206 //----------------------------------------------------------------------------- 
 207 //# Information on region 
 208 //----------------------------------------------------------------------------- 
 210 bool wxRegion::DoIsEqual(const wxRegion
& region
) const 
 212     wxFAIL_MSG( _T("not implemented") ); 
 217 // Outer bounds of region 
 218 bool wxRegion::DoGetBox(wxCoord
& x
, wxCoord
& y
, wxCoord
& w
, wxCoord
& h
) const 
 223         GetRegionBounds( M_REGION 
, &box 
) ; 
 226         w 
= box
.right 
- box
.left 
; 
 227         h 
= box
.bottom 
- box
.top 
; 
 240 bool wxRegion::IsEmpty() const 
 243         return EmptyRgn( M_REGION 
) ; 
 248 const WXHRGN 
wxRegion::GetWXHRGN() const 
 253 //----------------------------------------------------------------------------- 
 255 //----------------------------------------------------------------------------- 
 257 // Does the region contain the point? 
 258 wxRegionContain 
wxRegion::DoContainsPoint(wxCoord x
, wxCoord y
) const 
 263     Point p 
= { y 
, x 
} ; 
 264     if (PtInRgn( p 
, M_REGION 
) ) 
 270 // Does the region contain the rectangle (x, y, w, h)? 
 271 wxRegionContain 
wxRegion::DoContainsRect(const wxRect
& r
) const 
 276     Rect rect 
= { r
.y 
, r
.x 
, r
.y 
+ r
.height 
, r
.x 
+ r
.width 
} ; 
 277     if (RectInRgn( &rect 
, M_REGION 
) ) 
 283 /////////////////////////////////////////////////////////////////////////////// 
 285 //                               wxRegionIterator                            // 
 287 /////////////////////////////////////////////////////////////////////////////// 
 290  * Initialize empty iterator 
 292 wxRegionIterator::wxRegionIterator() 
 293     : m_current(0), m_numRects(0), m_rects(NULL
) 
 297 wxRegionIterator::~wxRegionIterator() 
 306 wxRegionIterator::wxRegionIterator(const wxRegionIterator
& iterator
) 
 308     , m_current(iterator
.m_current
) 
 312     SetRects(iterator
.m_numRects
, iterator
.m_rects
); 
 315 wxRegionIterator
& wxRegionIterator::operator=(const wxRegionIterator
& iterator
) 
 317     m_current  
= iterator
.m_current
; 
 318     SetRects(iterator
.m_numRects
, iterator
.m_rects
); 
 324  * Set iterator rects for region 
 326 void wxRegionIterator::SetRects(long numRects
, wxRect 
*rects
) 
 334     if (rects 
&& (numRects 
> 0)) 
 338         m_rects 
= new wxRect
[numRects
]; 
 339         for (i 
= 0; i 
< numRects
; i
++) 
 340             m_rects
[i
] = rects
[i
]; 
 343     m_numRects 
= numRects
; 
 347  * Initialize iterator for region 
 349 wxRegionIterator::wxRegionIterator(const wxRegion
& region
) 
 357  * Reset iterator for a new /e region. 
 360 OSStatus 
wxMacRegionToRectsCounterCallback( 
 361     UInt16 message
, RgnHandle region
, const Rect 
*rect
, void *data 
) 
 363     long *m_numRects 
= (long*) data 
; 
 364     if ( message 
== kQDRegionToRectsMsgInit 
) 
 368     else if (message 
== kQDRegionToRectsMsgParse
) 
 376 class RegionToRectsCallbackData
 
 383 OSStatus 
wxMacRegionToRectsSetterCallback( 
 384     UInt16 message
, RgnHandle region
, const Rect 
*rect
, void *data 
) 
 386     if (message 
== kQDRegionToRectsMsgParse
) 
 388         RegionToRectsCallbackData 
*cb 
= (RegionToRectsCallbackData
*) data 
; 
 389         cb
->m_rects
[cb
->m_current
++] = wxRect( rect
->left 
, rect
->top 
, rect
->right 
- rect
->left 
, rect
->bottom 
- rect
->top 
) ; 
 395 void wxRegionIterator::Reset(const wxRegion
& region
) 
 406     if (m_region
.IsEmpty()) 
 412         RegionToRectsUPP proc 
=  
 414         (RegionToRectsUPP
) wxMacRegionToRectsCounterCallback
; 
 416         NewRegionToRectsUPP( wxMacRegionToRectsCounterCallback 
); 
 419         OSStatus err 
= noErr
; 
 420         err 
= QDRegionToRects (OTHER_M_REGION( region 
) , kQDParseRegionFromTopLeft
, proc
, (void*)&m_numRects
); 
 424             DisposeRegionToRectsUPP (proc
); 
 428             (RegionToRectsUPP
) wxMacRegionToRectsSetterCallback
; 
 430             NewRegionToRectsUPP (wxMacRegionToRectsSetterCallback
); 
 432             m_rects 
= new wxRect
[m_numRects
]; 
 433             RegionToRectsCallbackData data 
; 
 434             data
.m_rects 
= m_rects 
; 
 436             QDRegionToRects( OTHER_M_REGION( region 
) , kQDParseRegionFromTopLeft
, proc
, (void*)&data 
); 
 444         DisposeRegionToRectsUPP( proc 
); 
 450  * Increment iterator. The rectangle returned is the one after the 
 453 wxRegionIterator
& wxRegionIterator::operator ++ () 
 455     if (m_current 
< m_numRects
) 
 462  * Increment iterator. The rectangle returned is the one before the 
 465 wxRegionIterator 
wxRegionIterator::operator ++ (int) 
 467     wxRegionIterator 
previous(*this); 
 469     if (m_current 
< m_numRects
) 
 475 long wxRegionIterator::GetX() const 
 477     if (m_current 
< m_numRects
) 
 478         return m_rects
[m_current
].x
; 
 483 long wxRegionIterator::GetY() const 
 485     if (m_current 
< m_numRects
) 
 486         return m_rects
[m_current
].y
; 
 491 long wxRegionIterator::GetW() const 
 493     if (m_current 
< m_numRects
) 
 494         return m_rects
[m_current
].width 
; 
 499 long wxRegionIterator::GetH() const 
 501     if (m_current 
< m_numRects
) 
 502         return m_rects
[m_current
].height
;