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