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"
17 #include "wx/window.h"
20 #pragma message disable nosimpint
22 #include "wx/x11/private.h"
23 #include "X11/Xutil.h"
25 #pragma message enable nosimpint
29 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
)
30 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
, wxObject
)
32 // ----------------------------------------------------------------------------
34 // ----------------------------------------------------------------------------
36 #include "wx/listimpl.cpp"
38 WX_DEFINE_LIST(wxRectList
);
40 //-----------------------------------------------------------------------------
41 // wxRegionRefData implementation
42 //-----------------------------------------------------------------------------
44 class WXDLLEXPORT wxRegionRefData
: public wxGDIRefData
{
48 m_region
= XCreateRegion();
50 m_rects
= (wxRect
*) NULL
;
54 wxRegionRefData(const wxRegionRefData
& data
)
56 m_region
= XCreateRegion();
57 m_rects
= (wxRect
*) NULL
;
59 XUnionRegion(m_region
, data
.m_region
, m_region
);
61 SetRects(data
.m_rectCount
, data
.m_rects
);
66 XDestroyRegion(m_region
);
70 wxRect
* GetRects() { return m_rects
; };
71 void SetRects(const wxRectList
& rectList
);
72 void SetRects(int count
, const wxRect
* rects
);
73 bool UsingRects() const { return m_usingRects
; }
74 int GetRectCount() const { return m_rectCount
; }
81 bool m_usingRects
; // TRUE if we're using the above.
84 void wxRegionRefData::SetRects(const wxRectList
& rectList
)
87 m_usingRects
= (rectList
.Number() > 0);
90 m_rectCount
= rectList
.Number();
91 m_rects
= new wxRect
[m_rectCount
];
94 wxRectList::Node
* node
= rectList
.GetFirst();
97 wxRect
* rect
= node
->GetData();
99 node
= node
->GetNext();
104 void wxRegionRefData::SetRects(int count
, const wxRect
* rects
)
107 m_usingRects
= (count
> 0);
111 m_rects
= new wxRect
[m_rectCount
];
113 for (i
= 0; i
< m_rectCount
; i
++)
114 m_rects
[i
] = rects
[i
];
118 void wxRegionRefData::DeleteRects()
123 m_rects
= (wxRect
*) NULL
;
126 m_usingRects
= FALSE
;
129 #define M_REGION (((wxRegionRefData*)m_refData)->m_region)
131 //-----------------------------------------------------------------------------
133 //-----------------------------------------------------------------------------
136 * Create an empty region.
142 wxRegion::wxRegion(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
144 m_refData
= new wxRegionRefData
;
151 XUnionRectWithRegion(&rect
, M_REGION
, M_REGION
);
154 wxRegion::wxRegion(const wxPoint
& topLeft
, const wxPoint
& bottomRight
)
156 m_refData
= new wxRegionRefData
;
161 rect
.width
= bottomRight
.x
- topLeft
.x
;
162 rect
.height
= bottomRight
.y
- topLeft
.y
;
163 XUnionRectWithRegion(&rect
, M_REGION
, M_REGION
);
166 wxRegion::wxRegion(const wxRect
& rect
)
168 m_refData
= new wxRegionRefData
;
173 rect1
.width
= rect
.width
;
174 rect1
.height
= rect
.height
;
175 XUnionRectWithRegion(&rect1
, M_REGION
, M_REGION
);
179 * Destroy the region.
181 wxRegion::~wxRegion()
183 // m_refData unrefed in ~wxObject
186 // Get the internal region handle
187 WXRegion
wxRegion::GetXRegion() const
189 wxASSERT( m_refData
!=NULL
);
191 return (WXRegion
) ((wxRegionRefData
*)m_refData
)->m_region
;
194 //-----------------------------------------------------------------------------
196 //-----------------------------------------------------------------------------
198 //! Clear current region
199 void wxRegion::Clear()
204 //! Combine rectangle (x, y, w, h) with this.
205 bool wxRegion::Combine(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, wxRegionOp op
)
207 // Don't change shared data
209 m_refData
= new wxRegionRefData();
210 } else if (m_refData
->GetRefCount() > 1) {
211 wxRegionRefData
* ref
= (wxRegionRefData
*)m_refData
;
213 m_refData
= new wxRegionRefData(*ref
);
215 // If ref count is 1, that means it's 'ours' anyway so no action.
217 Region rectRegion
= XCreateRegion();
223 rect
.height
= height
;
224 XUnionRectWithRegion(&rect
, rectRegion
, rectRegion
);
229 XIntersectRegion(M_REGION
, rectRegion
, M_REGION
);
232 XUnionRegion(M_REGION
, rectRegion
, M_REGION
);
240 case wxRGN_COPY
: // Don't have to do this one
249 //! Union /e region with this.
250 bool wxRegion::Combine(const wxRegion
& region
, wxRegionOp op
)
255 // Don't change shared data
257 m_refData
= new wxRegionRefData();
258 } else if (m_refData
->GetRefCount() > 1) {
259 wxRegionRefData
* ref
= (wxRegionRefData
*)m_refData
;
261 m_refData
= new wxRegionRefData(*ref
);
267 XIntersectRegion(M_REGION
, ((wxRegionRefData
*)region
.m_refData
)->m_region
,
271 XUnionRegion(M_REGION
, ((wxRegionRefData
*)region
.m_refData
)->m_region
,
280 case wxRGN_COPY
: // Don't have to do this one
289 bool wxRegion::Combine(const wxRect
& rect
, wxRegionOp op
)
291 return Combine(rect
.GetLeft(), rect
.GetTop(), rect
.GetWidth(), rect
.GetHeight(), op
);
294 //-----------------------------------------------------------------------------
295 //# Information on region
296 //-----------------------------------------------------------------------------
298 // Outer bounds of region
299 void wxRegion::GetBox(wxCoord
& x
, wxCoord
& y
, wxCoord
&w
, wxCoord
&h
) const
303 XClipBox(M_REGION
, &rect
);
313 wxRect
wxRegion::GetBox() const
317 return wxRect(x
, y
, w
, h
);
321 bool wxRegion::Empty() const
323 return m_refData
? XEmptyRegion(M_REGION
) : TRUE
;
326 //-----------------------------------------------------------------------------
328 //-----------------------------------------------------------------------------
330 // Does the region contain the point (x,y)?
331 wxRegionContain
wxRegion::Contains(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
)) const
336 // TODO. Return wxInRegion if within region.
342 // Does the region contain the point pt?
343 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
348 return XPointInRegion(M_REGION
, pt
.x
, pt
.y
) ? wxInRegion
: wxOutRegion
;
351 // Does the region contain the rectangle (x, y, w, h)?
352 wxRegionContain
wxRegion::Contains(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
357 switch (XRectInRegion(M_REGION
, x
, y
, w
, h
)) {
358 case RectangleIn
: return wxInRegion
;
359 case RectanglePart
: return wxPartRegion
;
364 // Does the region contain the rectangle rect
365 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
374 h
= rect
.GetHeight();
375 return Contains(x
, y
, w
, h
);
378 bool wxRegion::UsingRects() const
380 return ((wxRegionRefData
*)m_refData
)->UsingRects();
384 wxRectList& wxRegion::GetRectList()
386 return ((wxRegionRefData*)m_refData)->GetRectList();
390 wxRect
* wxRegion::GetRects()
392 return ((wxRegionRefData
*)m_refData
)->GetRects();
395 int wxRegion::GetRectCount() const
397 return ((wxRegionRefData
*)m_refData
)->GetRectCount();
400 void wxRegion::SetRects(const wxRectList
& rectList
)
402 ((wxRegionRefData
*)m_refData
)->SetRects(rectList
);
405 void wxRegion::SetRects(int count
, const wxRect
* rects
)
407 ((wxRegionRefData
*)m_refData
)->SetRects(count
, rects
);
410 ///////////////////////////////////////////////////////////////////////////////
412 // wxRegionIterator //
414 ///////////////////////////////////////////////////////////////////////////////
417 * Initialize empty iterator
419 wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL
)
423 wxRegionIterator::~wxRegionIterator()
430 * Initialize iterator for region
432 wxRegionIterator::wxRegionIterator(const wxRegion
& region
)
440 * Reset iterator for a new /e region.
442 void wxRegionIterator::Reset(const wxRegion
& region
)
452 if (m_region
.Empty())
456 // Create m_rects and fill with rectangles for this region.
457 // Since we can't find the rectangles in a region, we cheat
458 // by retrieving the rectangles explicitly set in wxPaintDC::wxPaintDC
460 if (m_region
.UsingRects())
462 wxRect
* rects
= m_region
.GetRects();
463 int count
= m_region
.GetRectCount();
465 m_rects
= new wxRect
[m_numRects
];
467 for (size_t i
= 0; i
< m_numRects
; i
++)
468 m_rects
[i
] = rects
[i
];
472 wxRectList::Node* node = rectList.GetFirst();
474 wxRect* rect = node->GetData();
476 node = node->GetNext();
483 // For now, fudge by getting the whole bounding box.
484 m_rects
= new wxRect
[1];
486 m_rects
[0] = m_region
.GetBox();
492 * Increment iterator. The rectangle returned is the one after the
495 void wxRegionIterator::operator ++ ()
497 if (m_current
< m_numRects
)
502 * Increment iterator. The rectangle returned is the one before the
505 void wxRegionIterator::operator ++ (int)
507 if (m_current
< m_numRects
)
511 wxCoord
wxRegionIterator::GetX() const
513 if (m_current
< m_numRects
)
514 return m_rects
[m_current
].x
;
518 wxCoord
wxRegionIterator::GetY() const
520 if (m_current
< m_numRects
)
521 return m_rects
[m_current
].y
;
525 wxCoord
wxRegionIterator::GetW() const
527 if (m_current
< m_numRects
)
528 return m_rects
[m_current
].width
;
532 wxCoord
wxRegionIterator::GetH() const
534 if (m_current
< m_numRects
)
535 return m_rects
[m_current
].height
;