]> git.saurik.com Git - wxWidgets.git/blame - src/mgl/region.cpp
assigning line marker to itself shouldn't invalidate it, add self-assignment check
[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
8f884a0d 60wxGDIRefData *wxRegion::CreateGDIRefData() const
6d7ee9e8
VS
61{
62 return new wxRegionRefData;
63}
64
8f884a0d 65wxGDIRefData *wxRegion::CloneGDIRefData(const wxGDIRefData *data) const
6d7ee9e8
VS
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
320bf9ce
WS
105wxRegion::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
32b8ec41
VZ
123wxRegion::~wxRegion()
124{
125 // m_refData unrefed in ~wxObject
126}
127
128const MGLRegion& wxRegion::GetMGLRegion() const
129{
130 return M_REGION;
131}
132
133//-----------------------------------------------------------------------------
134// Modify region
135//-----------------------------------------------------------------------------
136
137// Clear current region
138void wxRegion::Clear()
139{
140 UnRef();
141}
142
143
144//-----------------------------------------------------------------------------
145// Information on region
146//-----------------------------------------------------------------------------
147
bbcc2d1b 148bool wxRegion::DoIsEqual(const wxRegion& WXUNUSED(region)) const
8a16d737
VZ
149{
150 wxFAIL_MSG( _T("not implemented") );
151
152 return false;
153}
154
32b8ec41 155// Outer bounds of region
8a16d737 156bool wxRegion::DoGetBox(wxCoord& x, wxCoord& y, wxCoord&w, wxCoord &h) const
32b8ec41 157{
127eab18 158 if (m_refData)
32b8ec41
VZ
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;
8a16d737
VZ
166
167 return true;
127eab18
WS
168 }
169 else
32b8ec41
VZ
170 {
171 x = y = w = h = 0;
8a16d737 172 return false;
32b8ec41
VZ
173 }
174}
175
32b8ec41 176// Is region empty?
8a16d737 177bool wxRegion::IsEmpty() const
32b8ec41 178{
127eab18
WS
179 if (!m_refData)
180 return true;
181
182 return (bool)(M_REGION.isEmpty());
32b8ec41
VZ
183}
184
185//-----------------------------------------------------------------------------
186// Modifications
187//-----------------------------------------------------------------------------
188
8a16d737 189bool wxRegion::DoOffset(wxCoord x, wxCoord y)
6d7ee9e8
VS
190{
191 AllocExclusive();
192 M_REGION.offset(x, y);
127eab18 193 return true;
6d7ee9e8
VS
194}
195
32b8ec41 196// Union rectangle or region with this.
8a16d737 197bool wxRegion::DoUnionWithRect(const wxRect& r)
32b8ec41 198{
6d7ee9e8 199 AllocExclusive();
8a16d737 200 M_REGION += MGLRect(r.x, r.y, r.GetRight() + 1, r.GetHeight() + 1);
127eab18 201 return true;
32b8ec41
VZ
202}
203
8a16d737 204bool wxRegion::DoUnionWithRegion(const wxRegion& region)
32b8ec41 205{
6d7ee9e8 206 AllocExclusive();
32b8ec41 207 M_REGION += M_REGION_OF(region);
127eab18 208 return true;
32b8ec41
VZ
209}
210
8a16d737 211bool wxRegion::DoIntersect(const wxRegion& region)
32b8ec41 212{
6d7ee9e8 213 AllocExclusive();
32b8ec41 214 M_REGION &= M_REGION_OF(region);
127eab18 215 return true;
32b8ec41
VZ
216}
217
8a16d737 218bool wxRegion::DoSubtract(const wxRegion& region)
32b8ec41 219{
6d7ee9e8 220 AllocExclusive();
32b8ec41 221 M_REGION -= M_REGION_OF(region);
127eab18 222 return true;
32b8ec41
VZ
223}
224
8a16d737 225bool wxRegion::DoXor(const wxRegion& region)
32b8ec41 226{
6d7ee9e8 227 AllocExclusive();
32b8ec41
VZ
228 MGLRegion rg1 = M_REGION + M_REGION_OF(region),
229 rg2 = M_REGION & M_REGION_OF(region);
230 M_REGION = rg1 - rg2;
127eab18 231 return true;
32b8ec41
VZ
232}
233
234
235//-----------------------------------------------------------------------------
236// Tests
237//-----------------------------------------------------------------------------
238
239// Does the region contain the point (x,y)?
8a16d737 240wxRegionContain wxRegion::DoContainsPoint(wxCoord x, wxCoord y) const
32b8ec41
VZ
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
32b8ec41 251// Does the region contain the rectangle (x, y, w, h)?
8a16d737 252wxRegionContain wxRegion::DoContainsRect(const wxRect& r) const
32b8ec41
VZ
253{
254 if (!m_refData)
255 return wxOutRegion;
256
8a16d737 257 MGLRect rect(r.x, r.y, r.GetRight() + 1, r.GetBottom() + 1);
32b8ec41 258 MGLRegion rg;
127eab18 259
32b8ec41
VZ
260 // 1) is the rectangle entirely covered by the region?
261 rg = MGLRegion(rect) - M_REGION;
8a16d737
VZ
262 if (rg.isEmpty())
263 return wxInRegion;
127eab18 264
32b8ec41
VZ
265 // 2) is the rectangle completely outside the region?
266 rg = M_REGION & rect; // intersection
8a16d737
VZ
267 if (rg.isEmpty())
268 return wxOutRegion;
32b8ec41
VZ
269
270 // 3) neither case happened => it is partially covered:
271 return wxPartRegion;
272}
273
32b8ec41
VZ
274///////////////////////////////////////////////////////////////////////////////
275// wxRegionIterator //
276///////////////////////////////////////////////////////////////////////////////
277
2af6b4c3
VS
278#if wxUSE_THREADS
279static wxMutex *gs_mutexIterator;
280
281class wxMglRegionModule : public wxModule
282{
283public:
284 virtual bool OnInit()
285 {
286 gs_mutexIterator = new wxMutex();
127eab18 287 return true;
2af6b4c3
VS
288 }
289 virtual void OnExit()
290 {
291 wxDELETE(gs_mutexIterator);
292 }
293
294 DECLARE_DYNAMIC_CLASS(wxMglRegionModule)
295};
296IMPLEMENT_DYNAMIC_CLASS(wxMglRegionModule, wxModule)
297#endif
298
32b8ec41
VZ
299/*
300 * Initialize empty iterator
301 */
302wxRegionIterator::wxRegionIterator() : m_currentNode(NULL)
303{
127eab18 304 m_rects.DeleteContents(true);
32b8ec41
VZ
305}
306
307wxRegionIterator::~wxRegionIterator()
308{
309}
310
311/*
312 * Initialize iterator for region
313 */
314wxRegionIterator::wxRegionIterator(const wxRegion& region)
315{
127eab18 316 m_rects.DeleteContents(true);
32b8ec41
VZ
317 Reset(region);
318}
319
320/*
321 * Reset iterator for a new /e region.
322 */
127eab18 323
32b8ec41
VZ
324
325static wxRegionRectList *gs_rectList;
326
a246f95e 327static void MGLAPI wxMGL_region_callback(const rect_t *r)
32b8ec41 328{
127eab18 329 gs_rectList->Append(new wxRect(r->left, r->top,
32b8ec41
VZ
330 r->right - r->left, r->bottom - r->top));
331}
127eab18 332
32b8ec41
VZ
333void wxRegionIterator::Reset(const wxRegion& region)
334{
335 m_currentNode = NULL;
336 m_rects.Clear();
337
338 if (!region.Empty())
339 {
2af6b4c3 340#if wxUSE_THREADS
127eab18 341 wxMutexLocker lock(*gs_mutexIterator);
2af6b4c3 342#endif
32b8ec41
VZ
343 gs_rectList = &m_rects;
344 M_REGION_OF(region).traverse(wxMGL_region_callback);
32b8ec41
VZ
345 m_currentNode = m_rects.GetFirst();
346 }
347}
348
349/*
350 * Increment iterator. The rectangle returned is the one after the
351 * incrementation.
352 */
353void 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 */
363void wxRegionIterator::operator ++ (int)
364{
365 if (m_currentNode)
366 m_currentNode = m_currentNode->GetNext();
367}
368
369wxCoord wxRegionIterator::GetX() const
370{
371 if (m_currentNode)
372 return m_currentNode->GetData()->x;
373 else
374 return 0;
375}
376
377wxCoord wxRegionIterator::GetY() const
378{
379 if (m_currentNode)
380 return m_currentNode->GetData()->y;
381 else
382 return 0;
383}
384
385wxCoord wxRegionIterator::GetW() const
386{
387 if (m_currentNode)
388 return m_currentNode->GetData()->width;
389 else
390 return 0;
391}
392
393wxCoord wxRegionIterator::GetH() const
394{
395 if (m_currentNode)
396 return m_currentNode->GetData()->height;
397 else
398 return 0;
399}