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