1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/region.cpp
4 // Author: Robert Roebling
5 // Modified: VZ at 05.10.00: use AllocExclusive(), comparison fixed
7 // Copyright: (c) 1998 Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
16 #pragma implementation "region.h"
19 // ----------------------------------------------------------------------------
21 // ----------------------------------------------------------------------------
23 // For compilers that support precompilation, includes "wx.h".
24 #include "wx/wxprec.h"
26 #include "wx/region.h"
28 #include "wx/gtk/private.h"
32 // ----------------------------------------------------------------------------
33 // wxGdkRegion: creates a new region in ctor and destroys in dtor
34 // ----------------------------------------------------------------------------
39 wxGdkRegion() { m_region
= gdk_region_new(); }
40 ~wxGdkRegion() { gdk_region_destroy(m_region
); }
42 operator GdkRegion
*() const { return m_region
; }
50 // ----------------------------------------------------------------------------
51 // wxRegionRefData: private class containing the information about the region
52 // ----------------------------------------------------------------------------
54 class wxRegionRefData
: public wxObjectRefData
62 wxRegionRefData(const wxRegionRefData
& refData
)
66 m_region
= gdk_region_copy(refData
.m_region
);
68 m_region
= gdk_regions_union(wxGdkRegion(), refData
.m_region
);
75 gdk_region_destroy( m_region
);
81 // ----------------------------------------------------------------------------
83 // ----------------------------------------------------------------------------
85 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
86 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
88 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
)
89 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
)
91 // ----------------------------------------------------------------------------
92 // wxRegion construction
93 // ----------------------------------------------------------------------------
95 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
97 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
105 m_refData
= new wxRegionRefData();
108 M_REGIONDATA
->m_region
= gdk_region_rectangle( &rect
);
110 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( wxGdkRegion(), &rect
);
114 wxRegion::wxRegion( GdkRegion
*region
)
116 m_refData
= new wxRegionRefData();
118 M_REGIONDATA
->m_region
= gdk_region_copy( region
);
120 M_REGIONDATA
->m_region
= gdk_regions_union(wxGdkRegion(), region
);
124 wxRegion::wxRegion( size_t n
, const wxPoint
*points
, int fillStyle
)
126 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
127 for ( size_t i
= 0 ; i
< n
; i
++ )
129 gdkpoints
[i
].x
= points
[i
].x
;
130 gdkpoints
[i
].y
= points
[i
].y
;
133 m_refData
= new wxRegionRefData();
135 GdkRegion
* reg
= gdk_region_polygon
139 fillStyle
== wxWINDING_RULE
? GDK_WINDING_RULE
143 M_REGIONDATA
->m_region
= reg
;
148 wxRegion::~wxRegion()
150 // m_refData unrefed in ~wxObject
153 wxObjectRefData
*wxRegion::CreateRefData() const
155 return new wxRegionRefData
;
158 wxObjectRefData
*wxRegion::CloneRefData(const wxObjectRefData
*data
) const
160 return new wxRegionRefData(*(wxRegionRefData
*)data
);
163 // ----------------------------------------------------------------------------
164 // wxRegion comparison
165 // ----------------------------------------------------------------------------
167 bool wxRegion::operator==( const wxRegion
& region
)
169 if (m_refData
== region
.m_refData
) return TRUE
;
171 if (!m_refData
|| !region
.m_refData
) return FALSE
;
173 // compare the regions themselves, not the pointers to ref data!
174 return gdk_region_equal(M_REGIONDATA
->m_region
,
175 M_REGIONDATA_OF(region
)->m_region
);
178 // ----------------------------------------------------------------------------
179 // wxRegion operations
180 // ----------------------------------------------------------------------------
182 void wxRegion::Clear()
187 bool wxRegion::Union( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
189 // workaround for a strange GTK/X11 bug: taking union with an empty
190 // rectangle results in an empty region which is definitely not what we
192 if ( !width
|| !height
)
197 InitRect(x
, y
, width
, height
);
207 rect
.height
= height
;
210 gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
212 GdkRegion
*reg
= gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
213 gdk_region_destroy( M_REGIONDATA
->m_region
);
214 M_REGIONDATA
->m_region
= reg
;
221 bool wxRegion::Union( const wxRect
& rect
)
223 return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
226 bool wxRegion::Union( const wxRegion
& region
)
233 m_refData
= new wxRegionRefData();
234 M_REGIONDATA
->m_region
= gdk_region_new();
242 gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
244 GdkRegion
*reg
= gdk_regions_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
245 gdk_region_destroy( M_REGIONDATA
->m_region
);
246 M_REGIONDATA
->m_region
= reg
;
252 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
254 wxRegion
reg( x
, y
, width
, height
);
256 return Intersect( reg
);
259 bool wxRegion::Intersect( const wxRect
& rect
)
261 wxRegion
reg( rect
);
263 return Intersect( reg
);
266 bool wxRegion::Intersect( const wxRegion
& region
)
273 // intersecting with invalid region doesn't make sense
280 gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
282 GdkRegion
*reg
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
283 gdk_region_destroy( M_REGIONDATA
->m_region
);
284 M_REGIONDATA
->m_region
= reg
;
290 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
292 wxRegion
reg( x
, y
, width
, height
);
293 return Subtract( reg
);
296 bool wxRegion::Subtract( const wxRect
& rect
)
298 wxRegion
reg( rect
);
299 return Subtract( reg
);
302 bool wxRegion::Subtract( const wxRegion
& region
)
309 // subtracting from an invalid region doesn't make sense
316 gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
318 GdkRegion
*reg
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
319 gdk_region_destroy( M_REGIONDATA
->m_region
);
320 M_REGIONDATA
->m_region
= reg
;
326 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
328 wxRegion
reg( x
, y
, width
, height
);
332 bool wxRegion::Xor( const wxRect
& rect
)
334 wxRegion
reg( rect
);
338 bool wxRegion::Xor( const wxRegion
& region
)
351 gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
353 GdkRegion
*reg
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
354 gdk_region_destroy( M_REGIONDATA
->m_region
);
355 M_REGIONDATA
->m_region
= reg
;
361 bool wxRegion::Offset( wxCoord x
, wxCoord y
)
368 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
373 // ----------------------------------------------------------------------------
375 // ----------------------------------------------------------------------------
377 void wxRegion::GetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
382 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
397 wxRect
wxRegion::GetBox() const
400 GetBox( x
, y
, w
, h
);
401 return wxRect( x
, y
, w
, h
);
404 bool wxRegion::Empty() const
409 return gdk_region_empty( M_REGIONDATA
->m_region
);
412 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
) const
417 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
423 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
433 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
436 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
437 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
438 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
443 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
445 return Contains( pt
.x
, pt
.y
);
448 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
450 return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
453 GdkRegion
*wxRegion::GetRegion() const
456 return (GdkRegion
*) NULL
;
458 return M_REGIONDATA
->m_region
;
461 // ----------------------------------------------------------------------------
463 // ----------------------------------------------------------------------------
467 // the following structures must match the private structures
468 // in X11 region code ( xc/lib/X11/region.h )
470 // this makes the Region type transparent
471 // and we have access to the region rectangles
473 #include <gdk/gdkprivate.h>
476 short x1
, x2
, y1
, y2
;
480 long size
, numRects
;
481 _XBox
*rects
, extents
;
486 class wxRIRefData
: public wxObjectRefData
489 wxRIRefData() { Init(); }
490 virtual ~wxRIRefData();
492 void CreateRects( const wxRegion
& r
);
494 void Init() { m_rects
= NULL
; m_numRects
= 0; }
500 wxRIRefData::~wxRIRefData()
505 void wxRIRefData::CreateRects( const wxRegion
& region
)
511 GdkRegion
*gdkregion
= region
.GetRegion();
516 GdkRectangle
*gdkrects
= NULL
;
518 gdk_region_get_rectangles( gdkregion
, &gdkrects
, &numRects
);
520 m_numRects
= numRects
;
523 m_rects
= new wxRect
[m_numRects
];
524 for (size_t i
=0; i
< m_numRects
; ++i
)
526 GdkRectangle
&gr
= gdkrects
[i
];
527 wxRect
&wr
= m_rects
[i
];
531 wr
.height
= gr
.height
;
536 Region r
= ((GdkRegionPrivate
*)gdkregion
)->xregion
;
539 m_numRects
= r
->numRects
;
542 m_rects
= new wxRect
[m_numRects
];
543 for (size_t i
=0; i
< m_numRects
; ++i
)
545 _XBox
&xr
= r
->rects
[i
];
546 wxRect
&wr
= m_rects
[i
];
549 wr
.width
= xr
.x2
-xr
.x1
;
550 wr
.height
= xr
.y2
-xr
.y1
;
554 #endif // GTK+ 2.0/1.x
557 wxRegionIterator::wxRegionIterator()
559 m_refData
= new wxRIRefData();
563 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
565 m_refData
= new wxRIRefData();
569 void wxRegionIterator::Reset( const wxRegion
& region
)
572 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
576 bool wxRegionIterator::HaveRects() const
578 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
581 wxRegionIterator
& wxRegionIterator::operator ++ ()
589 wxRegionIterator
wxRegionIterator::operator ++ (int)
591 wxRegionIterator tmp
= *this;
598 wxCoord
wxRegionIterator::GetX() const
600 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
602 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
605 wxCoord
wxRegionIterator::GetY() const
607 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
609 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
612 wxCoord
wxRegionIterator::GetW() const
614 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
616 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
619 wxCoord
wxRegionIterator::GetH() const
621 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
623 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;
626 wxRect
wxRegionIterator::GetRect() const
630 r
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];