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