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