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