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 // ============================================================================
16 #pragma implementation "region.h"
19 // ----------------------------------------------------------------------------
21 // ----------------------------------------------------------------------------
25 #include "wx/region.h"
27 #include "wx/gtk/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
; }
49 // ----------------------------------------------------------------------------
50 // wxRegionRefData: private class containing the information about the region
51 // ----------------------------------------------------------------------------
53 class wxRegionRefData
: public wxObjectRefData
61 wxRegionRefData(const wxRegionRefData
& refData
)
65 m_region
= gdk_region_copy(refData
.m_region
);
67 m_region
= gdk_regions_union(wxGdkRegion(), refData
.m_region
);
74 gdk_region_destroy( m_region
);
80 // ----------------------------------------------------------------------------
82 // ----------------------------------------------------------------------------
84 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
85 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
87 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
)
88 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
)
90 // ----------------------------------------------------------------------------
91 // wxRegion construction
92 // ----------------------------------------------------------------------------
94 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
96 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
104 m_refData
= new wxRegionRefData();
107 M_REGIONDATA
->m_region
= gdk_region_rectangle( &rect
);
109 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( wxGdkRegion(), &rect
);
113 wxRegion::wxRegion( GdkRegion
*region
)
115 m_refData
= new wxRegionRefData();
117 M_REGIONDATA
->m_region
= gdk_region_copy( region
);
119 M_REGIONDATA
->m_region
= gdk_regions_union(wxGdkRegion(), region
);
123 wxRegion::wxRegion( size_t n
, const wxPoint
*points
, int fillStyle
)
125 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
126 for ( size_t i
= 0 ; i
< n
; i
++ )
128 gdkpoints
[i
].x
= points
[i
].x
;
129 gdkpoints
[i
].y
= points
[i
].y
;
132 m_refData
= new wxRegionRefData();
134 GdkRegion
* reg
= gdk_region_polygon
138 fillStyle
== wxWINDING_RULE
? GDK_WINDING_RULE
142 M_REGIONDATA
->m_region
= reg
;
147 wxRegion::~wxRegion()
149 // m_refData unrefed in ~wxObject
152 wxObjectRefData
*wxRegion::CreateRefData() const
154 return new wxRegionRefData
;
157 wxObjectRefData
*wxRegion::CloneRefData(const wxObjectRefData
*data
) const
159 return new wxRegionRefData(*(wxRegionRefData
*)data
);
162 // ----------------------------------------------------------------------------
163 // wxRegion comparison
164 // ----------------------------------------------------------------------------
166 bool wxRegion::operator==( const wxRegion
& region
)
168 if (m_refData
== region
.m_refData
) return TRUE
;
170 if (!m_refData
|| !region
.m_refData
) return FALSE
;
172 // compare the regions themselves, not the pointers to ref data!
173 return gdk_region_equal(M_REGIONDATA
->m_region
,
174 M_REGIONDATA_OF(region
)->m_region
);
177 // ----------------------------------------------------------------------------
178 // wxRegion operations
179 // ----------------------------------------------------------------------------
181 void wxRegion::Clear()
186 bool wxRegion::Union( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
188 // workaround for a strange GTK/X11 bug: taking union with an empty
189 // rectangle results in an empty region which is definitely not what we
191 if ( !width
|| !height
)
196 InitRect(x
, y
, width
, height
);
206 rect
.height
= height
;
209 gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
211 GdkRegion
*reg
= gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
212 gdk_region_destroy( M_REGIONDATA
->m_region
);
213 M_REGIONDATA
->m_region
= reg
;
220 bool wxRegion::Union( const wxRect
& rect
)
222 return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
225 bool wxRegion::Union( const wxRegion
& region
)
232 m_refData
= new wxRegionRefData();
233 M_REGIONDATA
->m_region
= gdk_region_new();
241 gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
243 GdkRegion
*reg
= gdk_regions_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
244 gdk_region_destroy( M_REGIONDATA
->m_region
);
245 M_REGIONDATA
->m_region
= reg
;
251 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
253 wxRegion
reg( x
, y
, width
, height
);
255 return Intersect( reg
);
258 bool wxRegion::Intersect( const wxRect
& rect
)
260 wxRegion
reg( rect
);
262 return Intersect( reg
);
265 bool wxRegion::Intersect( const wxRegion
& region
)
272 // intersecting with invalid region doesn't make sense
279 gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
281 GdkRegion
*reg
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
282 gdk_region_destroy( M_REGIONDATA
->m_region
);
283 M_REGIONDATA
->m_region
= reg
;
289 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
291 wxRegion
reg( x
, y
, width
, height
);
292 return Subtract( reg
);
295 bool wxRegion::Subtract( const wxRect
& rect
)
297 wxRegion
reg( rect
);
298 return Subtract( reg
);
301 bool wxRegion::Subtract( const wxRegion
& region
)
308 // subtracting from an invalid region doesn't make sense
315 gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
317 GdkRegion
*reg
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
318 gdk_region_destroy( M_REGIONDATA
->m_region
);
319 M_REGIONDATA
->m_region
= reg
;
325 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
327 wxRegion
reg( x
, y
, width
, height
);
331 bool wxRegion::Xor( const wxRect
& rect
)
333 wxRegion
reg( rect
);
337 bool wxRegion::Xor( const wxRegion
& region
)
350 gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
352 GdkRegion
*reg
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
353 gdk_region_destroy( M_REGIONDATA
->m_region
);
354 M_REGIONDATA
->m_region
= reg
;
360 bool wxRegion::Offset( wxCoord x
, wxCoord y
)
367 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
372 // ----------------------------------------------------------------------------
374 // ----------------------------------------------------------------------------
376 void wxRegion::GetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
381 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
396 wxRect
wxRegion::GetBox() const
399 GetBox( x
, y
, w
, h
);
400 return wxRect( x
, y
, w
, h
);
403 bool wxRegion::Empty() const
408 return gdk_region_empty( M_REGIONDATA
->m_region
);
411 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
) const
416 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
422 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
432 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
435 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
436 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
437 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
442 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
444 return Contains( pt
.x
, pt
.y
);
447 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
449 return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
452 GdkRegion
*wxRegion::GetRegion() const
455 return (GdkRegion
*) NULL
;
457 return M_REGIONDATA
->m_region
;
460 // ----------------------------------------------------------------------------
462 // ----------------------------------------------------------------------------
466 // the following structures must match the private structures
467 // in X11 region code ( xc/lib/X11/region.h )
469 // this makes the Region type transparent
470 // and we have access to the region rectangles
472 #include <gdk/gdkprivate.h>
475 short x1
, x2
, y1
, y2
;
479 long size
, numRects
;
480 _XBox
*rects
, extents
;
485 class wxRIRefData
: public wxObjectRefData
488 wxRIRefData() { Init(); }
489 virtual ~wxRIRefData();
491 void CreateRects( const wxRegion
& r
);
493 void Init() { m_rects
= NULL
; m_numRects
= 0; }
499 wxRIRefData::~wxRIRefData()
504 void wxRIRefData::CreateRects( const wxRegion
& region
)
510 GdkRegion
*gdkregion
= region
.GetRegion();
515 GdkRectangle
*gdkrects
= NULL
;
517 gdk_region_get_rectangles( gdkregion
, &gdkrects
, &numRects
);
519 m_numRects
= numRects
;
522 m_rects
= new wxRect
[m_numRects
];
523 for (size_t i
=0; i
< m_numRects
; ++i
)
525 GdkRectangle
&gr
= gdkrects
[i
];
526 wxRect
&wr
= m_rects
[i
];
530 wr
.height
= gr
.height
;
535 Region r
= ((GdkRegionPrivate
*)gdkregion
)->xregion
;
538 m_numRects
= r
->numRects
;
541 m_rects
= new wxRect
[m_numRects
];
542 for (size_t i
=0; i
< m_numRects
; ++i
)
544 _XBox
&xr
= r
->rects
[i
];
545 wxRect
&wr
= m_rects
[i
];
548 wr
.width
= xr
.x2
-xr
.x1
;
549 wr
.height
= xr
.y2
-xr
.y1
;
553 #endif // GTK+ 2.0/1.x
556 wxRegionIterator::wxRegionIterator()
558 m_refData
= new wxRIRefData();
562 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
564 m_refData
= new wxRIRefData();
568 void wxRegionIterator::Reset( const wxRegion
& region
)
571 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
575 bool wxRegionIterator::HaveRects() const
577 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
580 wxRegionIterator
& wxRegionIterator::operator ++ ()
588 wxRegionIterator
wxRegionIterator::operator ++ (int)
590 wxRegionIterator tmp
= *this;
597 wxCoord
wxRegionIterator::GetX() const
599 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
601 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
604 wxCoord
wxRegionIterator::GetY() const
606 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
608 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
611 wxCoord
wxRegionIterator::GetW() const
613 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
615 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
618 wxCoord
wxRegionIterator::GetH() const
620 wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") );
622 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;
625 wxRect
wxRegionIterator::GetRect() const
629 r
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];