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