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