]> git.saurik.com Git - wxWidgets.git/blame - src/mgl/region.cpp
GetSpacer returns a copy, not a reference to the size
[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__
dd05139a 14 #pragma hdrstop
32b8ec41
VZ
15#endif
16
17#include "wx/region.h"
b3a44e05 18
dd05139a
WS
19#ifndef WX_PRECOMP
20 #include "wx/gdicmn.h"
02761f6c 21 #include "wx/module.h"
dd05139a
WS
22#endif
23
32b8ec41
VZ
24#include "wx/thread.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:
6d7ee9e8 41 wxRegionRefData() {}
32b8ec41
VZ
42
43 wxRegionRefData(const wxRegionRefData& data)
44 {
45 m_region = data.m_region;
46 }
47
d3c7fc99 48 virtual ~wxRegionRefData() {}
32b8ec41
VZ
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
6d7ee9e8
VS
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
32b8ec41
VZ
70/*
71 * Create an empty region.
72 */
73wxRegion::wxRegion()
74{
6d7ee9e8 75 m_refData = NULL;
32b8ec41
VZ
76}
77
78wxRegion::wxRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
127eab18 79{
32b8ec41
VZ
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;
08c4a8a9 88 MGLRect rect(topLeft.x, topLeft.y, bottomRight.x+1, bottomRight.y+1);
32b8ec41
VZ
89 M_REGION = rect;
90}
91
92wxRegion::wxRegion(const wxRect& r)
93{
94 m_refData = new wxRegionRefData;
08c4a8a9 95 MGLRect rect(r.GetLeft(), r.GetTop(), r.GetRight()+1, r.GetBottom()+1);
32b8ec41
VZ
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
bbcc2d1b 130bool wxRegion::DoIsEqual(const wxRegion& WXUNUSED(region)) const
8a16d737
VZ
131{
132 wxFAIL_MSG( _T("not implemented") );
133
134 return false;
135}
136
32b8ec41 137// Outer bounds of region
8a16d737 138bool wxRegion::DoGetBox(wxCoord& x, wxCoord& y, wxCoord&w, wxCoord &h) const
32b8ec41 139{
127eab18 140 if (m_refData)
32b8ec41
VZ
141 {
142 rect_t rect;
143 rect = M_REGION.getBounds();
144 x = rect.left;
145 y = rect.top;
146 w = rect.right - rect.left;
147 h = rect.bottom - rect.top;
8a16d737
VZ
148
149 return true;
127eab18
WS
150 }
151 else
32b8ec41
VZ
152 {
153 x = y = w = h = 0;
8a16d737 154 return false;
32b8ec41
VZ
155 }
156}
157
32b8ec41 158// Is region empty?
8a16d737 159bool wxRegion::IsEmpty() const
32b8ec41 160{
127eab18
WS
161 if (!m_refData)
162 return true;
163
164 return (bool)(M_REGION.isEmpty());
32b8ec41
VZ
165}
166
167//-----------------------------------------------------------------------------
168// Modifications
169//-----------------------------------------------------------------------------
170
8a16d737 171bool wxRegion::DoOffset(wxCoord x, wxCoord y)
6d7ee9e8
VS
172{
173 AllocExclusive();
174 M_REGION.offset(x, y);
127eab18 175 return true;
6d7ee9e8
VS
176}
177
32b8ec41 178// Union rectangle or region with this.
8a16d737 179bool wxRegion::DoUnionWithRect(const wxRect& r)
32b8ec41 180{
6d7ee9e8 181 AllocExclusive();
8a16d737 182 M_REGION += MGLRect(r.x, r.y, r.GetRight() + 1, r.GetHeight() + 1);
127eab18 183 return true;
32b8ec41
VZ
184}
185
8a16d737 186bool wxRegion::DoUnionWithRegion(const wxRegion& region)
32b8ec41 187{
6d7ee9e8 188 AllocExclusive();
32b8ec41 189 M_REGION += M_REGION_OF(region);
127eab18 190 return true;
32b8ec41
VZ
191}
192
8a16d737 193bool wxRegion::DoIntersect(const wxRegion& region)
32b8ec41 194{
6d7ee9e8 195 AllocExclusive();
32b8ec41 196 M_REGION &= M_REGION_OF(region);
127eab18 197 return true;
32b8ec41
VZ
198}
199
8a16d737 200bool wxRegion::DoSubtract(const wxRegion& region)
32b8ec41 201{
6d7ee9e8 202 AllocExclusive();
32b8ec41 203 M_REGION -= M_REGION_OF(region);
127eab18 204 return true;
32b8ec41
VZ
205}
206
8a16d737 207bool wxRegion::DoXor(const wxRegion& region)
32b8ec41 208{
6d7ee9e8 209 AllocExclusive();
32b8ec41
VZ
210 MGLRegion rg1 = M_REGION + M_REGION_OF(region),
211 rg2 = M_REGION & M_REGION_OF(region);
212 M_REGION = rg1 - rg2;
127eab18 213 return true;
32b8ec41
VZ
214}
215
216
217//-----------------------------------------------------------------------------
218// Tests
219//-----------------------------------------------------------------------------
220
221// Does the region contain the point (x,y)?
8a16d737 222wxRegionContain wxRegion::DoContainsPoint(wxCoord x, wxCoord y) const
32b8ec41
VZ
223{
224 if (!m_refData)
225 return wxOutRegion;
226
227 if (M_REGION.includes((int)x, (int)y))
228 return wxInRegion;
229 else
230 return wxOutRegion;
231}
232
32b8ec41 233// Does the region contain the rectangle (x, y, w, h)?
8a16d737 234wxRegionContain wxRegion::DoContainsRect(const wxRect& r) const
32b8ec41
VZ
235{
236 if (!m_refData)
237 return wxOutRegion;
238
8a16d737 239 MGLRect rect(r.x, r.y, r.GetRight() + 1, r.GetBottom() + 1);
32b8ec41 240 MGLRegion rg;
127eab18 241
32b8ec41
VZ
242 // 1) is the rectangle entirely covered by the region?
243 rg = MGLRegion(rect) - M_REGION;
8a16d737
VZ
244 if (rg.isEmpty())
245 return wxInRegion;
127eab18 246
32b8ec41
VZ
247 // 2) is the rectangle completely outside the region?
248 rg = M_REGION & rect; // intersection
8a16d737
VZ
249 if (rg.isEmpty())
250 return wxOutRegion;
32b8ec41
VZ
251
252 // 3) neither case happened => it is partially covered:
253 return wxPartRegion;
254}
255
32b8ec41
VZ
256///////////////////////////////////////////////////////////////////////////////
257// wxRegionIterator //
258///////////////////////////////////////////////////////////////////////////////
259
2af6b4c3
VS
260#if wxUSE_THREADS
261static wxMutex *gs_mutexIterator;
262
263class wxMglRegionModule : public wxModule
264{
265public:
266 virtual bool OnInit()
267 {
268 gs_mutexIterator = new wxMutex();
127eab18 269 return true;
2af6b4c3
VS
270 }
271 virtual void OnExit()
272 {
273 wxDELETE(gs_mutexIterator);
274 }
275
276 DECLARE_DYNAMIC_CLASS(wxMglRegionModule)
277};
278IMPLEMENT_DYNAMIC_CLASS(wxMglRegionModule, wxModule)
279#endif
280
32b8ec41
VZ
281/*
282 * Initialize empty iterator
283 */
284wxRegionIterator::wxRegionIterator() : m_currentNode(NULL)
285{
127eab18 286 m_rects.DeleteContents(true);
32b8ec41
VZ
287}
288
289wxRegionIterator::~wxRegionIterator()
290{
291}
292
293/*
294 * Initialize iterator for region
295 */
296wxRegionIterator::wxRegionIterator(const wxRegion& region)
297{
127eab18 298 m_rects.DeleteContents(true);
32b8ec41
VZ
299 Reset(region);
300}
301
302/*
303 * Reset iterator for a new /e region.
304 */
127eab18 305
32b8ec41
VZ
306
307static wxRegionRectList *gs_rectList;
308
a246f95e 309static void MGLAPI wxMGL_region_callback(const rect_t *r)
32b8ec41 310{
127eab18 311 gs_rectList->Append(new wxRect(r->left, r->top,
32b8ec41
VZ
312 r->right - r->left, r->bottom - r->top));
313}
127eab18 314
32b8ec41
VZ
315void wxRegionIterator::Reset(const wxRegion& region)
316{
317 m_currentNode = NULL;
318 m_rects.Clear();
319
320 if (!region.Empty())
321 {
2af6b4c3 322#if wxUSE_THREADS
127eab18 323 wxMutexLocker lock(*gs_mutexIterator);
2af6b4c3 324#endif
32b8ec41
VZ
325 gs_rectList = &m_rects;
326 M_REGION_OF(region).traverse(wxMGL_region_callback);
32b8ec41
VZ
327 m_currentNode = m_rects.GetFirst();
328 }
329}
330
331/*
332 * Increment iterator. The rectangle returned is the one after the
333 * incrementation.
334 */
335void wxRegionIterator::operator ++ ()
336{
337 if (m_currentNode)
338 m_currentNode = m_currentNode->GetNext();
339}
340
341/*
342 * Increment iterator. The rectangle returned is the one before the
343 * incrementation.
344 */
345void wxRegionIterator::operator ++ (int)
346{
347 if (m_currentNode)
348 m_currentNode = m_currentNode->GetNext();
349}
350
351wxCoord wxRegionIterator::GetX() const
352{
353 if (m_currentNode)
354 return m_currentNode->GetData()->x;
355 else
356 return 0;
357}
358
359wxCoord wxRegionIterator::GetY() const
360{
361 if (m_currentNode)
362 return m_currentNode->GetData()->y;
363 else
364 return 0;
365}
366
367wxCoord wxRegionIterator::GetW() const
368{
369 if (m_currentNode)
370 return m_currentNode->GetData()->width;
371 else
372 return 0;
373}
374
375wxCoord wxRegionIterator::GetH() const
376{
377 if (m_currentNode)
378 return m_currentNode->GetData()->height;
379 else
380 return 0;
381}