]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk/region.cpp
Disable some wxWebView tests that fail on the buildbot but not locally.
[wxWidgets.git] / src / gtk / region.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/gtk/region.cpp
3// Purpose:
4// Author: Robert Roebling
5// Modified: VZ at 05.10.00: use AllocExclusive(), comparison fixed
6// Id: $Id$
7// Copyright: (c) 1998 Robert Roebling
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#include "wx/region.h"
23
24#ifndef WX_PRECOMP
25 #include "wx/log.h"
26#endif
27
28#include "wx/gtk/private.h"
29
30
31// ----------------------------------------------------------------------------
32// wxRegionRefData: private class containing the information about the region
33// ----------------------------------------------------------------------------
34
35class wxRegionRefData : public wxGDIRefData
36{
37public:
38 wxRegionRefData()
39 {
40 m_region = NULL;
41 }
42
43 wxRegionRefData(const wxRegionRefData& refData)
44 : wxGDIRefData()
45 {
46 m_region = gdk_region_copy(refData.m_region);
47 }
48
49 virtual ~wxRegionRefData()
50 {
51 if (m_region)
52 gdk_region_destroy( m_region );
53 }
54
55 GdkRegion *m_region;
56};
57
58// ----------------------------------------------------------------------------
59// macros
60// ----------------------------------------------------------------------------
61
62#define M_REGIONDATA ((wxRegionRefData *)m_refData)
63#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
64
65IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
66IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject)
67
68// ----------------------------------------------------------------------------
69// wxRegion construction
70// ----------------------------------------------------------------------------
71
72#define M_REGIONDATA ((wxRegionRefData *)m_refData)
73
74void wxRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
75{
76 GdkRectangle rect;
77 rect.x = x;
78 rect.y = y;
79 rect.width = w;
80 rect.height = h;
81
82 m_refData = new wxRegionRefData();
83
84 M_REGIONDATA->m_region = gdk_region_rectangle( &rect );
85}
86
87wxRegion::wxRegion( GdkRegion *region )
88{
89 m_refData = new wxRegionRefData();
90 M_REGIONDATA->m_region = gdk_region_copy( region );
91}
92
93wxRegion::wxRegion( size_t n, const wxPoint *points,
94 wxPolygonFillMode fillStyle )
95{
96 GdkPoint *gdkpoints = new GdkPoint[n];
97 for ( size_t i = 0 ; i < n ; i++ )
98 {
99 gdkpoints[i].x = points[i].x;
100 gdkpoints[i].y = points[i].y;
101 }
102
103 m_refData = new wxRegionRefData();
104
105 GdkRegion* reg = gdk_region_polygon
106 (
107 gdkpoints,
108 n,
109 fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
110 : GDK_EVEN_ODD_RULE
111 );
112
113 M_REGIONDATA->m_region = reg;
114
115 delete [] gdkpoints;
116}
117
118wxRegion::~wxRegion()
119{
120 // m_refData unrefed in ~wxObject
121}
122
123wxGDIRefData *wxRegion::CreateGDIRefData() const
124{
125 return new wxRegionRefData;
126}
127
128wxGDIRefData *wxRegion::CloneGDIRefData(const wxGDIRefData *data) const
129{
130 return new wxRegionRefData(*(wxRegionRefData *)data);
131}
132
133// ----------------------------------------------------------------------------
134// wxRegion comparison
135// ----------------------------------------------------------------------------
136
137bool wxRegion::DoIsEqual(const wxRegion& region) const
138{
139 return gdk_region_equal(M_REGIONDATA->m_region,
140 M_REGIONDATA_OF(region)->m_region);
141}
142
143// ----------------------------------------------------------------------------
144// wxRegion operations
145// ----------------------------------------------------------------------------
146
147void wxRegion::Clear()
148{
149 UnRef();
150}
151
152bool wxRegion::DoUnionWithRect(const wxRect& r)
153{
154 // workaround for a strange GTK/X11 bug: taking union with an empty
155 // rectangle results in an empty region which is definitely not what we
156 // want
157 if ( r.IsEmpty() )
158 return true;
159
160 if ( !m_refData )
161 {
162 InitRect(r.x, r.y, r.width, r.height);
163 }
164 else
165 {
166 AllocExclusive();
167
168 GdkRectangle rect;
169 rect.x = r.x;
170 rect.y = r.y;
171 rect.width = r.width;
172 rect.height = r.height;
173
174 gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
175 }
176
177 return true;
178}
179
180bool wxRegion::DoUnionWithRegion( const wxRegion& region )
181{
182 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
183
184 if (!m_refData)
185 {
186 m_refData = new wxRegionRefData(*M_REGIONDATA_OF(region));
187 }
188 else
189 {
190 AllocExclusive();
191 gdk_region_union( M_REGIONDATA->m_region, region.GetRegion() );
192 }
193
194 return true;
195}
196
197bool wxRegion::DoIntersect( const wxRegion& region )
198{
199 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
200
201 if (!m_refData)
202 {
203 // intersecting with invalid region doesn't make sense
204 return false;
205 }
206
207 AllocExclusive();
208
209 gdk_region_intersect( M_REGIONDATA->m_region, region.GetRegion() );
210
211 return true;
212}
213
214bool wxRegion::DoSubtract( const wxRegion& region )
215{
216 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
217
218 if (!m_refData)
219 {
220 // subtracting from an invalid region doesn't make sense
221 return false;
222 }
223
224 AllocExclusive();
225
226 gdk_region_subtract( M_REGIONDATA->m_region, region.GetRegion() );
227
228 return true;
229}
230
231bool wxRegion::DoXor( const wxRegion& region )
232{
233 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
234
235 if (!m_refData)
236 {
237 // XOR-ing with an invalid region is the same as XOR-ing with an empty
238 // one, i.e. it is simply a copy.
239 m_refData = new wxRegionRefData(*M_REGIONDATA_OF(region));
240 }
241 else
242 {
243 AllocExclusive();
244
245 gdk_region_xor( M_REGIONDATA->m_region, region.GetRegion() );
246 }
247
248 return true;
249}
250
251bool wxRegion::DoOffset( wxCoord x, wxCoord y )
252{
253 wxCHECK_MSG( m_refData, false, wxS("invalid region") );
254
255 AllocExclusive();
256
257 gdk_region_offset( M_REGIONDATA->m_region, x, y );
258
259 return true;
260}
261
262// ----------------------------------------------------------------------------
263// wxRegion tests
264// ----------------------------------------------------------------------------
265
266bool wxRegion::DoGetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
267{
268 if ( m_refData )
269 {
270 GdkRectangle rect;
271 gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
272 x = rect.x;
273 y = rect.y;
274 w = rect.width;
275 h = rect.height;
276
277 return true;
278 }
279 else
280 {
281 x = 0;
282 y = 0;
283 w = -1;
284 h = -1;
285
286 return false;
287 }
288}
289
290bool wxRegion::IsEmpty() const
291{
292 if (!m_refData)
293 return true;
294
295 return gdk_region_empty( M_REGIONDATA->m_region );
296}
297
298wxRegionContain wxRegion::DoContainsPoint( wxCoord x, wxCoord y ) const
299{
300 if (!m_refData)
301 return wxOutRegion;
302
303 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
304 return wxInRegion;
305 else
306 return wxOutRegion;
307}
308
309wxRegionContain wxRegion::DoContainsRect(const wxRect& r) const
310{
311 if (!m_refData)
312 return wxOutRegion;
313
314 GdkRectangle rect;
315 rect.x = r.x;
316 rect.y = r.y;
317 rect.width = r.width;
318 rect.height = r.height;
319 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
320 switch (res)
321 {
322 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
323 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
324 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
325 }
326 return wxOutRegion;
327}
328
329GdkRegion *wxRegion::GetRegion() const
330{
331 if (!m_refData)
332 return NULL;
333
334 return M_REGIONDATA->m_region;
335}
336
337// ----------------------------------------------------------------------------
338// wxRegionIterator
339// ----------------------------------------------------------------------------
340
341wxRegionIterator::wxRegionIterator()
342{
343 Init();
344 Reset();
345}
346
347wxRegionIterator::wxRegionIterator( const wxRegion& region )
348{
349 Init();
350 Reset(region);
351}
352
353void wxRegionIterator::Init()
354{
355 m_rects = NULL;
356 m_numRects = 0;
357}
358
359wxRegionIterator::~wxRegionIterator()
360{
361 wxDELETEA(m_rects);
362}
363
364void wxRegionIterator::CreateRects( const wxRegion& region )
365{
366 wxDELETEA(m_rects);
367 m_numRects = 0;
368
369 GdkRegion *gdkregion = region.GetRegion();
370 if (!gdkregion)
371 return;
372
373 GdkRectangle* gdkrects;
374 gdk_region_get_rectangles(gdkregion, &gdkrects, &m_numRects);
375
376 if (m_numRects)
377 {
378 m_rects = new wxRect[m_numRects];
379 for (int i = 0; i < m_numRects; ++i)
380 {
381 GdkRectangle &gr = gdkrects[i];
382 wxRect &wr = m_rects[i];
383 wr.x = gr.x;
384 wr.y = gr.y;
385 wr.width = gr.width;
386 wr.height = gr.height;
387 }
388 }
389 g_free( gdkrects );
390}
391
392void wxRegionIterator::Reset( const wxRegion& region )
393{
394 m_region = region;
395 CreateRects(region);
396 Reset();
397}
398
399bool wxRegionIterator::HaveRects() const
400{
401 return m_current < m_numRects;
402}
403
404wxRegionIterator& wxRegionIterator::operator ++ ()
405{
406 if (HaveRects())
407 ++m_current;
408
409 return *this;
410}
411
412wxRegionIterator wxRegionIterator::operator ++ (int)
413{
414 wxRegionIterator tmp = *this;
415
416 if (HaveRects())
417 ++m_current;
418
419 return tmp;
420}
421
422wxCoord wxRegionIterator::GetX() const
423{
424 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
425
426 return m_rects[m_current].x;
427}
428
429wxCoord wxRegionIterator::GetY() const
430{
431 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
432
433 return m_rects[m_current].y;
434}
435
436wxCoord wxRegionIterator::GetW() const
437{
438 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
439
440 return m_rects[m_current].width;
441}
442
443wxCoord wxRegionIterator::GetH() const
444{
445 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
446
447 return m_rects[m_current].height;
448}
449
450wxRect wxRegionIterator::GetRect() const
451{
452 wxRect r;
453 if( HaveRects() )
454 r = m_rects[m_current];
455
456 return r;
457}
458
459wxRegionIterator& wxRegionIterator::operator=(const wxRegionIterator& ri)
460{
461 if (this != &ri)
462 {
463 wxDELETEA(m_rects);
464
465 m_current = ri.m_current;
466 m_numRects = ri.m_numRects;
467 if ( m_numRects )
468 {
469 m_rects = new wxRect[m_numRects];
470 memcpy(m_rects, ri.m_rects, m_numRects * sizeof m_rects[0]);
471 }
472 }
473 return *this;
474}