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