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 // #include "wx/motif/private.h"
21 #if !USE_SHARED_LIBRARY
22 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
)
23 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
, wxObject
)
26 // ----------------------------------------------------------------------------
28 // ----------------------------------------------------------------------------
30 #include "wx/listimpl.cpp"
32 WX_DEFINE_LIST(wxRectList
);
34 //-----------------------------------------------------------------------------
35 // wxRegionRefData implementation
36 //-----------------------------------------------------------------------------
38 class WXDLLEXPORT wxRegionRefData
: public wxGDIRefData
{
42 m_region
= XCreateRegion();
44 m_rects
= (wxRect
*) NULL
;
48 wxRegionRefData(const wxRegionRefData
& data
)
50 m_region
= XCreateRegion();
51 m_rects
= (wxRect
*) NULL
;
53 XUnionRegion(m_region
, data
.m_region
, m_region
);
55 SetRects(data
.m_rectCount
, data
.m_rects
);
60 XDestroyRegion(m_region
);
64 wxRect
* GetRects() { return m_rects
; };
65 void SetRects(const wxRectList
& rectList
);
66 void SetRects(int count
, const wxRect
* rects
);
67 bool UsingRects() const { return m_usingRects
; }
68 int GetRectCount() const { return m_rectCount
; }
75 bool m_usingRects
; // TRUE if we're using the above.
78 void wxRegionRefData::SetRects(const wxRectList
& rectList
)
81 m_usingRects
= (rectList
.Number() > 0);
84 m_rectCount
= rectList
.Number();
85 m_rects
= new wxRect
[m_rectCount
];
88 wxRectList::Node
* node
= rectList
.GetFirst();
91 wxRect
* rect
= node
->GetData();
93 node
= node
->GetNext();
98 void wxRegionRefData::SetRects(int count
, const wxRect
* rects
)
101 m_usingRects
= (count
> 0);
105 m_rects
= new wxRect
[m_rectCount
];
107 for (i
= 0; i
< m_rectCount
; i
++)
108 m_rects
[i
] = rects
[i
];
112 void wxRegionRefData::DeleteRects()
117 m_rects
= (wxRect
*) NULL
;
120 m_usingRects
= FALSE
;
123 #define M_REGION (((wxRegionRefData*)m_refData)->m_region)
125 //-----------------------------------------------------------------------------
127 //-----------------------------------------------------------------------------
130 * Create an empty region.
136 wxRegion::wxRegion(long x
, long y
, long w
, long h
)
138 m_refData
= new wxRegionRefData
;
145 XUnionRectWithRegion(&rect
, M_REGION
, M_REGION
);
148 wxRegion::wxRegion(const wxPoint
& topLeft
, const wxPoint
& bottomRight
)
150 m_refData
= new wxRegionRefData
;
155 rect
.width
= bottomRight
.x
- topLeft
.x
;
156 rect
.height
= bottomRight
.y
- topLeft
.y
;
157 XUnionRectWithRegion(&rect
, M_REGION
, M_REGION
);
160 wxRegion::wxRegion(const wxRect
& rect
)
162 m_refData
= new wxRegionRefData
;
167 rect1
.width
= rect
.width
;
168 rect1
.height
= rect
.height
;
169 XUnionRectWithRegion(&rect1
, M_REGION
, M_REGION
);
173 * Destroy the region.
175 wxRegion::~wxRegion()
177 // m_refData unrefed in ~wxObject
180 // Get the internal region handle
181 WXRegion
wxRegion::GetXRegion() const
183 wxASSERT( m_refData
!=NULL
);
185 return (WXRegion
) ((wxRegionRefData
*)m_refData
)->m_region
;
188 //-----------------------------------------------------------------------------
190 //-----------------------------------------------------------------------------
192 //! Clear current region
193 void wxRegion::Clear()
198 //! Combine rectangle (x, y, w, h) with this.
199 bool wxRegion::Combine(long x
, long y
, long width
, long height
, wxRegionOp op
)
201 // Don't change shared data
203 m_refData
= new wxRegionRefData();
204 } else if (m_refData
->GetRefCount() > 1) {
205 wxRegionRefData
* ref
= (wxRegionRefData
*)m_refData
;
207 m_refData
= new wxRegionRefData(*ref
);
209 // If ref count is 1, that means it's 'ours' anyway so no action.
211 Region rectRegion
= XCreateRegion();
217 rect
.height
= height
;
218 XUnionRectWithRegion(&rect
, rectRegion
, rectRegion
);
223 XIntersectRegion(M_REGION
, rectRegion
, M_REGION
);
226 XUnionRegion(M_REGION
, rectRegion
, M_REGION
);
234 case wxRGN_COPY
: // Don't have to do this one
243 //! Union /e region with this.
244 bool wxRegion::Combine(const wxRegion
& region
, wxRegionOp op
)
249 // Don't change shared data
251 m_refData
= new wxRegionRefData();
252 } else if (m_refData
->GetRefCount() > 1) {
253 wxRegionRefData
* ref
= (wxRegionRefData
*)m_refData
;
255 m_refData
= new wxRegionRefData(*ref
);
261 XIntersectRegion(M_REGION
, ((wxRegionRefData
*)region
.m_refData
)->m_region
,
265 XUnionRegion(M_REGION
, ((wxRegionRefData
*)region
.m_refData
)->m_region
,
274 case wxRGN_COPY
: // Don't have to do this one
283 bool wxRegion::Combine(const wxRect
& rect
, wxRegionOp op
)
285 return Combine(rect
.GetLeft(), rect
.GetTop(), rect
.GetWidth(), rect
.GetHeight(), op
);
288 //-----------------------------------------------------------------------------
289 //# Information on region
290 //-----------------------------------------------------------------------------
292 // Outer bounds of region
293 void wxRegion::GetBox(long& x
, long& y
, long&w
, long &h
) const
297 XClipBox(M_REGION
, &rect
);
307 wxRect
wxRegion::GetBox() const
311 return wxRect(x
, y
, w
, h
);
315 bool wxRegion::Empty() const
317 return m_refData
? XEmptyRegion(M_REGION
) : TRUE
;
320 //-----------------------------------------------------------------------------
322 //-----------------------------------------------------------------------------
324 // Does the region contain the point (x,y)?
325 wxRegionContain
wxRegion::Contains(long WXUNUSED(x
), long WXUNUSED(y
)) const
330 // TODO. Return wxInRegion if within region.
336 // Does the region contain the point pt?
337 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
342 return XPointInRegion(M_REGION
, pt
.x
, pt
.y
) ? wxInRegion
: wxOutRegion
;
345 // Does the region contain the rectangle (x, y, w, h)?
346 wxRegionContain
wxRegion::Contains(long x
, long y
, long w
, long h
) const
351 switch (XRectInRegion(M_REGION
, x
, y
, w
, h
)) {
352 case RectangleIn
: return wxInRegion
;
353 case RectanglePart
: return wxPartRegion
;
358 // Does the region contain the rectangle rect
359 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
368 h
= rect
.GetHeight();
369 return Contains(x
, y
, w
, h
);
372 bool wxRegion::UsingRects() const
374 return ((wxRegionRefData
*)m_refData
)->UsingRects();
378 wxRectList& wxRegion::GetRectList()
380 return ((wxRegionRefData*)m_refData)->GetRectList();
384 wxRect
* wxRegion::GetRects()
386 return ((wxRegionRefData
*)m_refData
)->GetRects();
389 int wxRegion::GetRectCount() const
391 return ((wxRegionRefData
*)m_refData
)->GetRectCount();
394 void wxRegion::SetRects(const wxRectList
& rectList
)
396 ((wxRegionRefData
*)m_refData
)->SetRects(rectList
);
399 void wxRegion::SetRects(int count
, const wxRect
* rects
)
401 ((wxRegionRefData
*)m_refData
)->SetRects(count
, rects
);
404 ///////////////////////////////////////////////////////////////////////////////
406 // wxRegionIterator //
408 ///////////////////////////////////////////////////////////////////////////////
411 * Initialize empty iterator
413 wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL
)
417 wxRegionIterator::~wxRegionIterator()
424 * Initialize iterator for region
426 wxRegionIterator::wxRegionIterator(const wxRegion
& region
)
434 * Reset iterator for a new /e region.
436 void wxRegionIterator::Reset(const wxRegion
& region
)
446 if (m_region
.Empty())
450 // Create m_rects and fill with rectangles for this region.
451 // Since we can't find the rectangles in a region, we cheat
452 // by retrieving the rectangles explicitly set in wxPaintDC::wxPaintDC
454 if (m_region
.UsingRects())
456 wxRect
* rects
= m_region
.GetRects();
457 int count
= m_region
.GetRectCount();
459 m_rects
= new wxRect
[m_numRects
];
462 for (i
= 0; i
< m_numRects
; i
++)
463 m_rects
[i
] = rects
[i
];
467 wxRectList::Node* node = rectList.GetFirst();
469 wxRect* rect = node->GetData();
471 node = node->GetNext();
478 // For now, fudge by getting the whole bounding box.
479 m_rects
= new wxRect
[1];
481 m_rects
[0] = m_region
.GetBox();
487 * Increment iterator. The rectangle returned is the one after the
490 void wxRegionIterator::operator ++ ()
492 if (m_current
< m_numRects
)
497 * Increment iterator. The rectangle returned is the one before the
500 void wxRegionIterator::operator ++ (int)
502 if (m_current
< m_numRects
)
506 long wxRegionIterator::GetX() const
508 if (m_current
< m_numRects
)
509 return m_rects
[m_current
].x
;
513 long wxRegionIterator::GetY() const
515 if (m_current
< m_numRects
)
516 return m_rects
[m_current
].y
;
520 long wxRegionIterator::GetW() const
522 if (m_current
< m_numRects
)
523 return m_rects
[m_current
].width
;
527 long wxRegionIterator::GetH() const
529 if (m_current
< m_numRects
)
530 return m_rects
[m_current
].height
;