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 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
22 #include "wx/region.h"
24 #include "wx/gtk1/private.h"
27 // ----------------------------------------------------------------------------
28 // wxGdkRegion: creates a new region in ctor and destroys in dtor
29 // ----------------------------------------------------------------------------
34 wxGdkRegion() { m_region
= gdk_region_new(); }
35 ~wxGdkRegion() { gdk_region_destroy(m_region
); }
37 operator GdkRegion
*() const { return m_region
; }
44 // ----------------------------------------------------------------------------
45 // wxRegionRefData: private class containing the information about the region
46 // ----------------------------------------------------------------------------
48 class wxRegionRefData
: public wxObjectRefData
56 wxRegionRefData(const wxRegionRefData
& refData
)
59 m_region
= gdk_regions_union(wxGdkRegion(), refData
.m_region
);
65 gdk_region_destroy( m_region
);
71 // ----------------------------------------------------------------------------
73 // ----------------------------------------------------------------------------
75 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
76 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
78 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
)
79 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
)
81 // ----------------------------------------------------------------------------
82 // wxRegion construction
83 // ----------------------------------------------------------------------------
85 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
87 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
95 m_refData
= new wxRegionRefData();
97 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( wxGdkRegion(), &rect
);
100 wxRegion::wxRegion( GdkRegion
*region
)
102 m_refData
= new wxRegionRefData();
103 M_REGIONDATA
->m_region
= gdk_regions_union(wxGdkRegion(), region
);
106 wxRegion::wxRegion( size_t n
, const wxPoint
*points
, int fillStyle
)
108 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
109 for ( size_t i
= 0 ; i
< n
; i
++ )
111 gdkpoints
[i
].x
= points
[i
].x
;
112 gdkpoints
[i
].y
= points
[i
].y
;
115 m_refData
= new wxRegionRefData();
117 GdkRegion
* reg
= gdk_region_polygon
121 fillStyle
== wxWINDING_RULE
? GDK_WINDING_RULE
125 M_REGIONDATA
->m_region
= reg
;
130 wxRegion::~wxRegion()
132 // m_refData unrefed in ~wxObject
135 wxObjectRefData
*wxRegion::CreateRefData() const
137 return new wxRegionRefData
;
140 wxObjectRefData
*wxRegion::CloneRefData(const wxObjectRefData
*data
) const
142 return new wxRegionRefData(*(wxRegionRefData
*)data
);
145 // ----------------------------------------------------------------------------
146 // wxRegion comparison
147 // ----------------------------------------------------------------------------
149 bool wxRegion::operator==( const wxRegion
& region
) const
151 if (m_refData
== region
.m_refData
) return TRUE
;
153 if (!m_refData
|| !region
.m_refData
) return FALSE
;
155 // compare the regions themselves, not the pointers to ref data!
156 return gdk_region_equal(M_REGIONDATA
->m_region
,
157 M_REGIONDATA_OF(region
)->m_region
);
160 // ----------------------------------------------------------------------------
161 // wxRegion operations
162 // ----------------------------------------------------------------------------
164 void wxRegion::Clear()
169 bool wxRegion::Union( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
171 // workaround for a strange GTK/X11 bug: taking union with an empty
172 // rectangle results in an empty region which is definitely not what we
174 if ( !width
|| !height
)
179 InitRect(x
, y
, width
, height
);
189 rect
.height
= height
;
191 GdkRegion
*reg
= gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
192 gdk_region_destroy( M_REGIONDATA
->m_region
);
193 M_REGIONDATA
->m_region
= reg
;
199 bool wxRegion::Union( const wxRect
& rect
)
201 return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
204 bool wxRegion::Union( const wxRegion
& region
)
211 m_refData
= new wxRegionRefData();
212 M_REGIONDATA
->m_region
= gdk_region_new();
219 GdkRegion
*reg
= gdk_regions_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
220 gdk_region_destroy( M_REGIONDATA
->m_region
);
221 M_REGIONDATA
->m_region
= reg
;
226 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
228 wxRegion
reg( x
, y
, width
, height
);
230 return Intersect( reg
);
233 bool wxRegion::Intersect( const wxRect
& rect
)
235 wxRegion
reg( rect
);
237 return Intersect( reg
);
240 bool wxRegion::Intersect( const wxRegion
& region
)
247 // intersecting with invalid region doesn't make sense
253 GdkRegion
*reg
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
254 gdk_region_destroy( M_REGIONDATA
->m_region
);
255 M_REGIONDATA
->m_region
= reg
;
260 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
262 wxRegion
reg( x
, y
, width
, height
);
263 return Subtract( reg
);
266 bool wxRegion::Subtract( const wxRect
& rect
)
268 wxRegion
reg( rect
);
269 return Subtract( reg
);
272 bool wxRegion::Subtract( const wxRegion
& region
)
279 // subtracting from an invalid region doesn't make sense
285 GdkRegion
*reg
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
286 gdk_region_destroy( M_REGIONDATA
->m_region
);
287 M_REGIONDATA
->m_region
= reg
;
292 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
294 wxRegion
reg( x
, y
, width
, height
);
298 bool wxRegion::Xor( const wxRect
& rect
)
300 wxRegion
reg( rect
);
304 bool wxRegion::Xor( const wxRegion
& region
)
316 GdkRegion
*reg
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
317 gdk_region_destroy( M_REGIONDATA
->m_region
);
318 M_REGIONDATA
->m_region
= reg
;
323 bool wxRegion::Offset( wxCoord x
, wxCoord y
)
330 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
335 // ----------------------------------------------------------------------------
337 // ----------------------------------------------------------------------------
339 void wxRegion::GetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
344 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
359 wxRect
wxRegion::GetBox() const
362 GetBox( x
, y
, w
, h
);
363 return wxRect( x
, y
, w
, h
);
366 bool wxRegion::Empty() const
371 return gdk_region_empty( M_REGIONDATA
->m_region
);
374 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
) const
379 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
385 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
395 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
398 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
399 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
400 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
405 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
407 return Contains( pt
.x
, pt
.y
);
410 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
412 return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
415 GdkRegion
*wxRegion::GetRegion() const
418 return (GdkRegion
*) NULL
;
420 return M_REGIONDATA
->m_region
;
423 // ----------------------------------------------------------------------------
425 // ----------------------------------------------------------------------------
427 // the following structures must match the private structures
428 // in X11 region code ( xc/lib/X11/region.h )
430 // this makes the Region type transparent
431 // and we have access to the region rectangles
433 #include <gdk/gdkprivate.h>
436 short x1
, x2
, y1
, y2
;
440 long size
, numRects
;
441 _XBox
*rects
, extents
;
445 class wxRIRefData
: public wxObjectRefData
448 wxRIRefData() { Init(); }
449 virtual ~wxRIRefData();
451 void CreateRects( const wxRegion
& r
);
453 void Init() { m_rects
= NULL
; m_numRects
= 0; }
459 wxRIRefData::~wxRIRefData()
464 void wxRIRefData::CreateRects( const wxRegion
& region
)
470 GdkRegion
*gdkregion
= region
.GetRegion();
474 Region r
= ((GdkRegionPrivate
*)gdkregion
)->xregion
;
477 m_numRects
= r
->numRects
;
480 m_rects
= new wxRect
[m_numRects
];
481 for (size_t i
=0; i
< m_numRects
; ++i
)
483 _XBox
&xr
= r
->rects
[i
];
484 wxRect
&wr
= m_rects
[i
];
487 wr
.width
= xr
.x2
-xr
.x1
;
488 wr
.height
= xr
.y2
-xr
.y1
;
494 wxRegionIterator::wxRegionIterator()
496 m_refData
= new wxRIRefData();
500 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
502 m_refData
= new wxRIRefData();
506 void wxRegionIterator::Reset( const wxRegion
& region
)
509 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
513 bool wxRegionIterator::HaveRects() const
515 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
518 wxRegionIterator
& wxRegionIterator::operator ++ ()
526 wxRegionIterator
wxRegionIterator::operator ++ (int)
528 wxRegionIterator tmp
= *this;
535 wxCoord
wxRegionIterator::GetX() const
537 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
539 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
542 wxCoord
wxRegionIterator::GetY() const
544 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
546 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
549 wxCoord
wxRegionIterator::GetW() const
551 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
553 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
556 wxCoord
wxRegionIterator::GetH() const
558 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
560 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;
563 wxRect
wxRegionIterator::GetRect() const
567 r
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];