]> git.saurik.com Git - wxWidgets.git/blame - src/mac/region.cpp
a base for geometry operations
[wxWidgets.git] / src / mac / region.cpp
CommitLineData
e9576ca5
SC
1/////////////////////////////////////////////////////////////////////////////
2// File: region.cpp
3// Purpose: Region class
4// Author: Markus Holzem/Julian Smart/AUTHOR
5// Created: Fri Oct 24 10:46:34 MET 1997
6// RCS-ID: $Id$
7// Copyright: (c) 1997 Markus Holzem/Julian Smart/AUTHOR
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11#ifdef __GNUG__
12#pragma implementation "region.h"
13#endif
14
15#include "wx/region.h"
16#include "wx/gdicmn.h"
17
e9576ca5
SC
18 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
19 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
e9576ca5
SC
20
21//-----------------------------------------------------------------------------
22// wxRegionRefData implementation
23//-----------------------------------------------------------------------------
24
25class WXDLLEXPORT wxRegionRefData : public wxGDIRefData {
26public:
27 wxRegionRefData()
28 {
519cb848 29 m_macRgn = NewRgn() ;
e9576ca5
SC
30 }
31
32 wxRegionRefData(const wxRegionRefData& data)
33 {
519cb848
SC
34 m_macRgn = NewRgn() ;
35 CopyRgn( data.m_macRgn , m_macRgn ) ;
e9576ca5
SC
36 }
37
38 ~wxRegionRefData()
39 {
519cb848 40 DisposeRgn( m_macRgn ) ;
e9576ca5 41 }
519cb848 42 RgnHandle m_macRgn ;
e9576ca5
SC
43};
44
519cb848
SC
45#define M_REGION (((wxRegionRefData*)m_refData)->m_macRgn)
46#define OTHER_M_REGION(a) (((wxRegionRefData*)(a.m_refData))->m_macRgn)
e9576ca5
SC
47
48//-----------------------------------------------------------------------------
49// wxRegion
50//-----------------------------------------------------------------------------
51
52/*!
53 * Create an empty region.
54 */
55wxRegion::wxRegion()
56{
57 m_refData = new wxRegionRefData;
519cb848
SC
58}
59
60wxRegion::wxRegion(WXHRGN hRegion )
61{
62 m_refData = new wxRegionRefData;
63 CopyRgn( hRegion , M_REGION ) ;
e9576ca5
SC
64}
65
66wxRegion::wxRegion(long x, long y, long w, long h)
67{
68 m_refData = new wxRegionRefData;
519cb848 69 SetRectRgn( M_REGION , x , y , x+w , y+h ) ;
e9576ca5
SC
70}
71
72wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
73{
74 m_refData = new wxRegionRefData;
519cb848 75 SetRectRgn( M_REGION , topLeft.x , topLeft.y , bottomRight.x , bottomRight.y ) ;
e9576ca5
SC
76}
77
78wxRegion::wxRegion(const wxRect& rect)
79{
80 m_refData = new wxRegionRefData;
519cb848 81 SetRectRgn( M_REGION , rect.x , rect.y , rect.x+rect.width , rect.y+rect.height ) ;
e9576ca5
SC
82}
83
84/*!
85 * Destroy the region.
86 */
87wxRegion::~wxRegion()
88{
89 // m_refData unrefed in ~wxObject
90}
91
92//-----------------------------------------------------------------------------
93//# Modify region
94//-----------------------------------------------------------------------------
95
96//! Clear current region
97void wxRegion::Clear()
98{
99 UnRef();
100}
101
102//! Combine rectangle (x, y, w, h) with this.
103bool wxRegion::Combine(long x, long y, long width, long height, wxRegionOp op)
104{
105 // Don't change shared data
519cb848
SC
106 if (!m_refData)
107 {
e9576ca5 108 m_refData = new wxRegionRefData();
519cb848
SC
109 }
110 else if (m_refData->GetRefCount() > 1)
111 {
e9576ca5
SC
112 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
113 UnRef();
114 m_refData = new wxRegionRefData(*ref);
115 }
519cb848
SC
116 RgnHandle rgn = NewRgn() ;
117 SetRectRgn( rgn , x , y, x+width,y + height ) ;
118
e9576ca5
SC
119 switch (op)
120 {
121 case wxRGN_AND:
519cb848 122 SectRgn( M_REGION , rgn , M_REGION ) ;
e9576ca5
SC
123 break ;
124 case wxRGN_OR:
519cb848 125 UnionRgn( M_REGION , rgn , M_REGION ) ;
e9576ca5
SC
126 break ;
127 case wxRGN_XOR:
519cb848 128 XorRgn( M_REGION , rgn , M_REGION ) ;
e9576ca5
SC
129 break ;
130 case wxRGN_DIFF:
519cb848 131 DiffRgn( M_REGION , rgn , M_REGION ) ;
e9576ca5
SC
132 break ;
133 case wxRGN_COPY:
134 default:
519cb848 135 CopyRgn( rgn ,M_REGION ) ;
e9576ca5
SC
136 break ;
137 }
138
519cb848 139 DisposeRgn( rgn ) ;
e9576ca5 140
519cb848 141 return TRUE;
e9576ca5
SC
142}
143
144//! Union /e region with this.
145bool wxRegion::Combine(const wxRegion& region, wxRegionOp op)
146{
147 if (region.Empty())
148 return FALSE;
149
150 // Don't change shared data
151 if (!m_refData) {
152 m_refData = new wxRegionRefData();
519cb848
SC
153 }
154 else if (m_refData->GetRefCount() > 1)
155 {
e9576ca5
SC
156 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
157 UnRef();
158 m_refData = new wxRegionRefData(*ref);
159 }
160
e9576ca5
SC
161 switch (op)
162 {
163 case wxRGN_AND:
519cb848 164 SectRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
e9576ca5
SC
165 break ;
166 case wxRGN_OR:
519cb848 167 UnionRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
e9576ca5
SC
168 break ;
169 case wxRGN_XOR:
519cb848 170 XorRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
e9576ca5
SC
171 break ;
172 case wxRGN_DIFF:
519cb848 173 DiffRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
e9576ca5
SC
174 break ;
175 case wxRGN_COPY:
176 default:
519cb848 177 CopyRgn( OTHER_M_REGION(region) ,M_REGION ) ;
e9576ca5
SC
178 break ;
179 }
180
519cb848 181 return TRUE;
e9576ca5
SC
182}
183
184bool wxRegion::Combine(const wxRect& rect, wxRegionOp op)
185{
186 return Combine(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight(), op);
187}
188
189//-----------------------------------------------------------------------------
190//# Information on region
191//-----------------------------------------------------------------------------
192
193// Outer bounds of region
194void wxRegion::GetBox(long& x, long& y, long&w, long &h) const
195{
519cb848
SC
196 if (m_refData)
197 {
198 Rect box = (**M_REGION).rgnBBox ;
199 x = box.left ;
200 y = box.top ;
201 w = box.right - box.left ;
202 h = box.bottom - box.top ;
203 }
204 else
205 {
e9576ca5
SC
206 x = y = w = h = 0;
207 }
208}
209
210wxRect wxRegion::GetBox() const
211{
212 long x, y, w, h;
213 GetBox(x, y, w, h);
214 return wxRect(x, y, w, h);
215}
216
217// Is region empty?
218bool wxRegion::Empty() const
219{
519cb848
SC
220 return EmptyRgn( M_REGION ) ;
221}
222
223const WXHRGN wxRegion::GetWXHRGN() const
224{
225 return M_REGION ;
e9576ca5
SC
226}
227
228//-----------------------------------------------------------------------------
229//# Tests
230//-----------------------------------------------------------------------------
231
232// Does the region contain the point (x,y)?
233wxRegionContain wxRegion::Contains(long x, long y) const
234{
235 if (!m_refData)
236 return wxOutRegion;
237
238 // TODO. Return wxInRegion if within region.
239 if (0)
240 return wxInRegion;
241 return wxOutRegion;
242}
243
244// Does the region contain the point pt?
245wxRegionContain wxRegion::Contains(const wxPoint& pt) const
246{
247 if (!m_refData)
248 return wxOutRegion;
249
519cb848
SC
250 Point p = { pt.y , pt.x } ;
251 if (PtInRgn( p , M_REGION ) )
e9576ca5 252 return wxInRegion;
519cb848
SC
253
254 return wxOutRegion;
e9576ca5
SC
255}
256
257// Does the region contain the rectangle (x, y, w, h)?
258wxRegionContain wxRegion::Contains(long x, long y, long w, long h) const
259{
260 if (!m_refData)
261 return wxOutRegion;
262
519cb848
SC
263 Rect rect = { y , x , y + h , x + w } ;
264 if (RectInRgn( &rect , M_REGION ) )
e9576ca5
SC
265 return wxInRegion;
266 else
267 return wxOutRegion;
268}
269
270// Does the region contain the rectangle rect
271wxRegionContain wxRegion::Contains(const wxRect& rect) const
272{
273 if (!m_refData)
274 return wxOutRegion;
275
276 long x, y, w, h;
277 x = rect.x;
278 y = rect.y;
279 w = rect.GetWidth();
280 h = rect.GetHeight();
281 return Contains(x, y, w, h);
282}
283
284///////////////////////////////////////////////////////////////////////////////
285// //
286// wxRegionIterator //
287// //
288///////////////////////////////////////////////////////////////////////////////
289
290/*!
291 * Initialize empty iterator
292 */
293wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL)
294{
295}
296
297wxRegionIterator::~wxRegionIterator()
298{
299 if (m_rects)
300 delete[] m_rects;
301}
302
303/*!
304 * Initialize iterator for region
305 */
306wxRegionIterator::wxRegionIterator(const wxRegion& region)
307{
308 m_rects = NULL;
309
310 Reset(region);
311}
312
313/*!
314 * Reset iterator for a new /e region.
315 */
316void wxRegionIterator::Reset(const wxRegion& region)
317{
318 m_current = 0;
319 m_region = region;
320
321 if (m_rects)
322 delete[] m_rects;
323
324 m_rects = NULL;
325
326 if (m_region.Empty())
327 m_numRects = 0;
328 else
329 {
519cb848
SC
330 // we cannot dissolve it into rects on mac
331 m_rects = new wxRect[1];
332 Rect rect = (**OTHER_M_REGION( region )).rgnBBox ;
333 m_rects[0].x = rect.left;
334 m_rects[0].y = rect.top;
335 m_rects[0].width = rect.right - rect.left;
336 m_rects[0].height = rect.bottom - rect.top;
337 m_numRects = 1;
e9576ca5
SC
338 }
339}
340
341/*!
342 * Increment iterator. The rectangle returned is the one after the
343 * incrementation.
344 */
345void wxRegionIterator::operator ++ ()
346{
347 if (m_current < m_numRects)
348 ++m_current;
349}
350
351/*!
352 * Increment iterator. The rectangle returned is the one before the
353 * incrementation.
354 */
355void wxRegionIterator::operator ++ (int)
356{
357 if (m_current < m_numRects)
358 ++m_current;
359}
360
361long wxRegionIterator::GetX() const
362{
363 if (m_current < m_numRects)
364 return m_rects[m_current].x;
365 return 0;
366}
367
368long wxRegionIterator::GetY() const
369{
370 if (m_current < m_numRects)
371 return m_rects[m_current].y;
372 return 0;
373}
374
375long wxRegionIterator::GetW() const
376{
377 if (m_current < m_numRects)
378 return m_rects[m_current].width ;
379 return 0;
380}
381
382long wxRegionIterator::GetH() const
383{
384 if (m_current < m_numRects)
385 return m_rects[m_current].height;
386 return 0;
387}
388