]> git.saurik.com Git - wxWidgets.git/blob - src/mgl/region.cpp
revert unintended changes in previous commit
[wxWidgets.git] / src / mgl / region.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mgl/region.cpp
3 // Purpose: Region handling for wxWidgets/MGL
4 // Author: Vaclav Slavik
5 // RCS-ID: $Id$
6 // Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
12
13 #ifdef __BORLANDC__
14 #pragma hdrstop
15 #endif
16
17 #include "wx/region.h"
18
19 #include "wx/gdicmn.h"
20 #include "wx/thread.h"
21 #include "wx/module.h"
22
23 #include <mgraph.hpp>
24
25 #include "wx/listimpl.cpp"
26 WX_DEFINE_LIST(wxRegionRectList)
27
28 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
29 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
30
31 //-----------------------------------------------------------------------------
32 // wxRegionRefData implementation
33 //-----------------------------------------------------------------------------
34
35 class WXDLLEXPORT wxRegionRefData : public wxGDIRefData
36 {
37 public:
38 wxRegionRefData() {}
39
40 wxRegionRefData(const wxRegionRefData& data)
41 {
42 m_region = data.m_region;
43 }
44
45 ~wxRegionRefData() {}
46
47 MGLRegion m_region;
48 };
49
50 #define M_REGION (((wxRegionRefData*)m_refData)->m_region)
51 #define M_REGION_OF(r) (((wxRegionRefData*)(r.m_refData))->m_region)
52
53 //-----------------------------------------------------------------------------
54 // wxRegion
55 //-----------------------------------------------------------------------------
56
57 wxObjectRefData *wxRegion::CreateRefData() const
58 {
59 return new wxRegionRefData;
60 }
61
62 wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
63 {
64 return new wxRegionRefData(*(wxRegionRefData *)data);
65 }
66
67 /*
68 * Create an empty region.
69 */
70 wxRegion::wxRegion()
71 {
72 m_refData = NULL;
73 }
74
75 wxRegion::wxRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
76 {
77 m_refData = new wxRegionRefData;
78 MGLRect rect(x, y, x + w, y + h);
79 M_REGION = rect;
80 }
81
82 wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
83 {
84 m_refData = new wxRegionRefData;
85 MGLRect rect(topLeft.x, topLeft.y, bottomRight.x+1, bottomRight.y+1);
86 M_REGION = rect;
87 }
88
89 wxRegion::wxRegion(const wxRect& r)
90 {
91 m_refData = new wxRegionRefData;
92 MGLRect rect(r.GetLeft(), r.GetTop(), r.GetRight()+1, r.GetBottom()+1);
93 M_REGION = rect;
94 }
95
96 wxRegion::wxRegion(const MGLRegion& region)
97 {
98 m_refData = new wxRegionRefData;
99 M_REGION = region;
100 }
101
102 wxRegion::~wxRegion()
103 {
104 // m_refData unrefed in ~wxObject
105 }
106
107 const MGLRegion& wxRegion::GetMGLRegion() const
108 {
109 return M_REGION;
110 }
111
112 //-----------------------------------------------------------------------------
113 // Modify region
114 //-----------------------------------------------------------------------------
115
116 // Clear current region
117 void wxRegion::Clear()
118 {
119 UnRef();
120 }
121
122
123 //-----------------------------------------------------------------------------
124 // Information on region
125 //-----------------------------------------------------------------------------
126
127 // Outer bounds of region
128 void wxRegion::GetBox(wxCoord& x, wxCoord& y, wxCoord&w, wxCoord &h) const
129 {
130 if (m_refData)
131 {
132 rect_t rect;
133 rect = M_REGION.getBounds();
134 x = rect.left;
135 y = rect.top;
136 w = rect.right - rect.left;
137 h = rect.bottom - rect.top;
138 }
139 else
140 {
141 x = y = w = h = 0;
142 }
143 }
144
145 wxRect wxRegion::GetBox() const
146 {
147 wxCoord x, y, w, h;
148 GetBox(x, y, w, h);
149 return wxRect(x, y, w, h);
150 }
151
152 // Is region empty?
153 bool wxRegion::Empty() const
154 {
155 if (!m_refData)
156 return true;
157
158 return (bool)(M_REGION.isEmpty());
159 }
160
161 //-----------------------------------------------------------------------------
162 // Modifications
163 //-----------------------------------------------------------------------------
164
165 bool wxRegion::Offset(wxCoord x, wxCoord y)
166 {
167 AllocExclusive();
168 M_REGION.offset(x, y);
169 return true;
170 }
171
172 // Union rectangle or region with this.
173 bool wxRegion::Union(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
174 {
175 AllocExclusive();
176 M_REGION += MGLRect(x, y, x + width, y + height);
177 return true;
178 }
179
180 bool wxRegion::Union(const wxRegion& region)
181 {
182 AllocExclusive();
183 M_REGION += M_REGION_OF(region);
184 return true;
185 }
186
187 // Intersect rectangle or region with this.
188 bool wxRegion::Intersect(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
189 {
190 AllocExclusive();
191 M_REGION &= MGLRect(x, y, x + width, y + height);
192 return true;
193 }
194
195 bool wxRegion::Intersect(const wxRegion& region)
196 {
197 AllocExclusive();
198 M_REGION &= M_REGION_OF(region);
199 return true;
200 }
201
202 // Subtract rectangle or region from this:
203 // Combines the parts of 'this' that are not part of the second region.
204 bool wxRegion::Subtract(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
205 {
206 AllocExclusive();
207 M_REGION -= MGLRect(x, y, x + width, y + height);
208 return true;
209 }
210
211 bool wxRegion::Subtract(const wxRegion& region)
212 {
213 AllocExclusive();
214 M_REGION -= M_REGION_OF(region);
215 return true;
216 }
217
218 // XOR: the union of two combined regions except for any overlapping areas.
219 bool wxRegion::Xor(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
220 {
221 AllocExclusive();
222 MGLRect rect(x, y, x + width, y + height);
223 MGLRegion rg1 = M_REGION + rect,
224 rg2 = M_REGION & rect;
225 M_REGION = rg1 - rg2;
226 return true;
227 }
228
229 bool wxRegion::Xor(const wxRegion& region)
230 {
231 AllocExclusive();
232 MGLRegion rg1 = M_REGION + M_REGION_OF(region),
233 rg2 = M_REGION & M_REGION_OF(region);
234 M_REGION = rg1 - rg2;
235 return true;
236 }
237
238
239 //-----------------------------------------------------------------------------
240 // Tests
241 //-----------------------------------------------------------------------------
242
243 // Does the region contain the point (x,y)?
244 wxRegionContain wxRegion::Contains(wxCoord x, wxCoord y) const
245 {
246 if (!m_refData)
247 return wxOutRegion;
248
249 if (M_REGION.includes((int)x, (int)y))
250 return wxInRegion;
251 else
252 return wxOutRegion;
253 }
254
255 // Does the region contain the point pt?
256 wxRegionContain wxRegion::Contains(const wxPoint& pt) const
257 {
258 return Contains(pt.x, pt.y);
259 }
260
261 // Does the region contain the rectangle (x, y, w, h)?
262 wxRegionContain wxRegion::Contains(wxCoord x, wxCoord y, wxCoord w, wxCoord h) const
263 {
264 if (!m_refData)
265 return wxOutRegion;
266
267 MGLRect rect(x, y, x + w, y + h);
268 MGLRegion rg;
269
270 // 1) is the rectangle entirely covered by the region?
271 rg = MGLRegion(rect) - M_REGION;
272 if (rg.isEmpty()) return wxInRegion;
273
274 // 2) is the rectangle completely outside the region?
275 rg = M_REGION & rect; // intersection
276 if (rg.isEmpty()) return wxOutRegion;
277
278 // 3) neither case happened => it is partially covered:
279 return wxPartRegion;
280 }
281
282 // Does the region contain the rectangle rect
283 wxRegionContain wxRegion::Contains(const wxRect& rect) const
284 {
285 return Contains(rect.x, rect.y, rect.width, rect.height);
286 }
287
288
289 ///////////////////////////////////////////////////////////////////////////////
290 // wxRegionIterator //
291 ///////////////////////////////////////////////////////////////////////////////
292
293 #if wxUSE_THREADS
294 static wxMutex *gs_mutexIterator;
295
296 class wxMglRegionModule : public wxModule
297 {
298 public:
299 virtual bool OnInit()
300 {
301 gs_mutexIterator = new wxMutex();
302 return true;
303 }
304 virtual void OnExit()
305 {
306 wxDELETE(gs_mutexIterator);
307 }
308
309 DECLARE_DYNAMIC_CLASS(wxMglRegionModule)
310 };
311 IMPLEMENT_DYNAMIC_CLASS(wxMglRegionModule, wxModule)
312 #endif
313
314 /*
315 * Initialize empty iterator
316 */
317 wxRegionIterator::wxRegionIterator() : m_currentNode(NULL)
318 {
319 m_rects.DeleteContents(true);
320 }
321
322 wxRegionIterator::~wxRegionIterator()
323 {
324 }
325
326 /*
327 * Initialize iterator for region
328 */
329 wxRegionIterator::wxRegionIterator(const wxRegion& region)
330 {
331 m_rects.DeleteContents(true);
332 Reset(region);
333 }
334
335 /*
336 * Reset iterator for a new /e region.
337 */
338
339
340 static wxRegionRectList *gs_rectList;
341
342 static void MGLAPI wxMGL_region_callback(const rect_t *r)
343 {
344 gs_rectList->Append(new wxRect(r->left, r->top,
345 r->right - r->left, r->bottom - r->top));
346 }
347
348 void wxRegionIterator::Reset(const wxRegion& region)
349 {
350 m_currentNode = NULL;
351 m_rects.Clear();
352
353 if (!region.Empty())
354 {
355 #if wxUSE_THREADS
356 wxMutexLocker lock(*gs_mutexIterator);
357 #endif
358 gs_rectList = &m_rects;
359 M_REGION_OF(region).traverse(wxMGL_region_callback);
360 m_currentNode = m_rects.GetFirst();
361 }
362 }
363
364 /*
365 * Increment iterator. The rectangle returned is the one after the
366 * incrementation.
367 */
368 void wxRegionIterator::operator ++ ()
369 {
370 if (m_currentNode)
371 m_currentNode = m_currentNode->GetNext();
372 }
373
374 /*
375 * Increment iterator. The rectangle returned is the one before the
376 * incrementation.
377 */
378 void wxRegionIterator::operator ++ (int)
379 {
380 if (m_currentNode)
381 m_currentNode = m_currentNode->GetNext();
382 }
383
384 wxCoord wxRegionIterator::GetX() const
385 {
386 if (m_currentNode)
387 return m_currentNode->GetData()->x;
388 else
389 return 0;
390 }
391
392 wxCoord wxRegionIterator::GetY() const
393 {
394 if (m_currentNode)
395 return m_currentNode->GetData()->y;
396 else
397 return 0;
398 }
399
400 wxCoord wxRegionIterator::GetW() const
401 {
402 if (m_currentNode)
403 return m_currentNode->GetData()->width;
404 else
405 return 0;
406 }
407
408 wxCoord wxRegionIterator::GetH() const
409 {
410 if (m_currentNode)
411 return m_currentNode->GetData()->height;
412 else
413 return 0;
414 }