]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/mac/carbon/region.cpp
use unsigned for display count
[wxWidgets.git] / src / mac / carbon / region.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// File: src/mac/carbon/region.cpp
3// Purpose: Region class
4// Author: Stefan Csomor
5// Created: Fri Oct 24 10:46:34 MET 1997
6// RCS-ID: $Id$
7// Copyright: (c) 1997 Stefan Csomor
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11#include "wx/wxprec.h"
12
13#include "wx/region.h"
14
15#ifndef WX_PRECOMP
16 #include "wx/gdicmn.h"
17#endif
18
19#include "wx/mac/uma.h"
20
21IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
22IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
23
24//-----------------------------------------------------------------------------
25// wxRegionRefData implementation
26//-----------------------------------------------------------------------------
27
28class WXDLLEXPORT wxRegionRefData : public wxGDIRefData
29{
30public:
31 wxRegionRefData()
32 { m_macRgn = NewRgn(); }
33
34 wxRegionRefData(const wxRegionRefData& data)
35 : wxGDIRefData()
36 {
37 m_macRgn = NewRgn();
38 CopyRgn( data.m_macRgn , m_macRgn );
39 }
40
41 virtual ~wxRegionRefData()
42 { DisposeRgn( m_macRgn ); }
43
44 RgnHandle m_macRgn;
45};
46
47#define M_REGION (((wxRegionRefData*)m_refData)->m_macRgn)
48#define OTHER_M_REGION(a) (((wxRegionRefData*)(a.m_refData))->m_macRgn)
49
50//-----------------------------------------------------------------------------
51// wxRegion
52//-----------------------------------------------------------------------------
53
54/*!
55 * Create an empty region.
56 */
57wxRegion::wxRegion()
58{
59 m_refData = new wxRegionRefData;
60}
61
62wxRegion::wxRegion(WXHRGN hRegion )
63{
64 m_refData = new wxRegionRefData;
65 CopyRgn( (RgnHandle) hRegion , (RgnHandle) M_REGION ) ;
66}
67
68wxRegion::wxRegion(long x, long y, long w, long h)
69{
70 m_refData = new wxRegionRefData;
71 SetRectRgn( (RgnHandle) M_REGION , x , y , x + w , y + h ) ;
72}
73
74wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
75{
76 m_refData = new wxRegionRefData;
77 SetRectRgn( (RgnHandle) M_REGION , topLeft.x , topLeft.y , bottomRight.x , bottomRight.y ) ;
78}
79
80wxRegion::wxRegion(const wxRect& rect)
81{
82 m_refData = new wxRegionRefData;
83 SetRectRgn( (RgnHandle) M_REGION , rect.x , rect.y , rect.x + rect.width , rect.y + rect.height ) ;
84}
85
86wxRegion::wxRegion(size_t n, const wxPoint *points, int WXUNUSED(fillStyle))
87{
88 m_refData = new wxRegionRefData;
89
90 // OS X somehow does not collect the region invisibly as before, so sometimes things
91 // get drawn on screen instead of just being combined into a region, therefore we allocate a temp gworld now
92
93 GWorldPtr gWorld = NULL;
94 GWorldPtr oldWorld;
95 GDHandle oldGDHandle;
96 OSStatus err;
97 Rect destRect = { 0, 0, 1, 1 };
98
99 ::GetGWorld( &oldWorld, &oldGDHandle );
100 err = ::NewGWorld( &gWorld, 32, &destRect, NULL, NULL, 0 );
101 if ( err == noErr )
102 {
103 ::SetGWorld( gWorld, GetGDevice() );
104
105 OpenRgn();
106
107 wxCoord x1, x2 , y1 , y2 ;
108 x2 = x1 = points[0].x ;
109 y2 = y1 = points[0].y ;
110
111 ::MoveTo( x1, y1 );
112 for (size_t i = 1; i < n; i++)
113 {
114 x2 = points[i].x ;
115 y2 = points[i].y ;
116 ::LineTo( x2, y2 );
117 }
118
119 // close the polyline if necessary
120 if ( x1 != x2 || y1 != y2 )
121 ::LineTo( x1, y1 ) ;
122
123 CloseRgn( M_REGION ) ;
124
125 ::SetGWorld( oldWorld, oldGDHandle );
126 }
127}
128
129wxRegion::~wxRegion()
130{
131 // m_refData unrefed in ~wxObject
132}
133
134//-----------------------------------------------------------------------------
135//# Modify region
136//-----------------------------------------------------------------------------
137
138//! Clear current region
139void wxRegion::Clear()
140{
141 UnRef();
142}
143
144// Move the region
145bool wxRegion::DoOffset(wxCoord x, wxCoord y)
146{
147 wxCHECK_MSG( M_REGION, false, _T("invalid wxRegion") );
148
149 if ( !x && !y )
150 // nothing to do
151 return true;
152
153 OffsetRgn( M_REGION , x , y ) ;
154
155 return true ;
156}
157
158
159//! Union /e region with this.
160bool wxRegion::DoCombine(const wxRegion& region, wxRegionOp op)
161{
162 wxCHECK_MSG( region.Ok(), false, _T("invalid wxRegion") );
163
164 // Don't change shared data
165 if (!m_refData)
166 {
167 m_refData = new wxRegionRefData();
168 }
169 else if (m_refData->GetRefCount() > 1)
170 {
171 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
172 UnRef();
173 m_refData = new wxRegionRefData(*ref);
174 }
175
176 switch (op)
177 {
178 case wxRGN_AND:
179 SectRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
180 break ;
181
182 case wxRGN_OR:
183 UnionRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
184 break ;
185
186 case wxRGN_XOR:
187 XorRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
188 break ;
189
190 case wxRGN_DIFF:
191 DiffRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
192 break ;
193
194 case wxRGN_COPY:
195 default:
196 CopyRgn( OTHER_M_REGION(region) , M_REGION ) ;
197 break ;
198 }
199
200 return true;
201}
202
203//-----------------------------------------------------------------------------
204//# Information on region
205//-----------------------------------------------------------------------------
206
207bool wxRegion::DoIsEqual(const wxRegion& region) const
208{
209 wxFAIL_MSG( _T("not implemented") );
210
211 return false;
212}
213
214// Outer bounds of region
215bool wxRegion::DoGetBox(wxCoord& x, wxCoord& y, wxCoord& w, wxCoord& h) const
216{
217 if (m_refData)
218 {
219 Rect box ;
220 GetRegionBounds( M_REGION , &box ) ;
221 x = box.left ;
222 y = box.top ;
223 w = box.right - box.left ;
224 h = box.bottom - box.top ;
225
226 return true;
227 }
228 else
229 {
230 x = y = w = h = 0;
231
232 return false;
233 }
234}
235
236// Is region empty?
237bool wxRegion::IsEmpty() const
238{
239 if ( m_refData )
240 return EmptyRgn( M_REGION ) ;
241 else
242 return true ;
243}
244
245const WXHRGN wxRegion::GetWXHRGN() const
246{
247 return M_REGION ;
248}
249
250//-----------------------------------------------------------------------------
251//# Tests
252//-----------------------------------------------------------------------------
253
254// Does the region contain the point?
255wxRegionContain wxRegion::DoContainsPoint(wxCoord x, wxCoord y) const
256{
257 if (!m_refData)
258 return wxOutRegion;
259
260 Point p = { y , x } ;
261 if (PtInRgn( p , M_REGION ) )
262 return wxInRegion;
263
264 return wxOutRegion;
265}
266
267// Does the region contain the rectangle (x, y, w, h)?
268wxRegionContain wxRegion::DoContainsRect(const wxRect& r) const
269{
270 if (!m_refData)
271 return wxOutRegion;
272
273 Rect rect = { r.y , r.x , r.y + r.height , r.x + r.width } ;
274 if (RectInRgn( &rect , M_REGION ) )
275 return wxInRegion;
276 else
277 return wxOutRegion;
278}
279
280///////////////////////////////////////////////////////////////////////////////
281// //
282// wxRegionIterator //
283// //
284///////////////////////////////////////////////////////////////////////////////
285
286/*!
287 * Initialize empty iterator
288 */
289wxRegionIterator::wxRegionIterator()
290 : m_current(0), m_numRects(0), m_rects(NULL)
291{
292}
293
294wxRegionIterator::~wxRegionIterator()
295{
296 if (m_rects)
297 {
298 delete [] m_rects;
299 m_rects = NULL;
300 }
301}
302
303wxRegionIterator::wxRegionIterator(const wxRegionIterator& iterator)
304 : wxObject()
305 , m_current(iterator.m_current)
306 , m_numRects(0)
307 , m_rects(NULL)
308{
309 SetRects(iterator.m_numRects, iterator.m_rects);
310}
311
312wxRegionIterator& wxRegionIterator::operator=(const wxRegionIterator& iterator)
313{
314 m_current = iterator.m_current;
315 SetRects(iterator.m_numRects, iterator.m_rects);
316
317 return *this;
318}
319
320/*!
321 * Set iterator rects for region
322 */
323void wxRegionIterator::SetRects(long numRects, wxRect *rects)
324{
325 if (m_rects)
326 {
327 delete [] m_rects;
328 m_rects = NULL;
329 }
330
331 if (rects && (numRects > 0))
332 {
333 int i;
334
335 m_rects = new wxRect[numRects];
336 for (i = 0; i < numRects; i++)
337 m_rects[i] = rects[i];
338 }
339
340 m_numRects = numRects;
341}
342
343/*!
344 * Initialize iterator for region
345 */
346wxRegionIterator::wxRegionIterator(const wxRegion& region)
347{
348 m_rects = NULL;
349
350 Reset(region);
351}
352
353/*!
354 * Reset iterator for a new /e region.
355 */
356
357OSStatus wxMacRegionToRectsCounterCallback(
358 UInt16 message, RgnHandle region, const Rect *rect, void *data )
359{
360 long *m_numRects = (long*) data ;
361 if ( message == kQDRegionToRectsMsgInit )
362 {
363 (*m_numRects) = 0 ;
364 }
365 else if (message == kQDRegionToRectsMsgParse)
366 {
367 (*m_numRects) += 1 ;
368 }
369
370 return noErr;
371}
372
373class RegionToRectsCallbackData
374{
375public :
376 wxRect* m_rects ;
377 long m_current ;
378};
379
380OSStatus wxMacRegionToRectsSetterCallback(
381 UInt16 message, RgnHandle region, const Rect *rect, void *data )
382{
383 if (message == kQDRegionToRectsMsgParse)
384 {
385 RegionToRectsCallbackData *cb = (RegionToRectsCallbackData*) data ;
386 cb->m_rects[cb->m_current++] = wxRect( rect->left , rect->top , rect->right - rect->left , rect->bottom - rect->top ) ;
387 }
388
389 return noErr;
390}
391
392void wxRegionIterator::Reset(const wxRegion& region)
393{
394 m_current = 0;
395 m_region = region;
396
397 if (m_rects)
398 {
399 delete [] m_rects;
400 m_rects = NULL;
401 }
402
403 if (m_region.IsEmpty())
404 {
405 m_numRects = 0;
406 }
407 else
408 {
409 RegionToRectsUPP proc = NewRegionToRectsUPP( wxMacRegionToRectsCounterCallback );
410
411 OSStatus err = noErr;
412 err = QDRegionToRects (OTHER_M_REGION( region ) , kQDParseRegionFromTopLeft, proc, (void*)&m_numRects);
413 if (err == noErr)
414 {
415 DisposeRegionToRectsUPP (proc);
416 proc = NewRegionToRectsUPP (wxMacRegionToRectsSetterCallback);
417 m_rects = new wxRect[m_numRects];
418 RegionToRectsCallbackData data ;
419 data.m_rects = m_rects ;
420 data.m_current = 0 ;
421 QDRegionToRects( OTHER_M_REGION( region ) , kQDParseRegionFromTopLeft, proc, (void*)&data );
422 }
423 else
424 {
425 m_numRects = 0;
426 }
427
428 DisposeRegionToRectsUPP( proc );
429 }
430}
431
432/*!
433 * Increment iterator. The rectangle returned is the one after the
434 * incrementation.
435 */
436wxRegionIterator& wxRegionIterator::operator ++ ()
437{
438 if (m_current < m_numRects)
439 ++m_current;
440
441 return *this;
442}
443
444/*!
445 * Increment iterator. The rectangle returned is the one before the
446 * incrementation.
447 */
448wxRegionIterator wxRegionIterator::operator ++ (int)
449{
450 wxRegionIterator previous(*this);
451
452 if (m_current < m_numRects)
453 ++m_current;
454
455 return previous;
456}
457
458long wxRegionIterator::GetX() const
459{
460 if (m_current < m_numRects)
461 return m_rects[m_current].x;
462
463 return 0;
464}
465
466long wxRegionIterator::GetY() const
467{
468 if (m_current < m_numRects)
469 return m_rects[m_current].y;
470
471 return 0;
472}
473
474long wxRegionIterator::GetW() const
475{
476 if (m_current < m_numRects)
477 return m_rects[m_current].width ;
478
479 return 0;
480}
481
482long wxRegionIterator::GetH() const
483{
484 if (m_current < m_numRects)
485 return m_rects[m_current].height;
486
487 return 0;
488}