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
];
466 for (i
= 0; i
< m_numRects
; i
++)
467 m_rects
[i
] = rects
[i
];
471 wxRectList::Node* node = rectList.GetFirst();
473 wxRect* rect = node->GetData();
475 node = node->GetNext();
482 // For now, fudge by getting the whole bounding box.
483 m_rects
= new wxRect
[1];
485 m_rects
[0] = m_region
.GetBox();
491 * Increment iterator. The rectangle returned is the one after the
494 void wxRegionIterator::operator ++ ()
496 if (m_current
< m_numRects
)
501 * Increment iterator. The rectangle returned is the one before the
504 void wxRegionIterator::operator ++ (int)
506 if (m_current
< m_numRects
)
510 wxCoord
wxRegionIterator::GetX() const
512 if (m_current
< m_numRects
)
513 return m_rects
[m_current
].x
;
517 wxCoord
wxRegionIterator::GetY() const
519 if (m_current
< m_numRects
)
520 return m_rects
[m_current
].y
;
524 wxCoord
wxRegionIterator::GetW() const
526 if (m_current
< m_numRects
)
527 return m_rects
[m_current
].width
;
531 wxCoord
wxRegionIterator::GetH() const
533 if (m_current
< m_numRects
)
534 return m_rects
[m_current
].height
;