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