]> git.saurik.com Git - wxWidgets.git/blob - src/mgl/region.cpp
wxRichTextCtrl native caret now flashes, for wxMac/Core Graphics mode
[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 #ifndef WX_PRECOMP
20 #include "wx/gdicmn.h"
21 #include "wx/module.h"
22 #endif
23
24 #include "wx/thread.h"
25
26 #include <mgraph.hpp>
27
28 #include "wx/listimpl.cpp"
29 WX_DEFINE_LIST(wxRegionRectList)
30
31 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
32 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
33
34 //-----------------------------------------------------------------------------
35 // wxRegionRefData implementation
36 //-----------------------------------------------------------------------------
37
38 class WXDLLEXPORT wxRegionRefData : public wxGDIRefData
39 {
40 public:
41 wxRegionRefData() {}
42
43 wxRegionRefData(const wxRegionRefData& data)
44 {
45 m_region = data.m_region;
46 }
47
48 virtual ~wxRegionRefData() {}
49
50 MGLRegion m_region;
51 };
52
53 #define M_REGION (((wxRegionRefData*)m_refData)->m_region)
54 #define M_REGION_OF(r) (((wxRegionRefData*)(r.m_refData))->m_region)
55
56 //-----------------------------------------------------------------------------
57 // wxRegion
58 //-----------------------------------------------------------------------------
59
60 wxGDIRefData *wxRegion::CreateGDIRefData() const
61 {
62 return new wxRegionRefData;
63 }
64
65 wxGDIRefData *wxRegion::CloneGDIRefData(const wxGDIRefData *data) const
66 {
67 return new wxRegionRefData(*(wxRegionRefData *)data);
68 }
69
70 /*
71 * Create an empty region.
72 */
73 wxRegion::wxRegion()
74 {
75 m_refData = NULL;
76 }
77
78 wxRegion::wxRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
79 {
80 m_refData = new wxRegionRefData;
81 MGLRect rect(x, y, x + w, y + h);
82 M_REGION = rect;
83 }
84
85 wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
86 {
87 m_refData = new wxRegionRefData;
88 MGLRect rect(topLeft.x, topLeft.y, bottomRight.x+1, bottomRight.y+1);
89 M_REGION = rect;
90 }
91
92 wxRegion::wxRegion(const wxRect& r)
93 {
94 m_refData = new wxRegionRefData;
95 MGLRect rect(r.GetLeft(), r.GetTop(), r.GetRight()+1, r.GetBottom()+1);
96 M_REGION = rect;
97 }
98
99 wxRegion::wxRegion(const MGLRegion& region)
100 {
101 m_refData = new wxRegionRefData;
102 M_REGION = region;
103 }
104
105 wxRegion::wxRegion(size_t n, const wxPoint *points, int WXUNUSED(fillStyle))
106 {
107 m_refData = new wxRegionRefData;
108 point_t *pts = new point_t[n];
109
110 for (size_t i = 0; i < n; i++)
111 {
112 pts[i].x = points[i].x;
113 pts[i].y = points[i].y;
114 }
115
116 region_t* rgn = MGL_rgnPolygon(n, pts, 1, 0, 0);
117
118 M_REGION = rgn;
119
120 delete [] pts;
121 }
122
123 wxRegion::~wxRegion()
124 {
125 // m_refData unrefed in ~wxObject
126 }
127
128 const MGLRegion& wxRegion::GetMGLRegion() const
129 {
130 return M_REGION;
131 }
132
133 //-----------------------------------------------------------------------------
134 // Modify region
135 //-----------------------------------------------------------------------------
136
137 // Clear current region
138 void wxRegion::Clear()
139 {
140 UnRef();
141 }
142
143
144 //-----------------------------------------------------------------------------
145 // Information on region
146 //-----------------------------------------------------------------------------
147
148 bool wxRegion::DoIsEqual(const wxRegion& WXUNUSED(region)) const
149 {
150 wxFAIL_MSG( _T("not implemented") );
151
152 return false;
153 }
154
155 // Outer bounds of region
156 bool wxRegion::DoGetBox(wxCoord& x, wxCoord& y, wxCoord&w, wxCoord &h) const
157 {
158 if (m_refData)
159 {
160 rect_t rect;
161 rect = M_REGION.getBounds();
162 x = rect.left;
163 y = rect.top;
164 w = rect.right - rect.left;
165 h = rect.bottom - rect.top;
166
167 return true;
168 }
169 else
170 {
171 x = y = w = h = 0;
172 return false;
173 }
174 }
175
176 // Is region empty?
177 bool wxRegion::IsEmpty() const
178 {
179 if (!m_refData)
180 return true;
181
182 return (bool)(M_REGION.isEmpty());
183 }
184
185 //-----------------------------------------------------------------------------
186 // Modifications
187 //-----------------------------------------------------------------------------
188
189 bool wxRegion::DoOffset(wxCoord x, wxCoord y)
190 {
191 AllocExclusive();
192 M_REGION.offset(x, y);
193 return true;
194 }
195
196 // Union rectangle or region with this.
197 bool wxRegion::DoUnionWithRect(const wxRect& r)
198 {
199 AllocExclusive();
200 M_REGION += MGLRect(r.x, r.y, r.GetRight() + 1, r.GetHeight() + 1);
201 return true;
202 }
203
204 bool wxRegion::DoUnionWithRegion(const wxRegion& region)
205 {
206 AllocExclusive();
207 M_REGION += M_REGION_OF(region);
208 return true;
209 }
210
211 bool wxRegion::DoIntersect(const wxRegion& region)
212 {
213 AllocExclusive();
214 M_REGION &= M_REGION_OF(region);
215 return true;
216 }
217
218 bool wxRegion::DoSubtract(const wxRegion& region)
219 {
220 AllocExclusive();
221 M_REGION -= M_REGION_OF(region);
222 return true;
223 }
224
225 bool wxRegion::DoXor(const wxRegion& region)
226 {
227 AllocExclusive();
228 MGLRegion rg1 = M_REGION + M_REGION_OF(region),
229 rg2 = M_REGION & M_REGION_OF(region);
230 M_REGION = rg1 - rg2;
231 return true;
232 }
233
234
235 //-----------------------------------------------------------------------------
236 // Tests
237 //-----------------------------------------------------------------------------
238
239 // Does the region contain the point (x,y)?
240 wxRegionContain wxRegion::DoContainsPoint(wxCoord x, wxCoord y) const
241 {
242 if (!m_refData)
243 return wxOutRegion;
244
245 if (M_REGION.includes((int)x, (int)y))
246 return wxInRegion;
247 else
248 return wxOutRegion;
249 }
250
251 // Does the region contain the rectangle (x, y, w, h)?
252 wxRegionContain wxRegion::DoContainsRect(const wxRect& r) const
253 {
254 if (!m_refData)
255 return wxOutRegion;
256
257 MGLRect rect(r.x, r.y, r.GetRight() + 1, r.GetBottom() + 1);
258 MGLRegion rg;
259
260 // 1) is the rectangle entirely covered by the region?
261 rg = MGLRegion(rect) - M_REGION;
262 if (rg.isEmpty())
263 return wxInRegion;
264
265 // 2) is the rectangle completely outside the region?
266 rg = M_REGION & rect; // intersection
267 if (rg.isEmpty())
268 return wxOutRegion;
269
270 // 3) neither case happened => it is partially covered:
271 return wxPartRegion;
272 }
273
274 ///////////////////////////////////////////////////////////////////////////////
275 // wxRegionIterator //
276 ///////////////////////////////////////////////////////////////////////////////
277
278 #if wxUSE_THREADS
279 static wxMutex *gs_mutexIterator;
280
281 class wxMglRegionModule : public wxModule
282 {
283 public:
284 virtual bool OnInit()
285 {
286 gs_mutexIterator = new wxMutex();
287 return true;
288 }
289 virtual void OnExit()
290 {
291 wxDELETE(gs_mutexIterator);
292 }
293
294 DECLARE_DYNAMIC_CLASS(wxMglRegionModule)
295 };
296 IMPLEMENT_DYNAMIC_CLASS(wxMglRegionModule, wxModule)
297 #endif
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 #if wxUSE_THREADS
341 wxMutexLocker lock(*gs_mutexIterator);
342 #endif
343 gs_rectList = &m_rects;
344 M_REGION_OF(region).traverse(wxMGL_region_callback);
345 m_currentNode = m_rects.GetFirst();
346 }
347 }
348
349 /*
350 * Increment iterator. The rectangle returned is the one after the
351 * incrementation.
352 */
353 void wxRegionIterator::operator ++ ()
354 {
355 if (m_currentNode)
356 m_currentNode = m_currentNode->GetNext();
357 }
358
359 /*
360 * Increment iterator. The rectangle returned is the one before the
361 * incrementation.
362 */
363 void wxRegionIterator::operator ++ (int)
364 {
365 if (m_currentNode)
366 m_currentNode = m_currentNode->GetNext();
367 }
368
369 wxCoord wxRegionIterator::GetX() const
370 {
371 if (m_currentNode)
372 return m_currentNode->GetData()->x;
373 else
374 return 0;
375 }
376
377 wxCoord wxRegionIterator::GetY() const
378 {
379 if (m_currentNode)
380 return m_currentNode->GetData()->y;
381 else
382 return 0;
383 }
384
385 wxCoord wxRegionIterator::GetW() const
386 {
387 if (m_currentNode)
388 return m_currentNode->GetData()->width;
389 else
390 return 0;
391 }
392
393 wxCoord wxRegionIterator::GetH() const
394 {
395 if (m_currentNode)
396 return m_currentNode->GetData()->height;
397 else
398 return 0;
399 }