1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk1/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 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
22 #include "wx/region.h"
28 #include "wx/gtk1/private.h"
31 // ----------------------------------------------------------------------------
32 // wxGdkRegion: creates a new region in ctor and destroys in dtor
33 // ----------------------------------------------------------------------------
38 wxGdkRegion() { m_region
= gdk_region_new(); }
39 ~wxGdkRegion() { gdk_region_destroy(m_region
); }
41 operator GdkRegion
*() const { return m_region
; }
48 // ----------------------------------------------------------------------------
49 // wxRegionRefData: private class containing the information about the region
50 // ----------------------------------------------------------------------------
52 class wxRegionRefData
: public wxGDIRefData
60 wxRegionRefData(const wxRegionRefData
& refData
)
63 m_region
= gdk_regions_union(wxGdkRegion(), refData
.m_region
);
66 virtual ~wxRegionRefData()
69 gdk_region_destroy( m_region
);
75 // ----------------------------------------------------------------------------
77 // ----------------------------------------------------------------------------
79 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
80 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
82 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
)
83 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
)
85 // ----------------------------------------------------------------------------
86 // wxRegion construction
87 // ----------------------------------------------------------------------------
89 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
91 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
99 m_refData
= new wxRegionRefData();
101 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( wxGdkRegion(), &rect
);
104 wxRegion::wxRegion( GdkRegion
*region
)
106 m_refData
= new wxRegionRefData();
107 M_REGIONDATA
->m_region
= gdk_regions_union(wxGdkRegion(), region
);
110 wxRegion::wxRegion( size_t n
, const wxPoint
*points
, wxPolygonFillMode fillStyle
)
112 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
113 for ( size_t i
= 0 ; i
< n
; i
++ )
115 gdkpoints
[i
].x
= points
[i
].x
;
116 gdkpoints
[i
].y
= points
[i
].y
;
119 m_refData
= new wxRegionRefData();
121 GdkRegion
* reg
= gdk_region_polygon
125 fillStyle
== wxWINDING_RULE
? GDK_WINDING_RULE
129 M_REGIONDATA
->m_region
= reg
;
134 wxRegion::~wxRegion()
136 // m_refData unrefed in ~wxObject
139 wxGDIRefData
*wxRegion::CreateGDIRefData() const
141 return new wxRegionRefData
;
144 wxGDIRefData
*wxRegion::CloneGDIRefData(const wxGDIRefData
*data
) const
146 return new wxRegionRefData(*(wxRegionRefData
*)data
);
149 // ----------------------------------------------------------------------------
150 // wxRegion comparison
151 // ----------------------------------------------------------------------------
153 bool wxRegion::DoIsEqual(const wxRegion
& region
) const
155 return gdk_region_equal(M_REGIONDATA
->m_region
,
156 M_REGIONDATA_OF(region
)->m_region
);
159 // ----------------------------------------------------------------------------
160 // wxRegion operations
161 // ----------------------------------------------------------------------------
163 void wxRegion::Clear()
168 bool wxRegion::DoUnionWithRect(const wxRect
& r
)
170 // workaround for a strange GTK/X11 bug: taking union with an empty
171 // rectangle results in an empty region which is definitely not what we
178 InitRect(r
.x
, r
.y
, r
.width
, r
.height
);
187 rect
.width
= r
.width
;
188 rect
.height
= r
.height
;
190 GdkRegion
*reg
= gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
191 gdk_region_destroy( M_REGIONDATA
->m_region
);
192 M_REGIONDATA
->m_region
= reg
;
198 bool wxRegion::DoUnionWithRegion( const wxRegion
& region
)
205 m_refData
= new wxRegionRefData();
206 M_REGIONDATA
->m_region
= gdk_region_new();
213 GdkRegion
*reg
= gdk_regions_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
214 gdk_region_destroy( M_REGIONDATA
->m_region
);
215 M_REGIONDATA
->m_region
= reg
;
220 bool wxRegion::DoIntersect( const wxRegion
& region
)
222 wxCHECK_MSG( region
.Ok(), false, _T("invalid region") );
226 // intersecting with invalid region doesn't make sense
232 GdkRegion
*reg
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
233 gdk_region_destroy( M_REGIONDATA
->m_region
);
234 M_REGIONDATA
->m_region
= reg
;
239 bool wxRegion::DoSubtract( const wxRegion
& region
)
241 wxCHECK_MSG( region
.Ok(), false, _T("invalid region") );
245 // subtracting from an invalid region doesn't make sense
251 GdkRegion
*reg
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
252 gdk_region_destroy( M_REGIONDATA
->m_region
);
253 M_REGIONDATA
->m_region
= reg
;
258 bool wxRegion::DoXor( const wxRegion
& region
)
260 wxCHECK_MSG( region
.Ok(), false, _T("invalid region") );
269 GdkRegion
*reg
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
270 gdk_region_destroy( M_REGIONDATA
->m_region
);
271 M_REGIONDATA
->m_region
= reg
;
276 bool wxRegion::DoOffset( wxCoord x
, wxCoord y
)
283 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
288 // ----------------------------------------------------------------------------
290 // ----------------------------------------------------------------------------
292 bool wxRegion::DoGetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
297 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
316 bool wxRegion::IsEmpty() const
321 return gdk_region_empty( M_REGIONDATA
->m_region
);
324 wxRegionContain
wxRegion::DoContainsPoint( wxCoord x
, wxCoord y
) const
329 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
335 wxRegionContain
wxRegion::DoContainsRect(const wxRect
& r
) const
343 rect
.width
= r
.width
;
344 rect
.height
= r
.height
;
345 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
348 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
349 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
350 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
355 GdkRegion
*wxRegion::GetRegion() const
358 return (GdkRegion
*) NULL
;
360 return M_REGIONDATA
->m_region
;
363 // ----------------------------------------------------------------------------
365 // ----------------------------------------------------------------------------
367 // the following structures must match the private structures
368 // in X11 region code ( xc/lib/X11/region.h )
370 // this makes the Region type transparent
371 // and we have access to the region rectangles
373 #include <gdk/gdkprivate.h>
376 short x1
, x2
, y1
, y2
;
380 long size
, numRects
;
381 _XBox
*rects
, extents
;
385 class wxRIRefData
: public wxGDIRefData
388 wxRIRefData() { Init(); }
389 virtual ~wxRIRefData();
391 void CreateRects( const wxRegion
& r
);
393 void Init() { m_rects
= NULL
; m_numRects
= 0; }
399 wxRIRefData::~wxRIRefData()
404 void wxRIRefData::CreateRects( const wxRegion
& region
)
410 GdkRegion
*gdkregion
= region
.GetRegion();
414 Region r
= ((GdkRegionPrivate
*)gdkregion
)->xregion
;
417 m_numRects
= r
->numRects
;
420 m_rects
= new wxRect
[m_numRects
];
421 for (size_t i
=0; i
< m_numRects
; ++i
)
423 _XBox
&xr
= r
->rects
[i
];
424 wxRect
&wr
= m_rects
[i
];
427 wr
.width
= xr
.x2
-xr
.x1
;
428 wr
.height
= xr
.y2
-xr
.y1
;
434 wxRegionIterator::wxRegionIterator()
436 m_refData
= new wxRIRefData();
440 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
442 m_refData
= new wxRIRefData();
446 void wxRegionIterator::Reset( const wxRegion
& region
)
449 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
453 bool wxRegionIterator::HaveRects() const
455 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
458 wxRegionIterator
& wxRegionIterator::operator ++ ()
466 wxRegionIterator
wxRegionIterator::operator ++ (int)
468 wxRegionIterator tmp
= *this;
475 wxCoord
wxRegionIterator::GetX() const
477 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
479 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
482 wxCoord
wxRegionIterator::GetY() const
484 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
486 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
489 wxCoord
wxRegionIterator::GetW() const
491 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
493 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
496 wxCoord
wxRegionIterator::GetH() const
498 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
500 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;
503 wxRect
wxRegionIterator::GetRect() const
507 r
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];