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/gtk/private.h"
28 // ----------------------------------------------------------------------------
29 // wxGdkRegion: creates a new region in ctor and destroys in dtor
30 // ----------------------------------------------------------------------------
35 wxGdkRegion() { m_region
= gdk_region_new(); }
36 ~wxGdkRegion() { gdk_region_destroy(m_region
); }
38 operator GdkRegion
*() const { return m_region
; }
46 // ----------------------------------------------------------------------------
47 // wxRegionRefData: private class containing the information about the region
48 // ----------------------------------------------------------------------------
50 class wxRegionRefData
: public wxObjectRefData
58 wxRegionRefData(const wxRegionRefData
& refData
)
62 m_region
= gdk_region_copy(refData
.m_region
);
64 m_region
= gdk_regions_union(wxGdkRegion(), refData
.m_region
);
71 gdk_region_destroy( m_region
);
77 // ----------------------------------------------------------------------------
79 // ----------------------------------------------------------------------------
81 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
82 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
84 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
)
85 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
)
87 // ----------------------------------------------------------------------------
88 // wxRegion construction
89 // ----------------------------------------------------------------------------
91 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
93 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
101 m_refData
= new wxRegionRefData();
104 M_REGIONDATA
->m_region
= gdk_region_rectangle( &rect
);
106 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( wxGdkRegion(), &rect
);
110 wxRegion::wxRegion( GdkRegion
*region
)
112 m_refData
= new wxRegionRefData();
114 M_REGIONDATA
->m_region
= gdk_region_copy( region
);
116 M_REGIONDATA
->m_region
= gdk_regions_union(wxGdkRegion(), region
);
120 wxRegion::wxRegion( size_t n
, const wxPoint
*points
, int fillStyle
)
122 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
123 for ( size_t i
= 0 ; i
< n
; i
++ )
125 gdkpoints
[i
].x
= points
[i
].x
;
126 gdkpoints
[i
].y
= points
[i
].y
;
129 m_refData
= new wxRegionRefData();
131 GdkRegion
* reg
= gdk_region_polygon
135 fillStyle
== wxWINDING_RULE
? GDK_WINDING_RULE
139 M_REGIONDATA
->m_region
= reg
;
144 wxRegion::~wxRegion()
146 // m_refData unrefed in ~wxObject
149 wxObjectRefData
*wxRegion::CreateRefData() const
151 return new wxRegionRefData
;
154 wxObjectRefData
*wxRegion::CloneRefData(const wxObjectRefData
*data
) const
156 return new wxRegionRefData(*(wxRegionRefData
*)data
);
159 // ----------------------------------------------------------------------------
160 // wxRegion comparison
161 // ----------------------------------------------------------------------------
163 bool wxRegion::operator==( const wxRegion
& region
) const
165 if (m_refData
== region
.m_refData
) return TRUE
;
167 if (!m_refData
|| !region
.m_refData
) return FALSE
;
169 // compare the regions themselves, not the pointers to ref data!
170 return gdk_region_equal(M_REGIONDATA
->m_region
,
171 M_REGIONDATA_OF(region
)->m_region
);
174 // ----------------------------------------------------------------------------
175 // wxRegion operations
176 // ----------------------------------------------------------------------------
178 void wxRegion::Clear()
183 bool wxRegion::Union( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
185 // workaround for a strange GTK/X11 bug: taking union with an empty
186 // rectangle results in an empty region which is definitely not what we
188 if ( !width
|| !height
)
193 InitRect(x
, y
, width
, height
);
203 rect
.height
= height
;
206 gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
208 GdkRegion
*reg
= gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
209 gdk_region_destroy( M_REGIONDATA
->m_region
);
210 M_REGIONDATA
->m_region
= reg
;
217 bool wxRegion::Union( const wxRect
& rect
)
219 return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
222 bool wxRegion::Union( const wxRegion
& region
)
229 m_refData
= new wxRegionRefData();
230 M_REGIONDATA
->m_region
= gdk_region_new();
238 gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
240 GdkRegion
*reg
= gdk_regions_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
241 gdk_region_destroy( M_REGIONDATA
->m_region
);
242 M_REGIONDATA
->m_region
= reg
;
248 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
250 wxRegion
reg( x
, y
, width
, height
);
252 return Intersect( reg
);
255 bool wxRegion::Intersect( const wxRect
& rect
)
257 wxRegion
reg( rect
);
259 return Intersect( reg
);
262 bool wxRegion::Intersect( const wxRegion
& region
)
269 // intersecting with invalid region doesn't make sense
276 gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
278 GdkRegion
*reg
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
279 gdk_region_destroy( M_REGIONDATA
->m_region
);
280 M_REGIONDATA
->m_region
= reg
;
286 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
288 wxRegion
reg( x
, y
, width
, height
);
289 return Subtract( reg
);
292 bool wxRegion::Subtract( const wxRect
& rect
)
294 wxRegion
reg( rect
);
295 return Subtract( reg
);
298 bool wxRegion::Subtract( const wxRegion
& region
)
305 // subtracting from an invalid region doesn't make sense
312 gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
314 GdkRegion
*reg
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
315 gdk_region_destroy( M_REGIONDATA
->m_region
);
316 M_REGIONDATA
->m_region
= reg
;
322 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
324 wxRegion
reg( x
, y
, width
, height
);
328 bool wxRegion::Xor( const wxRect
& rect
)
330 wxRegion
reg( rect
);
334 bool wxRegion::Xor( const wxRegion
& region
)
347 gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
349 GdkRegion
*reg
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
350 gdk_region_destroy( M_REGIONDATA
->m_region
);
351 M_REGIONDATA
->m_region
= reg
;
357 bool wxRegion::Offset( wxCoord x
, wxCoord y
)
364 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
369 // ----------------------------------------------------------------------------
371 // ----------------------------------------------------------------------------
373 void wxRegion::GetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
378 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
393 wxRect
wxRegion::GetBox() const
396 GetBox( x
, y
, w
, h
);
397 return wxRect( x
, y
, w
, h
);
400 bool wxRegion::Empty() const
405 return gdk_region_empty( M_REGIONDATA
->m_region
);
408 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
) const
413 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
419 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
429 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
432 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
433 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
434 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
439 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
441 return Contains( pt
.x
, pt
.y
);
444 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
446 return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
449 GdkRegion
*wxRegion::GetRegion() const
452 return (GdkRegion
*) NULL
;
454 return M_REGIONDATA
->m_region
;
457 // ----------------------------------------------------------------------------
459 // ----------------------------------------------------------------------------
463 // the following structures must match the private structures
464 // in X11 region code ( xc/lib/X11/region.h )
466 // this makes the Region type transparent
467 // and we have access to the region rectangles
469 #include <gdk/gdkprivate.h>
472 short x1
, x2
, y1
, y2
;
476 long size
, numRects
;
477 _XBox
*rects
, extents
;
482 class wxRIRefData
: public wxObjectRefData
485 wxRIRefData() { Init(); }
486 virtual ~wxRIRefData();
488 void CreateRects( const wxRegion
& r
);
490 void Init() { m_rects
= NULL
; m_numRects
= 0; }
496 wxRIRefData::~wxRIRefData()
501 void wxRIRefData::CreateRects( const wxRegion
& region
)
507 GdkRegion
*gdkregion
= region
.GetRegion();
512 GdkRectangle
*gdkrects
= NULL
;
514 gdk_region_get_rectangles( gdkregion
, &gdkrects
, &numRects
);
516 m_numRects
= numRects
;
519 m_rects
= new wxRect
[m_numRects
];
520 for (size_t i
=0; i
< m_numRects
; ++i
)
522 GdkRectangle
&gr
= gdkrects
[i
];
523 wxRect
&wr
= m_rects
[i
];
527 wr
.height
= gr
.height
;
532 Region r
= ((GdkRegionPrivate
*)gdkregion
)->xregion
;
535 m_numRects
= r
->numRects
;
538 m_rects
= new wxRect
[m_numRects
];
539 for (size_t i
=0; i
< m_numRects
; ++i
)
541 _XBox
&xr
= r
->rects
[i
];
542 wxRect
&wr
= m_rects
[i
];
545 wr
.width
= xr
.x2
-xr
.x1
;
546 wr
.height
= xr
.y2
-xr
.y1
;
550 #endif // GTK+ 2.0/1.x
553 wxRegionIterator::wxRegionIterator()
555 m_refData
= new wxRIRefData();
559 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
561 m_refData
= new wxRIRefData();
565 void wxRegionIterator::Reset( const wxRegion
& region
)
568 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
572 bool wxRegionIterator::HaveRects() const
574 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
577 wxRegionIterator
& wxRegionIterator::operator ++ ()
585 wxRegionIterator
wxRegionIterator::operator ++ (int)
587 wxRegionIterator tmp
= *this;
594 wxCoord
wxRegionIterator::GetX() const
596 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
598 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
601 wxCoord
wxRegionIterator::GetY() const
603 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
605 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
608 wxCoord
wxRegionIterator::GetW() const
610 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
612 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
615 wxCoord
wxRegionIterator::GetH() const
617 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
619 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;
622 wxRect
wxRegionIterator::GetRect() const
626 r
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];