]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk1/region.cpp
Include wx/checkbox.h according to precompiled headers of wx/wx.h (with other minor...
[wxWidgets.git] / src / gtk1 / region.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/gtk1/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/gtk1/private.h"
29
30
31// ----------------------------------------------------------------------------
32// wxGdkRegion: creates a new region in ctor and destroys in dtor
33// ----------------------------------------------------------------------------
34
35class wxGdkRegion
36{
37public:
38 wxGdkRegion() { m_region = gdk_region_new(); }
39 ~wxGdkRegion() { gdk_region_destroy(m_region); }
40
41 operator GdkRegion *() const { return m_region; }
42
43private:
44 GdkRegion *m_region;
45};
46
47
48// ----------------------------------------------------------------------------
49// wxRegionRefData: private class containing the information about the region
50// ----------------------------------------------------------------------------
51
52class wxRegionRefData : public wxObjectRefData
53{
54public:
55 wxRegionRefData()
56 {
57 m_region = NULL;
58 }
59
60 wxRegionRefData(const wxRegionRefData& refData)
61 : wxObjectRefData()
62 {
63 m_region = gdk_regions_union(wxGdkRegion(), refData.m_region);
64 }
65
66 ~wxRegionRefData()
67 {
68 if (m_region)
69 gdk_region_destroy( m_region );
70 }
71
72 GdkRegion *m_region;
73};
74
75// ----------------------------------------------------------------------------
76// macros
77// ----------------------------------------------------------------------------
78
79#define M_REGIONDATA ((wxRegionRefData *)m_refData)
80#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
81
82IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
83IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject)
84
85// ----------------------------------------------------------------------------
86// wxRegion construction
87// ----------------------------------------------------------------------------
88
89#define M_REGIONDATA ((wxRegionRefData *)m_refData)
90
91void wxRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
92{
93 GdkRectangle rect;
94 rect.x = x;
95 rect.y = y;
96 rect.width = w;
97 rect.height = h;
98
99 m_refData = new wxRegionRefData();
100
101 M_REGIONDATA->m_region = gdk_region_union_with_rect( wxGdkRegion(), &rect );
102}
103
104wxRegion::wxRegion( GdkRegion *region )
105{
106 m_refData = new wxRegionRefData();
107 M_REGIONDATA->m_region = gdk_regions_union(wxGdkRegion(), region);
108}
109
110wxRegion::wxRegion( size_t n, const wxPoint *points, int fillStyle )
111{
112 GdkPoint *gdkpoints = new GdkPoint[n];
113 for ( size_t i = 0 ; i < n ; i++ )
114 {
115 gdkpoints[i].x = points[i].x;
116 gdkpoints[i].y = points[i].y;
117 }
118
119 m_refData = new wxRegionRefData();
120
121 GdkRegion* reg = gdk_region_polygon
122 (
123 gdkpoints,
124 n,
125 fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
126 : GDK_EVEN_ODD_RULE
127 );
128
129 M_REGIONDATA->m_region = reg;
130
131 delete [] gdkpoints;
132}
133
134wxRegion::~wxRegion()
135{
136 // m_refData unrefed in ~wxObject
137}
138
139wxObjectRefData *wxRegion::CreateRefData() const
140{
141 return new wxRegionRefData;
142}
143
144wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
145{
146 return new wxRegionRefData(*(wxRegionRefData *)data);
147}
148
149// ----------------------------------------------------------------------------
150// wxRegion comparison
151// ----------------------------------------------------------------------------
152
153bool wxRegion::operator==( const wxRegion& region ) const
154{
155 if (m_refData == region.m_refData) return TRUE;
156
157 if (!m_refData || !region.m_refData) return FALSE;
158
159 // compare the regions themselves, not the pointers to ref data!
160 return gdk_region_equal(M_REGIONDATA->m_region,
161 M_REGIONDATA_OF(region)->m_region);
162}
163
164// ----------------------------------------------------------------------------
165// wxRegion operations
166// ----------------------------------------------------------------------------
167
168void wxRegion::Clear()
169{
170 UnRef();
171}
172
173bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
174{
175 // workaround for a strange GTK/X11 bug: taking union with an empty
176 // rectangle results in an empty region which is definitely not what we
177 // want
178 if ( !width || !height )
179 return TRUE;
180
181 if ( !m_refData )
182 {
183 InitRect(x, y, width, height);
184 }
185 else
186 {
187 AllocExclusive();
188
189 GdkRectangle rect;
190 rect.x = x;
191 rect.y = y;
192 rect.width = width;
193 rect.height = height;
194
195 GdkRegion *reg = gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
196 gdk_region_destroy( M_REGIONDATA->m_region );
197 M_REGIONDATA->m_region = reg;
198 }
199
200 return TRUE;
201}
202
203bool wxRegion::Union( const wxRect& rect )
204{
205 return Union( rect.x, rect.y, rect.width, rect.height );
206}
207
208bool wxRegion::Union( const wxRegion& region )
209{
210 if (region.IsNull())
211 return FALSE;
212
213 if (!m_refData)
214 {
215 m_refData = new wxRegionRefData();
216 M_REGIONDATA->m_region = gdk_region_new();
217 }
218 else
219 {
220 AllocExclusive();
221 }
222
223 GdkRegion *reg = gdk_regions_union( M_REGIONDATA->m_region, region.GetRegion() );
224 gdk_region_destroy( M_REGIONDATA->m_region );
225 M_REGIONDATA->m_region = reg;
226
227 return TRUE;
228}
229
230bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
231{
232 wxRegion reg( x, y, width, height );
233
234 return Intersect( reg );
235}
236
237bool wxRegion::Intersect( const wxRect& rect )
238{
239 wxRegion reg( rect );
240
241 return Intersect( reg );
242}
243
244bool wxRegion::Intersect( const wxRegion& region )
245{
246 if (region.IsNull())
247 return FALSE;
248
249 if (!m_refData)
250 {
251 // intersecting with invalid region doesn't make sense
252 return FALSE;
253 }
254
255 AllocExclusive();
256
257 GdkRegion *reg = gdk_regions_intersect( M_REGIONDATA->m_region, region.GetRegion() );
258 gdk_region_destroy( M_REGIONDATA->m_region );
259 M_REGIONDATA->m_region = reg;
260
261 return TRUE;
262}
263
264bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
265{
266 wxRegion reg( x, y, width, height );
267 return Subtract( reg );
268}
269
270bool wxRegion::Subtract( const wxRect& rect )
271{
272 wxRegion reg( rect );
273 return Subtract( reg );
274}
275
276bool wxRegion::Subtract( const wxRegion& region )
277{
278 if (region.IsNull())
279 return FALSE;
280
281 if (!m_refData)
282 {
283 // subtracting from an invalid region doesn't make sense
284 return FALSE;
285 }
286
287 AllocExclusive();
288
289 GdkRegion *reg = gdk_regions_subtract( M_REGIONDATA->m_region, region.GetRegion() );
290 gdk_region_destroy( M_REGIONDATA->m_region );
291 M_REGIONDATA->m_region = reg;
292
293 return TRUE;
294}
295
296bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
297{
298 wxRegion reg( x, y, width, height );
299 return Xor( reg );
300}
301
302bool wxRegion::Xor( const wxRect& rect )
303{
304 wxRegion reg( rect );
305 return Xor( reg );
306}
307
308bool wxRegion::Xor( const wxRegion& region )
309{
310 if (region.IsNull())
311 return FALSE;
312
313 if (!m_refData)
314 {
315 return FALSE;
316 }
317
318 AllocExclusive();
319
320 GdkRegion *reg = gdk_regions_xor( M_REGIONDATA->m_region, region.GetRegion() );
321 gdk_region_destroy( M_REGIONDATA->m_region );
322 M_REGIONDATA->m_region = reg;
323
324 return TRUE;
325}
326
327bool wxRegion::Offset( wxCoord x, wxCoord y )
328{
329 if (!m_refData)
330 return FALSE;
331
332 AllocExclusive();
333
334 gdk_region_offset( M_REGIONDATA->m_region, x, y );
335
336 return TRUE;
337}
338
339// ----------------------------------------------------------------------------
340// wxRegion tests
341// ----------------------------------------------------------------------------
342
343void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
344{
345 if ( m_refData )
346 {
347 GdkRectangle rect;
348 gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
349 x = rect.x;
350 y = rect.y;
351 w = rect.width;
352 h = rect.height;
353 }
354 else
355 {
356 x = 0;
357 y = 0;
358 w = -1;
359 h = -1;
360 }
361}
362
363wxRect wxRegion::GetBox() const
364{
365 wxCoord x, y, w, h;
366 GetBox( x, y, w, h );
367 return wxRect( x, y, w, h );
368}
369
370bool wxRegion::Empty() const
371{
372 if (!m_refData)
373 return TRUE;
374
375 return gdk_region_empty( M_REGIONDATA->m_region );
376}
377
378wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
379{
380 if (!m_refData)
381 return wxOutRegion;
382
383 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
384 return wxInRegion;
385 else
386 return wxOutRegion;
387}
388
389wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
390{
391 if (!m_refData)
392 return wxOutRegion;
393
394 GdkRectangle rect;
395 rect.x = x;
396 rect.y = y;
397 rect.width = w;
398 rect.height = h;
399 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
400 switch (res)
401 {
402 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
403 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
404 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
405 }
406 return wxOutRegion;
407}
408
409wxRegionContain wxRegion::Contains(const wxPoint& pt) const
410{
411 return Contains( pt.x, pt.y );
412}
413
414wxRegionContain wxRegion::Contains(const wxRect& rect) const
415{
416 return Contains( rect.x, rect.y, rect.width, rect.height );
417}
418
419GdkRegion *wxRegion::GetRegion() const
420{
421 if (!m_refData)
422 return (GdkRegion*) NULL;
423
424 return M_REGIONDATA->m_region;
425}
426
427// ----------------------------------------------------------------------------
428// wxRegionIterator
429// ----------------------------------------------------------------------------
430
431// the following structures must match the private structures
432// in X11 region code ( xc/lib/X11/region.h )
433
434// this makes the Region type transparent
435// and we have access to the region rectangles
436
437#include <gdk/gdkprivate.h>
438
439struct _XBox {
440 short x1, x2, y1, y2;
441};
442
443struct _XRegion {
444 long size , numRects;
445 _XBox *rects, extents;
446};
447
448
449class wxRIRefData: public wxObjectRefData
450{
451public:
452 wxRIRefData() { Init(); }
453 virtual ~wxRIRefData();
454
455 void CreateRects( const wxRegion& r );
456
457 void Init() { m_rects = NULL; m_numRects = 0; }
458
459 wxRect *m_rects;
460 size_t m_numRects;
461};
462
463wxRIRefData::~wxRIRefData()
464{
465 delete [] m_rects;
466}
467
468void wxRIRefData::CreateRects( const wxRegion& region )
469{
470 delete [] m_rects;
471
472 Init();
473
474 GdkRegion *gdkregion = region.GetRegion();
475 if (!gdkregion)
476 return;
477
478 Region r = ((GdkRegionPrivate *)gdkregion)->xregion;
479 if (r)
480 {
481 m_numRects = r->numRects;
482 if (m_numRects)
483 {
484 m_rects = new wxRect[m_numRects];
485 for (size_t i=0; i < m_numRects; ++i)
486 {
487 _XBox &xr = r->rects[i];
488 wxRect &wr = m_rects[i];
489 wr.x = xr.x1;
490 wr.y = xr.y1;
491 wr.width = xr.x2-xr.x1;
492 wr.height = xr.y2-xr.y1;
493 }
494 }
495 }
496}
497
498wxRegionIterator::wxRegionIterator()
499{
500 m_refData = new wxRIRefData();
501 Reset();
502}
503
504wxRegionIterator::wxRegionIterator( const wxRegion& region )
505{
506 m_refData = new wxRIRefData();
507 Reset(region);
508}
509
510void wxRegionIterator::Reset( const wxRegion& region )
511{
512 m_region = region;
513 ((wxRIRefData*)m_refData)->CreateRects(region);
514 Reset();
515}
516
517bool wxRegionIterator::HaveRects() const
518{
519 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
520}
521
522wxRegionIterator& wxRegionIterator::operator ++ ()
523{
524 if (HaveRects())
525 ++m_current;
526
527 return *this;
528}
529
530wxRegionIterator wxRegionIterator::operator ++ (int)
531{
532 wxRegionIterator tmp = *this;
533 if (HaveRects())
534 ++m_current;
535
536 return tmp;
537}
538
539wxCoord wxRegionIterator::GetX() const
540{
541 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
542
543 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
544}
545
546wxCoord wxRegionIterator::GetY() const
547{
548 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
549
550 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
551}
552
553wxCoord wxRegionIterator::GetW() const
554{
555 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
556
557 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
558}
559
560wxCoord wxRegionIterator::GetH() const
561{
562 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
563
564 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
565}
566
567wxRect wxRegionIterator::GetRect() const
568{
569 wxRect r;
570 if( HaveRects() )
571 r = ((wxRIRefData*)m_refData)->m_rects[m_current];
572
573 return r;
574}