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