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