]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/region.cpp
more new files
[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/msw/private.h"
27
28#if !USE_SHARED_LIBRARY
29 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
30 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
31#endif
32
33//-----------------------------------------------------------------------------
34// wxRegionRefData implementation
35//-----------------------------------------------------------------------------
36
37class WXDLLEXPORT wxRegionRefData : public wxGDIRefData
38{
39public:
40 wxRegionRefData()
41 {
42 m_region = 0;
43 }
44
45 wxRegionRefData(const wxRegionRefData& data)
46 {
47#if defined(__WIN32__)
48 DWORD noBytes = ::GetRegionData(data.m_region, 0, NULL);
49 RGNDATA *rgnData = (RGNDATA*) new char[noBytes];
50 ::GetRegionData(data.m_region, noBytes, rgnData);
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
58 }
59
60 ~wxRegionRefData()
61 {
62 ::DeleteObject(m_region);
63 m_region = 0;
64 }
65
66 HRGN m_region;
67};
68
69#define M_REGION (((wxRegionRefData*)m_refData)->m_region)
70
71//-----------------------------------------------------------------------------
72// wxRegion
73//-----------------------------------------------------------------------------
74
75/*
76 * Create an empty region.
77 */
78wxRegion::wxRegion()
79{
80 m_refData = new wxRegionRefData;
81 M_REGION = ::CreateRectRgn(0, 0, 0, 0);
82}
83
84wxRegion::wxRegion(WXHRGN hRegion)
85{
86 m_refData = new wxRegionRefData;
87 M_REGION = (HRGN) hRegion;
88}
89
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
108/*
109 * Destroy the region.
110 */
111wxRegion::~wxRegion()
112{
113 // m_refData unrefed in ~wxObject
114}
115
116//-----------------------------------------------------------------------------
117// Modify region
118//-----------------------------------------------------------------------------
119
120// Clear current region
121void wxRegion::Clear()
122{
123 UnRef();
124}
125
126// Combine rectangle (x, y, w, h) with this.
127bool wxRegion::Combine(long x, long y, long width, long height, wxRegionOp op)
128{
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 }
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
153 bool success = (ERROR != ::CombineRgn(M_REGION, M_REGION, rectRegion, mode));
154
155 ::DeleteObject(rectRegion);
156
157 return success;
158}
159
160// Union /e region with this.
161bool wxRegion::Combine(const wxRegion& region, wxRegionOp op)
162{
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 }
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
187 return (ERROR != ::CombineRgn(M_REGION, M_REGION, ((wxRegionRefData*)region.m_refData)->m_region, mode));
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//-----------------------------------------------------------------------------
196// Information on region
197//-----------------------------------------------------------------------------
198
199// Outer bounds of region
200void wxRegion::GetBox(long& x, long& y, long&w, long &h) const
201{
202 if (m_refData) {
203 RECT rect;
204 ::GetRgnBox(M_REGION, & rect);
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 }
212}
213
214wxRect wxRegion::GetBox() const
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?
222bool wxRegion::Empty() const
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//-----------------------------------------------------------------------------
233// Tests
234//-----------------------------------------------------------------------------
235
236// Does the region contain the point (x,y)?
237wxRegionContain wxRegion::Contains(long x, long y) const
238{
239 if (!m_refData)
240 return wxOutRegion;
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{
251 if (!m_refData)
252 return wxOutRegion;
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{
263 if (!m_refData)
264 return wxOutRegion;
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{
281 if (!m_refData)
282 return wxOutRegion;
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
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
300///////////////////////////////////////////////////////////////////////////////
301// //
302// wxRegionIterator //
303// //
304///////////////////////////////////////////////////////////////////////////////
305
306/*
307 * Initialize empty iterator
308 */
309wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL)
310{
311}
312
313wxRegionIterator::~wxRegionIterator()
314{
315 if (m_rects)
316 delete[] m_rects;
317}
318
319/*
320 * Initialize iterator for region
321 */
322wxRegionIterator::wxRegionIterator(const wxRegion& region)
323{
324 m_rects = NULL;
325
326 Reset(region);
327}
328
329/*
330 * Reset iterator for a new /e region.
331 */
332void wxRegionIterator::Reset(const wxRegion& region)
333{
334 m_current = 0;
335 m_region = region;
336
337 if (m_rects)
338 delete[] m_rects;
339
340 m_rects = NULL;
341
342 if (m_region.Empty())
343 m_numRects = 0;
344 else
345 {
346#if defined(__WIN32__)
347 DWORD noBytes = ::GetRegionData(((wxRegionRefData*)region.m_refData)->m_region, 0, NULL);
348 RGNDATA *rgnData = (RGNDATA*) new char[noBytes];
349 ::GetRegionData(((wxRegionRefData*)region.m_refData)->m_region, noBytes, rgnData);
350
351 RGNDATAHEADER* header = (RGNDATAHEADER*) rgnData;
352
353 m_rects = new wxRect[header->nCount];
354
355 RECT* rect = (RECT*) ((char*)rgnData + sizeof(RGNDATAHEADER)) ;
356 size_t i;
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);
361 rect ++; // Advances pointer by sizeof(RECT)
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
381/*
382 * Increment iterator. The rectangle returned is the one after the
383 * incrementation.
384 */
385void wxRegionIterator::operator ++ ()
386{
387 if (m_current < m_numRects)
388 ++m_current;
389}
390
391/*
392 * Increment iterator. The rectangle returned is the one before the
393 * incrementation.
394 */
395void wxRegionIterator::operator ++ (int)
396{
397 if (m_current < m_numRects)
398 ++m_current;
399}
400
401long wxRegionIterator::GetX() const
402{
403 if (m_current < m_numRects)
404 return m_rects[m_current].x;
405 return 0;
406}
407
408long wxRegionIterator::GetY() const
409{
410 if (m_current < m_numRects)
411 return m_rects[m_current].y;
412 return 0;
413}
414
415long wxRegionIterator::GetW() const
416{
417 if (m_current < m_numRects)
418 return m_rects[m_current].width ;
419 return 0;
420}
421
422long wxRegionIterator::GetH() const
423{
424 if (m_current < m_numRects)
425 return m_rects[m_current].height;
426 return 0;
427}
428