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