1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:   Region class 
   4 // Author:    Markus Holzem/Julian Smart 
   5 // Created:   Fri Oct 24 10:46:34 MET 1997 
   7 // Copyright: (c) 1997 Markus Holzem/Julian Smart 
   8 // Licence:   wxWindows licence 
   9 ///////////////////////////////////////////////////////////////////////////// 
  12 #pragma implementation "region.h" 
  15 #include "wx/region.h" 
  16 #include "wx/gdicmn.h" 
  19 #pragma message disable nosimpint 
  23 #pragma message enable nosimpint 
  25 // #include "wx/motif/private.h" 
  27     IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
) 
  28     IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
, wxObject
) 
  30 // ---------------------------------------------------------------------------- 
  32 // ---------------------------------------------------------------------------- 
  34 #include "wx/listimpl.cpp" 
  36 WX_DEFINE_LIST(wxRectList
); 
  38 //----------------------------------------------------------------------------- 
  39 // wxRegionRefData implementation 
  40 //----------------------------------------------------------------------------- 
  42 class WXDLLEXPORT wxRegionRefData 
: public wxGDIRefData 
{ 
  46         m_region 
= XCreateRegion(); 
  48         m_rects 
= (wxRect
*) NULL
; 
  52     wxRegionRefData(const wxRegionRefData
& data
) 
  54         m_region 
= XCreateRegion(); 
  55         m_rects 
= (wxRect
*) NULL
; 
  57         XUnionRegion(m_region
, data
.m_region
, m_region
); 
  59         SetRects(data
.m_rectCount
, data
.m_rects
); 
  64         XDestroyRegion(m_region
); 
  68     wxRect
* GetRects() { return m_rects
; }; 
  69     void SetRects(const wxRectList
& rectList
); 
  70     void SetRects(int count
, const wxRect
* rects
); 
  71     bool UsingRects() const { return m_usingRects
; } 
  72     int GetRectCount() const { return m_rectCount
; } 
  79     bool        m_usingRects
;  // TRUE if we're using the above. 
  82 void wxRegionRefData::SetRects(const wxRectList
& rectList
) 
  85     m_usingRects 
= (rectList
.Number() > 0); 
  88       m_rectCount 
= rectList
.Number(); 
  89       m_rects 
= new wxRect
[m_rectCount
]; 
  92     wxRectList::Node
* node 
= rectList
.GetFirst(); 
  95         wxRect
* rect 
= node
->GetData(); 
  97         node 
= node
->GetNext(); 
 102 void wxRegionRefData::SetRects(int count
, const wxRect
* rects
) 
 105     m_usingRects 
= (count 
> 0); 
 109       m_rects 
= new wxRect
[m_rectCount
]; 
 111       for (i 
= 0; i 
< m_rectCount
; i
++) 
 112         m_rects
[i
] = rects
[i
]; 
 116 void wxRegionRefData::DeleteRects() 
 121       m_rects 
= (wxRect
*) NULL
; 
 124    m_usingRects 
= FALSE
; 
 127 #define M_REGION (((wxRegionRefData*)m_refData)->m_region) 
 129 //----------------------------------------------------------------------------- 
 131 //----------------------------------------------------------------------------- 
 134  * Create an empty region. 
 140 wxRegion::wxRegion(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) 
 142     m_refData 
= new wxRegionRefData
; 
 149     XUnionRectWithRegion(&rect
, M_REGION
, M_REGION
); 
 152 wxRegion::wxRegion(const wxPoint
& topLeft
, const wxPoint
& bottomRight
) 
 154     m_refData 
= new wxRegionRefData
; 
 159     rect
.width    
= bottomRight
.x 
- topLeft
.x
; 
 160     rect
.height 
= bottomRight
.y 
- topLeft
.y
; 
 161     XUnionRectWithRegion(&rect
, M_REGION
, M_REGION
); 
 164 wxRegion::wxRegion(const wxRect
& rect
) 
 166     m_refData 
= new wxRegionRefData
; 
 171     rect1
.width    
= rect
.width
; 
 172     rect1
.height 
= rect
.height
; 
 173     XUnionRectWithRegion(&rect1
, M_REGION
, M_REGION
); 
 177  * Destroy the region. 
 179 wxRegion::~wxRegion() 
 181     // m_refData unrefed in ~wxObject 
 184 // Get the internal region handle 
 185 WXRegion 
wxRegion::GetXRegion() const 
 187     wxASSERT( m_refData 
!=NULL 
); 
 189     return (WXRegion
) ((wxRegionRefData
*)m_refData
)->m_region
; 
 192 //----------------------------------------------------------------------------- 
 194 //----------------------------------------------------------------------------- 
 196 //! Clear current region 
 197 void wxRegion::Clear() 
 202 //! Combine rectangle (x, y, w, h) with this. 
 203 bool wxRegion::Combine(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, wxRegionOp op
) 
 205     // Don't change shared data 
 207         m_refData 
= new wxRegionRefData(); 
 208     } else if (m_refData
->GetRefCount() > 1) { 
 209         wxRegionRefData
* ref 
= (wxRegionRefData
*)m_refData
; 
 211         m_refData 
= new wxRegionRefData(*ref
); 
 213     // If ref count is 1, that means it's 'ours' anyway so no action. 
 215     Region rectRegion 
= XCreateRegion(); 
 221     rect
.height 
= height
; 
 222     XUnionRectWithRegion(&rect
, rectRegion
, rectRegion
); 
 227             XIntersectRegion(M_REGION
, rectRegion
, M_REGION
); 
 230             XUnionRegion(M_REGION
, rectRegion
, M_REGION
); 
 238         case wxRGN_COPY
: // Don't have to do this one 
 247 //! Union /e region with this. 
 248 bool wxRegion::Combine(const wxRegion
& region
, wxRegionOp op
) 
 253     // Don't change shared data 
 255         m_refData 
= new wxRegionRefData(); 
 256     } else    if (m_refData
->GetRefCount() > 1) { 
 257         wxRegionRefData
* ref 
= (wxRegionRefData
*)m_refData
; 
 259         m_refData 
= new wxRegionRefData(*ref
); 
 265             XIntersectRegion(M_REGION
, ((wxRegionRefData
*)region
.m_refData
)->m_region
, 
 269             XUnionRegion(M_REGION
, ((wxRegionRefData
*)region
.m_refData
)->m_region
, 
 278         case wxRGN_COPY
: // Don't have to do this one 
 287 bool wxRegion::Combine(const wxRect
& rect
, wxRegionOp op
) 
 289     return Combine(rect
.GetLeft(), rect
.GetTop(), rect
.GetWidth(), rect
.GetHeight(), op
); 
 292 //----------------------------------------------------------------------------- 
 293 //# Information on region 
 294 //----------------------------------------------------------------------------- 
 296 // Outer bounds of region 
 297 void wxRegion::GetBox(wxCoord
& x
, wxCoord
& y
, wxCoord
&w
, wxCoord 
&h
) const 
 301         XClipBox(M_REGION
, &rect
); 
 311 wxRect 
wxRegion::GetBox() const 
 315     return wxRect(x
, y
, w
, h
); 
 319 bool wxRegion::Empty() const 
 321     return m_refData 
? XEmptyRegion(M_REGION
) : TRUE
; 
 324 //----------------------------------------------------------------------------- 
 326 //----------------------------------------------------------------------------- 
 328 // Does the region contain the point (x,y)? 
 329 wxRegionContain 
wxRegion::Contains(wxCoord 
WXUNUSED(x
), wxCoord 
WXUNUSED(y
)) const 
 334     // TODO. Return wxInRegion if within region. 
 340 // Does the region contain the point pt? 
 341 wxRegionContain 
wxRegion::Contains(const wxPoint
& pt
) const 
 346     return XPointInRegion(M_REGION
, pt
.x
, pt
.y
) ? wxInRegion 
: wxOutRegion
; 
 349 // Does the region contain the rectangle (x, y, w, h)? 
 350 wxRegionContain 
wxRegion::Contains(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const 
 355     switch (XRectInRegion(M_REGION
, x
, y
, w
, h
)) { 
 356         case RectangleIn
:    return wxInRegion
; 
 357         case RectanglePart
: return wxPartRegion
; 
 362 // Does the region contain the rectangle rect 
 363 wxRegionContain 
wxRegion::Contains(const wxRect
& rect
) const 
 372     h 
= rect
.GetHeight(); 
 373     return Contains(x
, y
, w
, h
); 
 376 bool wxRegion::UsingRects() const 
 378     return ((wxRegionRefData
*)m_refData
)->UsingRects(); 
 382 wxRectList& wxRegion::GetRectList() 
 384     return ((wxRegionRefData*)m_refData)->GetRectList(); 
 388 wxRect
* wxRegion::GetRects() 
 390     return ((wxRegionRefData
*)m_refData
)->GetRects(); 
 393 int wxRegion::GetRectCount() const 
 395     return ((wxRegionRefData
*)m_refData
)->GetRectCount(); 
 398 void wxRegion::SetRects(const wxRectList
& rectList
) 
 400     ((wxRegionRefData
*)m_refData
)->SetRects(rectList
); 
 403 void wxRegion::SetRects(int count
, const wxRect
* rects
) 
 405     ((wxRegionRefData
*)m_refData
)->SetRects(count
, rects
); 
 408 /////////////////////////////////////////////////////////////////////////////// 
 410 //                               wxRegionIterator                                 // 
 412 /////////////////////////////////////////////////////////////////////////////// 
 415  * Initialize empty iterator 
 417 wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL
) 
 421 wxRegionIterator::~wxRegionIterator() 
 428  * Initialize iterator for region 
 430 wxRegionIterator::wxRegionIterator(const wxRegion
& region
) 
 438  * Reset iterator for a new /e region. 
 440 void wxRegionIterator::Reset(const wxRegion
& region
) 
 450     if (m_region
.Empty()) 
 454         // Create m_rects and fill with rectangles for this region. 
 455         // Since we can't find the rectangles in a region, we cheat 
 456         // by retrieving the rectangles explicitly set in wxPaintDC::wxPaintDC 
 458         if (m_region
.UsingRects()) 
 460             wxRect
* rects 
= m_region
.GetRects(); 
 461             int count 
= m_region
.GetRectCount(); 
 463             m_rects 
= new wxRect
[m_numRects
]; 
 465             for (size_t i 
= 0; i 
< m_numRects
; i
++) 
 466                m_rects
[i
] = rects
[i
]; 
 470             wxRectList::Node* node = rectList.GetFirst(); 
 472                 wxRect* rect = node->GetData(); 
 474                 node = node->GetNext(); 
 481             // For now, fudge by getting the whole bounding box. 
 482             m_rects 
= new wxRect
[1]; 
 484             m_rects
[0] = m_region
.GetBox(); 
 490  * Increment iterator. The rectangle returned is the one after the 
 493 void wxRegionIterator::operator ++ () 
 495     if (m_current 
< m_numRects
) 
 500  * Increment iterator. The rectangle returned is the one before the 
 503 void wxRegionIterator::operator ++ (int) 
 505     if (m_current 
< m_numRects
) 
 509 wxCoord 
wxRegionIterator::GetX() const 
 511     if (m_current 
< m_numRects
) 
 512         return m_rects
[m_current
].x
; 
 516 wxCoord 
wxRegionIterator::GetY() const 
 518     if (m_current 
< m_numRects
) 
 519         return m_rects
[m_current
].y
; 
 523 wxCoord 
wxRegionIterator::GetW() const 
 525     if (m_current 
< m_numRects
) 
 526         return m_rects
[m_current
].width 
; 
 530 wxCoord 
wxRegionIterator::GetH() const 
 532     if (m_current 
< m_numRects
) 
 533         return m_rects
[m_current
].height
;