]> git.saurik.com Git - wxWidgets.git/blame - src/msw/region.cpp
New Unix configure system
[wxWidgets.git] / src / msw / region.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// File: region.cpp
3// Purpose: Region handling for wxWindows/X11
4// Author: Markus Holzem
5// Created: Fri Oct 24 10:46:34 MET 1997
6// RCS-ID: $Id$
7// Copyright: (c) 1997 Julian Smart and Markus Holzem
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11#ifdef __GNUG__
12#pragma implementation "region.h"
13#endif
14
15#include "wx/wxprec.h"
16
17#ifdef __BORLANDC__
18#pragma hdrstop
19#endif
20
21#include "wx/msw/region.h"
22#include "wx/gdicmn.h"
23
24#include <windows.h>
25
26#if !USE_SHARED_LIBRARY
27 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
28 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
29#endif
30
31//-----------------------------------------------------------------------------
32// wxRegionRefData implementation
33//-----------------------------------------------------------------------------
34
35class WXDLLEXPORT wxRegionRefData : public wxGDIRefData {
36public:
37 wxRegionRefData(void)
38 {
39 }
40
41 wxRegionRefData(const wxRegionRefData& data)
42 {
43#if defined(__WIN32__)
44 DWORD noBytes = ::GetRegionData(data.m_region, 0, NULL);
45 RGNDATA *rgnData = (RGNDATA*) new char[noBytes];
46 ::GetRegionData(data.m_region, noBytes, rgnData);
47 m_region = ::ExtCreateRegion(NULL, noBytes, rgnData);
48 delete[] (char*) rgnData;
49#else
50 RECT rect;
51 ::GetRgnBox(data.m_region, &rect);
52 m_region = ::CreateRectRgnIndirect(&rect);
53#endif
54 }
55
56 ~wxRegionRefData(void)
57 {
58 ::DeleteObject(m_region);
59 m_region = 0;
60 }
61
62 HRGN m_region;
63};
64
65#define M_REGION (((wxRegionRefData*)m_refData)->m_region)
66
67//-----------------------------------------------------------------------------
68// wxRegion
69//-----------------------------------------------------------------------------
70
71/*!
72 * Create an empty region.
73 */
74wxRegion::wxRegion(void)
75{
76 m_refData = new wxRegionRefData;
77 M_REGION = ::CreateRectRgn(0, 0, 0, 0);
78}
79
81d66cf3
JS
80wxRegion::wxRegion(WXHRGN hRegion)
81{
82 m_refData = new wxRegionRefData;
83 M_REGION = (HRGN) hRegion;
84}
85
2bda0e17
KB
86wxRegion::wxRegion(long x, long y, long w, long h)
87{
88 m_refData = new wxRegionRefData;
89 M_REGION = ::CreateRectRgn(x, y, x + w, y + h);
90}
91
92wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
93{
94 m_refData = new wxRegionRefData;
95 M_REGION = ::CreateRectRgn(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y);
96}
97
98wxRegion::wxRegion(const wxRect& rect)
99{
100 m_refData = new wxRegionRefData;
101 M_REGION = ::CreateRectRgn(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
102}
103
104/*!
105 * Destroy the region.
106 */
107wxRegion::~wxRegion(void)
108{
109 // m_refData unrefed in ~wxObject
110}
111
112//-----------------------------------------------------------------------------
113//# Modify region
114//-----------------------------------------------------------------------------
115
116//! Clear current region
117void wxRegion::Clear(void)
118{
119 UnRef();
120}
121
122//! Combine rectangle (x, y, w, h) with this.
123bool wxRegion::Combine(long x, long y, long width, long height, wxRegionOp op)
124{
125 // Don't change shared data
126 if (!m_refData) {
127 m_refData = new wxRegionRefData();
128 } else if (m_refData->GetRefCount() > 1) {
129 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
130 UnRef();
131 m_refData = new wxRegionRefData(*ref);
132 }
133 // If ref count is 1, that means it's 'ours' anyway so no action.
134
135 HRGN rectRegion = ::CreateRectRgn(x, y, x + width, y + height);
136
137 int mode = 0;
138 switch (op)
139 {
140 case wxRGN_AND: mode = RGN_AND; break ;
141 case wxRGN_OR: mode = RGN_OR; break ;
142 case wxRGN_XOR: mode = RGN_XOR; break ;
143 case wxRGN_DIFF: mode = RGN_DIFF; break ;
144 case wxRGN_COPY:
145 default:
146 mode = RGN_COPY; break ;
147 }
148
149 bool success = (ERROR != ::CombineRgn(M_REGION, M_REGION, rectRegion, mode));
150
151 ::DeleteObject(rectRegion);
152
153 return success;
154}
155
156//! Union /e region with this.
157bool wxRegion::Combine(const wxRegion& region, wxRegionOp op)
158{
159 if (region.Empty())
160 return FALSE;
161
162 // Don't change shared data
163 if (!m_refData) {
164 m_refData = new wxRegionRefData();
165 } else if (m_refData->GetRefCount() > 1) {
166 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
167 UnRef();
168 m_refData = new wxRegionRefData(*ref);
169 }
170
171 int mode = 0;
172 switch (op)
173 {
174 case wxRGN_AND: mode = RGN_AND; break ;
175 case wxRGN_OR: mode = RGN_OR; break ;
176 case wxRGN_XOR: mode = RGN_XOR; break ;
177 case wxRGN_DIFF: mode = RGN_DIFF; break ;
178 case wxRGN_COPY:
179 default:
180 mode = RGN_COPY; break ;
181 }
182
183 return (ERROR != ::CombineRgn(M_REGION, M_REGION, ((wxRegionRefData*)region.m_refData)->m_region, mode));
184}
185
186bool wxRegion::Combine(const wxRect& rect, wxRegionOp op)
187{
188 return Combine(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight(), op);
189}
190
191//-----------------------------------------------------------------------------
192//# Information on region
193//-----------------------------------------------------------------------------
194
195// Outer bounds of region
196void wxRegion::GetBox(long& x, long& y, long&w, long &h) const
197{
198 if (m_refData) {
199 RECT rect;
200 ::GetRgnBox(M_REGION, & rect);
201 x = rect.left;
202 y = rect.top;
203 w = rect.right - rect.left;
204 h = rect.bottom - rect.top;
205 } else {
206 x = y = w = h = 0;
207 }
208}
209
210wxRect wxRegion::GetBox(void) const
211{
212 long x, y, w, h;
213 GetBox(x, y, w, h);
214 return wxRect(x, y, w, h);
215}
216
217// Is region empty?
218bool wxRegion::Empty(void) const
219{
220 if (M_REGION == 0)
221 return TRUE;
222 long x, y, w, h;
223 GetBox(x, y, w, h);
224
225 return ((w == 0) && (h == 0));
226}
227
228//-----------------------------------------------------------------------------
229//# Tests
230//-----------------------------------------------------------------------------
231
232// Does the region contain the point (x,y)?
233wxRegionContain wxRegion::Contains(long x, long y) const
234{
235 if (!m_refData)
236 return wxOutRegion;
237
238 if (::PtInRegion(M_REGION, (int) x, (int) y))
239 return wxInRegion;
240 else
241 return wxOutRegion;
242}
243
244// Does the region contain the point pt?
245wxRegionContain wxRegion::Contains(const wxPoint& pt) const
246{
247 if (!m_refData)
248 return wxOutRegion;
249
250 if (::PtInRegion(M_REGION, (int) pt.x, (int) pt.y))
251 return wxInRegion;
252 else
253 return wxOutRegion;
254}
255
256// Does the region contain the rectangle (x, y, w, h)?
257wxRegionContain wxRegion::Contains(long x, long y, long w, long h) const
258{
259 if (!m_refData)
260 return wxOutRegion;
261
262 RECT rect;
263 rect.left = x;
264 rect.top = y;
265 rect.right = x + w;
266 rect.bottom = y + h;
267
268 if (::RectInRegion(M_REGION, & rect))
269 return wxInRegion;
270 else
271 return wxOutRegion;
272}
273
274// Does the region contain the rectangle rect
275wxRegionContain wxRegion::Contains(const wxRect& rect) const
276{
277 if (!m_refData)
278 return wxOutRegion;
279
280 long x, y, w, h;
281 x = rect.x;
282 y = rect.y;
283 w = rect.GetWidth();
284 h = rect.GetHeight();
285 return Contains(x, y, w, h);
286}
287
288///////////////////////////////////////////////////////////////////////////////
289// //
290// wxRegionIterator //
291// //
292///////////////////////////////////////////////////////////////////////////////
293
294/*!
295 * Initialize empty iterator
296 */
297wxRegionIterator::wxRegionIterator(void) : m_current(0), m_numRects(0), m_rects(NULL)
298{
299}
300
301wxRegionIterator::~wxRegionIterator(void)
302{
303 if (m_rects)
304 delete[] m_rects;
305}
306
307/*!
308 * Initialize iterator for region
309 */
310wxRegionIterator::wxRegionIterator(const wxRegion& region)
311{
312 m_rects = NULL;
313
314 Reset(region);
315}
316
317/*!
318 * Reset iterator for a new /e region.
319 */
320void wxRegionIterator::Reset(const wxRegion& region)
321{
322 m_current = 0;
323 m_region = region;
324
325 if (m_rects)
326 delete[] m_rects;
327
328 m_rects = NULL;
329
330 if (m_region.Empty())
331 m_numRects = 0;
332 else
333 {
334#if defined(__WIN32__)
335 DWORD noBytes = ::GetRegionData(((wxRegionRefData*)region.m_refData)->m_region, 0, NULL);
336 RGNDATA *rgnData = (RGNDATA*) new char[noBytes];
337 ::GetRegionData(((wxRegionRefData*)region.m_refData)->m_region, noBytes, rgnData);
338
339 RGNDATAHEADER* header = (RGNDATAHEADER*) rgnData;
340
341 m_rects = new wxRect[header->nCount];
342
343 RECT* rect = (RECT*) (rgnData + sizeof(RGNDATAHEADER)) ;
344 uint i;
345 for (i = 0; i < header->nCount; i++)
346 {
347 m_rects[i] = wxRect(rect->left, rect->top,
348 rect->right - rect->left, rect->bottom - rect->top);
349 rect += sizeof(RECT);
350 }
351
352 m_numRects = header->nCount;
353
354 delete[] (char*) rgnData;
355#else
356 RECT rect;
357 ::GetRgnBox(((wxRegionRefData*)region.m_refData)->m_region, &rect);
358 m_rects = new wxRect[1];
359 m_rects[0].x = rect.left;
360 m_rects[0].y = rect.top;
361 m_rects[0].width = rect.right - rect.left;
362 m_rects[0].height = rect.bottom - rect.top;
363
364 m_numRects = 1;
365#endif
366 }
367}
368
369/*!
370 * Increment iterator. The rectangle returned is the one after the
371 * incrementation.
372 */
373void wxRegionIterator::operator ++ (void)
374{
375 if (m_current < m_numRects)
376 ++m_current;
377}
378
379/*!
380 * Increment iterator. The rectangle returned is the one before the
381 * incrementation.
382 */
383void wxRegionIterator::operator ++ (int)
384{
385 if (m_current < m_numRects)
386 ++m_current;
387}
388
389long wxRegionIterator::GetX(void) const
390{
391 if (m_current < m_numRects)
392 return m_rects[m_current].x;
393 return 0;
394}
395
396long wxRegionIterator::GetY(void) const
397{
398 if (m_current < m_numRects)
399 return m_rects[m_current].y;
400 return 0;
401}
402
403long wxRegionIterator::GetW(void) const
404{
405 if (m_current < m_numRects)
406 return m_rects[m_current].width ;
407 return 0;
408}
409
410long wxRegionIterator::GetH(void) const
411{
412 if (m_current < m_numRects)
413 return m_rects[m_current].height;
414 return 0;
415}
416