1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk1/region.cpp
4 // Author: Robert Roebling
5 // Modified: VZ at 05.10.00: use AllocExclusive(), comparison fixed
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 // For compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
21 #include "wx/region.h"
27 #include "wx/gtk1/private.h"
30 // ----------------------------------------------------------------------------
31 // wxGdkRegion: creates a new region in ctor and destroys in dtor
32 // ----------------------------------------------------------------------------
37 wxGdkRegion() { m_region
= gdk_region_new(); }
38 ~wxGdkRegion() { gdk_region_destroy(m_region
); }
40 operator GdkRegion
*() const { return m_region
; }
47 // ----------------------------------------------------------------------------
48 // wxRegionRefData: private class containing the information about the region
49 // ----------------------------------------------------------------------------
51 class wxRegionRefData
: public wxGDIRefData
59 wxRegionRefData(const wxRegionRefData
& refData
)
62 m_region
= gdk_regions_union(wxGdkRegion(), refData
.m_region
);
65 virtual ~wxRegionRefData()
68 gdk_region_destroy( m_region
);
74 // ----------------------------------------------------------------------------
76 // ----------------------------------------------------------------------------
78 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
79 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
81 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
)
82 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
)
84 // ----------------------------------------------------------------------------
85 // wxRegion construction
86 // ----------------------------------------------------------------------------
88 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
90 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
98 m_refData
= new wxRegionRefData();
100 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( wxGdkRegion(), &rect
);
103 wxRegion::wxRegion( GdkRegion
*region
)
105 m_refData
= new wxRegionRefData();
106 M_REGIONDATA
->m_region
= gdk_regions_union(wxGdkRegion(), region
);
109 wxRegion::wxRegion( size_t n
, const wxPoint
*points
, wxPolygonFillMode fillStyle
)
111 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
112 for ( size_t i
= 0 ; i
< n
; i
++ )
114 gdkpoints
[i
].x
= points
[i
].x
;
115 gdkpoints
[i
].y
= points
[i
].y
;
118 m_refData
= new wxRegionRefData();
120 GdkRegion
* reg
= gdk_region_polygon
124 fillStyle
== wxWINDING_RULE
? GDK_WINDING_RULE
128 M_REGIONDATA
->m_region
= reg
;
133 wxRegion::~wxRegion()
135 // m_refData unrefed in ~wxObject
138 wxGDIRefData
*wxRegion::CreateGDIRefData() const
140 return new wxRegionRefData
;
143 wxGDIRefData
*wxRegion::CloneGDIRefData(const wxGDIRefData
*data
) const
145 return new wxRegionRefData(*(wxRegionRefData
*)data
);
148 // ----------------------------------------------------------------------------
149 // wxRegion comparison
150 // ----------------------------------------------------------------------------
152 bool wxRegion::DoIsEqual(const wxRegion
& region
) const
154 return gdk_region_equal(M_REGIONDATA
->m_region
,
155 M_REGIONDATA_OF(region
)->m_region
);
158 // ----------------------------------------------------------------------------
159 // wxRegion operations
160 // ----------------------------------------------------------------------------
162 void wxRegion::Clear()
167 bool wxRegion::DoUnionWithRect(const wxRect
& r
)
169 // workaround for a strange GTK/X11 bug: taking union with an empty
170 // rectangle results in an empty region which is definitely not what we
177 InitRect(r
.x
, r
.y
, r
.width
, r
.height
);
186 rect
.width
= r
.width
;
187 rect
.height
= r
.height
;
189 GdkRegion
*reg
= gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
190 gdk_region_destroy( M_REGIONDATA
->m_region
);
191 M_REGIONDATA
->m_region
= reg
;
197 bool wxRegion::DoUnionWithRegion( const wxRegion
& region
)
204 m_refData
= new wxRegionRefData();
205 M_REGIONDATA
->m_region
= gdk_region_new();
212 GdkRegion
*reg
= gdk_regions_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
213 gdk_region_destroy( M_REGIONDATA
->m_region
);
214 M_REGIONDATA
->m_region
= reg
;
219 bool wxRegion::DoIntersect( const wxRegion
& region
)
221 wxCHECK_MSG( region
.IsOk(), false, wxT("invalid region") );
225 // intersecting with invalid region doesn't make sense
231 GdkRegion
*reg
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
232 gdk_region_destroy( M_REGIONDATA
->m_region
);
233 M_REGIONDATA
->m_region
= reg
;
238 bool wxRegion::DoSubtract( const wxRegion
& region
)
240 wxCHECK_MSG( region
.IsOk(), false, wxT("invalid region") );
244 // subtracting from an invalid region doesn't make sense
250 GdkRegion
*reg
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
251 gdk_region_destroy( M_REGIONDATA
->m_region
);
252 M_REGIONDATA
->m_region
= reg
;
257 bool wxRegion::DoXor( const wxRegion
& region
)
259 wxCHECK_MSG( region
.IsOk(), false, wxT("invalid region") );
268 GdkRegion
*reg
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
269 gdk_region_destroy( M_REGIONDATA
->m_region
);
270 M_REGIONDATA
->m_region
= reg
;
275 bool wxRegion::DoOffset( wxCoord x
, wxCoord y
)
282 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
287 // ----------------------------------------------------------------------------
289 // ----------------------------------------------------------------------------
291 bool wxRegion::DoGetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
296 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
315 bool wxRegion::IsEmpty() const
320 return gdk_region_empty( M_REGIONDATA
->m_region
);
323 wxRegionContain
wxRegion::DoContainsPoint( wxCoord x
, wxCoord y
) const
328 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
334 wxRegionContain
wxRegion::DoContainsRect(const wxRect
& r
) const
342 rect
.width
= r
.width
;
343 rect
.height
= r
.height
;
344 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
347 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
348 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
349 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
354 GdkRegion
*wxRegion::GetRegion() const
359 return M_REGIONDATA
->m_region
;
362 // ----------------------------------------------------------------------------
364 // ----------------------------------------------------------------------------
366 // the following structures must match the private structures
367 // in X11 region code ( xc/lib/X11/region.h )
369 // this makes the Region type transparent
370 // and we have access to the region rectangles
372 #include <gdk/gdkprivate.h>
375 short x1
, x2
, y1
, y2
;
379 long size
, numRects
;
380 _XBox
*rects
, extents
;
384 class wxRIRefData
: public wxGDIRefData
387 wxRIRefData() { Init(); }
388 virtual ~wxRIRefData();
390 void CreateRects( const wxRegion
& r
);
392 void Init() { m_rects
= NULL
; m_numRects
= 0; }
398 wxRIRefData::~wxRIRefData()
403 void wxRIRefData::CreateRects( const wxRegion
& region
)
409 GdkRegion
*gdkregion
= region
.GetRegion();
413 Region r
= ((GdkRegionPrivate
*)gdkregion
)->xregion
;
416 m_numRects
= r
->numRects
;
419 m_rects
= new wxRect
[m_numRects
];
420 for (size_t i
=0; i
< m_numRects
; ++i
)
422 _XBox
&xr
= r
->rects
[i
];
423 wxRect
&wr
= m_rects
[i
];
426 wr
.width
= xr
.x2
-xr
.x1
;
427 wr
.height
= xr
.y2
-xr
.y1
;
433 wxRegionIterator::wxRegionIterator()
435 m_refData
= new wxRIRefData();
439 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
441 m_refData
= new wxRIRefData();
445 void wxRegionIterator::Reset( const wxRegion
& region
)
448 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
452 bool wxRegionIterator::HaveRects() const
454 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
457 wxRegionIterator
& wxRegionIterator::operator ++ ()
465 wxRegionIterator
wxRegionIterator::operator ++ (int)
467 wxRegionIterator tmp
= *this;
474 wxCoord
wxRegionIterator::GetX() const
476 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
478 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
481 wxCoord
wxRegionIterator::GetY() const
483 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
485 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
488 wxCoord
wxRegionIterator::GetW() const
490 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
492 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
495 wxCoord
wxRegionIterator::GetH() const
497 wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
499 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;
502 wxRect
wxRegionIterator::GetRect() const
506 r
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];