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