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