]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/region.cpp
Fixed incorrect clipping region on wxGTK
[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
11#ifdef __GNUG__
12#pragma implementation "region.h"
13#endif
14
15#include "wx/region.h"
16#include "wx/gdicmn.h"
2f1ae414 17#include "wx/mac/uma.h"
e9576ca5 18
2f1ae414 19#if !USE_SHARED_LIBRARY
e40298d5
JS
20 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
21 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
2f1ae414 22#endif
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
92 OpenRgn();
93
94 wxCoord x1, x2 , y1 , y2 ;
95 x2 = x1 = points[0].x ;
96 y2 = y1 = points[0].y ;
97 ::MoveTo(x1,y1);
9156f27c 98 for (size_t i = 1; i < n; i++)
564cb9de
SC
99 {
100 x2 = points[i].x ;
101 y2 = points[i].y ;
102 ::LineTo(x2, y2);
103 }
104 // close the polyline if necessary
105 if ( x1 != x2 || y1 != y2 )
106 {
107 ::LineTo(x1,y1 ) ;
108 }
109 ClosePoly();
110 CloseRgn( M_REGION ) ;
111}
112
e9576ca5
SC
113/*!
114 * Destroy the region.
115 */
116wxRegion::~wxRegion()
117{
118 // m_refData unrefed in ~wxObject
119}
120
121//-----------------------------------------------------------------------------
122//# Modify region
123//-----------------------------------------------------------------------------
124
125//! Clear current region
126void wxRegion::Clear()
127{
128 UnRef();
129}
130
131//! Combine rectangle (x, y, w, h) with this.
132bool wxRegion::Combine(long x, long y, long width, long height, wxRegionOp op)
133{
e40298d5
JS
134 // Don't change shared data
135 if (!m_refData)
136 {
137 m_refData = new wxRegionRefData();
138 }
139 else if (m_refData->GetRefCount() > 1)
140 {
141 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
142 UnRef();
143 m_refData = new wxRegionRefData(*ref);
144 }
519cb848 145 RgnHandle rgn = NewRgn() ;
e40298d5
JS
146 SetRectRgn( rgn , x , y, x+width,y + height ) ;
147
e9576ca5
SC
148 switch (op)
149 {
150 case wxRGN_AND:
519cb848 151 SectRgn( M_REGION , rgn , M_REGION ) ;
e9576ca5
SC
152 break ;
153 case wxRGN_OR:
519cb848 154 UnionRgn( M_REGION , rgn , M_REGION ) ;
e9576ca5
SC
155 break ;
156 case wxRGN_XOR:
519cb848 157 XorRgn( M_REGION , rgn , M_REGION ) ;
e9576ca5
SC
158 break ;
159 case wxRGN_DIFF:
519cb848 160 DiffRgn( M_REGION , rgn , M_REGION ) ;
e9576ca5
SC
161 break ;
162 case wxRGN_COPY:
163 default:
e40298d5 164 CopyRgn( rgn ,M_REGION ) ;
e9576ca5
SC
165 break ;
166 }
167
e40298d5 168 DisposeRgn( rgn ) ;
e9576ca5 169
519cb848 170 return TRUE;
e9576ca5
SC
171}
172
173//! Union /e region with this.
174bool wxRegion::Combine(const wxRegion& region, wxRegionOp op)
175{
e40298d5
JS
176 if (region.Empty())
177 return FALSE;
178
179 // Don't change shared data
180 if (!m_refData) {
181 m_refData = new wxRegionRefData();
182 }
183 else if (m_refData->GetRefCount() > 1)
184 {
185 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
186 UnRef();
187 m_refData = new wxRegionRefData(*ref);
188 }
e9576ca5 189
e9576ca5
SC
190 switch (op)
191 {
192 case wxRGN_AND:
519cb848 193 SectRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
e9576ca5
SC
194 break ;
195 case wxRGN_OR:
519cb848 196 UnionRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
e9576ca5
SC
197 break ;
198 case wxRGN_XOR:
519cb848 199 XorRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
e9576ca5
SC
200 break ;
201 case wxRGN_DIFF:
519cb848 202 DiffRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
e9576ca5
SC
203 break ;
204 case wxRGN_COPY:
205 default:
e40298d5 206 CopyRgn( OTHER_M_REGION(region) ,M_REGION ) ;
e9576ca5
SC
207 break ;
208 }
209
e40298d5 210 return TRUE;
e9576ca5
SC
211}
212
213bool wxRegion::Combine(const wxRect& rect, wxRegionOp op)
214{
215 return Combine(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight(), op);
216}
217
218//-----------------------------------------------------------------------------
219//# Information on region
220//-----------------------------------------------------------------------------
221
222// Outer bounds of region
c0cd186f 223void wxRegion::GetBox(wxCoord& x, wxCoord& y, wxCoord& w, wxCoord& h) const
e9576ca5 224{
e40298d5
JS
225 if (m_refData)
226 {
227 Rect box ;
228 GetRegionBounds( M_REGION , &box ) ;
519cb848
SC
229 x = box.left ;
230 y = box.top ;
231 w = box.right - box.left ;
232 h = box.bottom - box.top ;
e40298d5
JS
233 }
234 else
235 {
236 x = y = w = h = 0;
237 }
e9576ca5
SC
238}
239
240wxRect wxRegion::GetBox() const
241{
c0cd186f 242 wxCoord x, y, w, h;
e9576ca5
SC
243 GetBox(x, y, w, h);
244 return wxRect(x, y, w, h);
245}
246
247// Is region empty?
248bool wxRegion::Empty() const
249{
519cb848
SC
250 return EmptyRgn( M_REGION ) ;
251}
252
253const WXHRGN wxRegion::GetWXHRGN() const
254{
e40298d5 255 return M_REGION ;
e9576ca5
SC
256}
257
258//-----------------------------------------------------------------------------
259//# Tests
260//-----------------------------------------------------------------------------
261
262// Does the region contain the point (x,y)?
263wxRegionContain wxRegion::Contains(long x, long y) const
264{
e40298d5
JS
265 if (!m_refData)
266 return wxOutRegion;
e9576ca5
SC
267
268 // TODO. Return wxInRegion if within region.
269 if (0)
270 return wxInRegion;
271 return wxOutRegion;
272}
273
274// Does the region contain the point pt?
275wxRegionContain wxRegion::Contains(const wxPoint& pt) const
276{
e40298d5
JS
277 if (!m_refData)
278 return wxOutRegion;
e9576ca5 279
519cb848
SC
280 Point p = { pt.y , pt.x } ;
281 if (PtInRgn( p , M_REGION ) )
e9576ca5 282 return wxInRegion;
519cb848
SC
283
284 return wxOutRegion;
e9576ca5
SC
285}
286
287// Does the region contain the rectangle (x, y, w, h)?
288wxRegionContain wxRegion::Contains(long x, long y, long w, long h) const
289{
e40298d5
JS
290 if (!m_refData)
291 return wxOutRegion;
e9576ca5 292
519cb848
SC
293 Rect rect = { y , x , y + h , x + w } ;
294 if (RectInRgn( &rect , M_REGION ) )
e9576ca5
SC
295 return wxInRegion;
296 else
297 return wxOutRegion;
298}
299
300// Does the region contain the rectangle rect
301wxRegionContain wxRegion::Contains(const wxRect& rect) const
302{
e40298d5
JS
303 if (!m_refData)
304 return wxOutRegion;
e9576ca5
SC
305
306 long x, y, w, h;
307 x = rect.x;
308 y = rect.y;
309 w = rect.GetWidth();
310 h = rect.GetHeight();
311 return Contains(x, y, w, h);
312}
313
314///////////////////////////////////////////////////////////////////////////////
e7600a2c
GD
315// //
316// wxRegionIterator //
317// //
e9576ca5
SC
318///////////////////////////////////////////////////////////////////////////////
319
320/*!
321 * Initialize empty iterator
322 */
e7600a2c
GD
323wxRegionIterator::wxRegionIterator()
324 : m_current(0), m_numRects(0), m_rects(NULL)
e9576ca5
SC
325{
326}
327
328wxRegionIterator::~wxRegionIterator()
329{
6dcbb6d0 330 if (m_rects) {
e9576ca5 331 delete[] m_rects;
6dcbb6d0
GD
332 m_rects = NULL;
333 }
e9576ca5
SC
334}
335
e7600a2c
GD
336wxRegionIterator::wxRegionIterator(const wxRegionIterator& iterator)
337 : wxObject()
338 , m_current(iterator.m_current)
6dcbb6d0 339 , m_numRects(0)
2012e3ea 340 , m_rects(NULL)
e7600a2c 341{
6dcbb6d0 342 SetRects(iterator.m_numRects, iterator.m_rects);
e7600a2c
GD
343}
344
345wxRegionIterator& wxRegionIterator::operator=(const wxRegionIterator& iterator)
346{
347 m_current = iterator.m_current;
6dcbb6d0 348 SetRects(iterator.m_numRects, iterator.m_rects);
e7600a2c
GD
349 return *this;
350}
351
6dcbb6d0
GD
352/*!
353 * Set iterator rects for region
354 */
355void wxRegionIterator::SetRects(long numRects, wxRect *rects)
356{
357 if (m_rects) {
358 delete[] m_rects;
359 m_rects = NULL;
360 }
361 if (rects)
362 {
363 int i;
364 m_rects = new wxRect[numRects];
365 for (i = 0; i < numRects; i++)
366 m_rects[i] = rects[i];
367 }
368 m_numRects = numRects;
369}
370
e9576ca5
SC
371/*!
372 * Initialize iterator for region
373 */
374wxRegionIterator::wxRegionIterator(const wxRegion& region)
375{
376 m_rects = NULL;
377
e7600a2c 378 Reset(region);
e9576ca5
SC
379}
380
381/*!
382 * Reset iterator for a new /e region.
383 */
384void wxRegionIterator::Reset(const wxRegion& region)
385{
6dcbb6d0
GD
386 m_current = 0;
387 m_region = region;
e9576ca5 388
6dcbb6d0 389 if (m_rects) {
e9576ca5 390 delete[] m_rects;
6dcbb6d0
GD
391 m_rects = NULL;
392 }
e9576ca5 393
6dcbb6d0
GD
394 if (m_region.Empty())
395 m_numRects = 0;
396 else
e9576ca5 397 {
e40298d5 398 // we cannot dissolve it into rects on mac
519cb848 399 m_rects = new wxRect[1];
6dcbb6d0
GD
400 Rect rect ;
401 GetRegionBounds( OTHER_M_REGION( region ) , &rect ) ;
519cb848
SC
402 m_rects[0].x = rect.left;
403 m_rects[0].y = rect.top;
404 m_rects[0].width = rect.right - rect.left;
405 m_rects[0].height = rect.bottom - rect.top;
406 m_numRects = 1;
e9576ca5
SC
407 }
408}
409
410/*!
411 * Increment iterator. The rectangle returned is the one after the
412 * incrementation.
413 */
e7600a2c 414wxRegionIterator& wxRegionIterator::operator ++ ()
e9576ca5 415{
e7600a2c
GD
416 if (m_current < m_numRects)
417 ++m_current;
418 return *this;
e9576ca5
SC
419}
420
421/*!
422 * Increment iterator. The rectangle returned is the one before the
423 * incrementation.
424 */
e7600a2c 425wxRegionIterator wxRegionIterator::operator ++ (int)
e9576ca5 426{
e7600a2c
GD
427 wxRegionIterator previous(*this);
428
429 if (m_current < m_numRects)
430 ++m_current;
431
432 return previous;
e9576ca5
SC
433}
434
435long wxRegionIterator::GetX() const
436{
e40298d5
JS
437 if (m_current < m_numRects)
438 return m_rects[m_current].x;
439 return 0;
e9576ca5
SC
440}
441
442long wxRegionIterator::GetY() const
443{
e40298d5
JS
444 if (m_current < m_numRects)
445 return m_rects[m_current].y;
446 return 0;
e9576ca5
SC
447}
448
449long wxRegionIterator::GetW() const
450{
e40298d5
JS
451 if (m_current < m_numRects)
452 return m_rects[m_current].width ;
453 return 0;
e9576ca5
SC
454}
455
456long wxRegionIterator::GetH() const
457{
e40298d5
JS
458 if (m_current < m_numRects)
459 return m_rects[m_current].height;
460 return 0;
e9576ca5
SC
461}
462