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 // ----------------------------------------------------------------------------
23 #include "wx/region.h"
30 // ----------------------------------------------------------------------------
31 // wxRegionRefData: private class containing the information about the region
32 // ----------------------------------------------------------------------------
34 class wxRegionRefData
: public wxObjectRefData
42 wxRegionRefData(const wxRegionRefData
& refData
)
45 m_region
= gdk_region_copy(refData
.m_region
);
47 m_region
= gdk_region_new();
48 GdkRegion
*regCopy
= gdk_regions_union(m_region
, refData
.m_region
);
49 gdk_region_destroy(m_region
);
57 gdk_region_destroy( m_region
);
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
67 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
68 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
70 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
);
71 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
);
73 // ----------------------------------------------------------------------------
74 // wxRegion construction
75 // ----------------------------------------------------------------------------
77 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
79 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
87 m_refData
= new wxRegionRefData();
90 M_REGIONDATA
->m_region
= gdk_region_rectangle( rect
);
92 GdkRegion
*reg
= gdk_region_new();
93 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( reg
, &rect
);
94 gdk_region_destroy( reg
);
98 wxRegion::wxRegion( size_t n
, const wxPoint
*points
, int fillStyle
)
100 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
101 for ( size_t i
= 0 ; i
< n
; i
++ )
103 gdkpoints
[i
].x
= points
[i
].x
;
104 gdkpoints
[i
].y
= points
[i
].y
;
107 m_refData
= new wxRegionRefData();
109 GdkRegion
* reg
= gdk_region_polygon
113 fillStyle
== wxWINDING_RULE
? GDK_WINDING_RULE
117 M_REGIONDATA
->m_region
= reg
;
122 wxRegion::~wxRegion()
124 // m_refData unrefed in ~wxObject
127 wxObjectRefData
*wxRegion::CreateRefData() const
129 return new wxRegionRefData
;
132 wxObjectRefData
*wxRegion::CloneRefData(const wxObjectRefData
*data
) const
134 return new wxRegionRefData(*(wxRegionRefData
*)data
);
136 // ----------------------------------------------------------------------------
137 // wxRegion comparison
138 // ----------------------------------------------------------------------------
140 bool wxRegion::operator==( const wxRegion
& region
)
142 // compare the regions themselves, not the pointers to ref data!
143 return gdk_region_equal(M_REGIONDATA
->m_region
,
144 M_REGIONDATA_OF(region
)->m_region
);
147 bool wxRegion::operator != ( const wxRegion
& region
)
149 return !(*this == region
);
152 // ----------------------------------------------------------------------------
153 // wxRegion operations
154 // ----------------------------------------------------------------------------
156 void wxRegion::Clear()
161 bool wxRegion::Union( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
167 rect
.height
= height
;
171 m_refData
= new wxRegionRefData();
173 M_REGIONDATA
->m_region
= gdk_region_rectangle( rect
);
175 GdkRegion
*reg
= gdk_region_new();
176 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( reg
, &rect
);
177 gdk_region_destroy( reg
);
185 gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
187 GdkRegion
*reg
= gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
188 gdk_region_destroy( M_REGIONDATA
->m_region
);
189 M_REGIONDATA
->m_region
= reg
;
196 bool wxRegion::Union( const wxRect
& rect
)
198 return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
201 bool wxRegion::Union( const wxRegion
& region
)
208 m_refData
= new wxRegionRefData();
209 M_REGIONDATA
->m_region
= gdk_region_new();
217 gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
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
;
227 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
229 wxRegion
reg( x
, y
, width
, height
);
231 return Intersect( reg
);
234 bool wxRegion::Intersect( const wxRect
& rect
)
236 wxRegion
reg( rect
);
238 return Intersect( reg
);
241 bool wxRegion::Intersect( const wxRegion
& region
)
248 m_refData
= new wxRegionRefData();
249 M_REGIONDATA
->m_region
= gdk_region_new();
260 gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
262 GdkRegion
*reg
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
263 gdk_region_destroy( M_REGIONDATA
->m_region
);
264 M_REGIONDATA
->m_region
= reg
;
270 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
272 wxRegion
reg( x
, y
, width
, height
);
273 return Subtract( reg
);
276 bool wxRegion::Subtract( const wxRect
& rect
)
278 wxRegion
reg( rect
);
279 return Subtract( reg
);
282 bool wxRegion::Subtract( const wxRegion
& region
)
289 m_refData
= new wxRegionRefData();
290 M_REGIONDATA
->m_region
= gdk_region_new();
298 gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
300 GdkRegion
*reg
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
301 gdk_region_destroy( M_REGIONDATA
->m_region
);
302 M_REGIONDATA
->m_region
= reg
;
308 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
310 wxRegion
reg( x
, y
, width
, height
);
314 bool wxRegion::Xor( const wxRect
& rect
)
316 wxRegion
reg( rect
);
320 bool wxRegion::Xor( const wxRegion
& region
)
327 m_refData
= new wxRegionRefData();
328 M_REGIONDATA
->m_region
= gdk_region_new();
336 gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
338 GdkRegion
*reg
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
339 gdk_region_destroy( M_REGIONDATA
->m_region
);
340 M_REGIONDATA
->m_region
= reg
;
346 // ----------------------------------------------------------------------------
348 // ----------------------------------------------------------------------------
350 void wxRegion::GetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
355 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
370 wxRect
wxRegion::GetBox() const
373 GetBox( x
, y
, w
, h
);
374 return wxRect( x
, y
, w
, h
);
377 bool wxRegion::Offset( wxCoord x
, wxCoord y
)
384 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
389 bool wxRegion::Empty() const
394 return gdk_region_empty( M_REGIONDATA
->m_region
);
397 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
) const
402 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
408 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
418 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
421 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
422 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
423 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
428 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
430 return Contains( pt
.x
, pt
.y
);
433 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
435 return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
438 GdkRegion
*wxRegion::GetRegion() const
441 return (GdkRegion
*) NULL
;
443 return M_REGIONDATA
->m_region
;
446 // ----------------------------------------------------------------------------
448 // ----------------------------------------------------------------------------
452 // the following structures must match the private structures
453 // in X11 region code ( xc/lib/X11/region.h )
455 // this makes the Region type transparent
456 // and we have access to the region rectangles
458 #include <gdk/gdkprivate.h>
461 short x1
, x2
, y1
, y2
;
465 long size
, numRects
;
466 _XBox
*rects
, extents
;
471 class wxRIRefData
: public wxObjectRefData
475 wxRIRefData() : m_rects(0), m_numRects(0){}
481 void CreateRects( const wxRegion
& r
);
484 wxRIRefData::~wxRIRefData()
489 void wxRIRefData::CreateRects( const wxRegion
& region
)
497 GdkRegion
*gdkregion
= region
.GetRegion();
498 if (!gdkregion
) return;
501 GdkRectangles
*gdkrects
= NULL
;
503 gdk_region_get_rectangles( gdkregion
, &gdkrect
, &numRects
);
505 m_numRects
= numRects
;
508 m_rects
= new wxRect
[m_numRects
];
509 for (size_t i
=0; i
< m_numRects
; ++i
)
511 GdkRectangle
&gr
= gdkrects
[i
];
512 wxRect
&wr
= m_rects
[i
];
516 wr
.height
= gr
.height
;
519 g_delete( gdkrects
); // delete []
521 Region r
= ((GdkRegionPrivate
*)gdkregion
)->xregion
;
524 m_numRects
= r
->numRects
;
527 m_rects
= new wxRect
[m_numRects
];
528 for (size_t i
=0; i
< m_numRects
; ++i
)
530 _XBox
&xr
= r
->rects
[i
];
531 wxRect
&wr
= m_rects
[i
];
534 wr
.width
= xr
.x2
-xr
.x1
;
535 wr
.height
= xr
.y2
-xr
.y1
;
542 wxRegionIterator::wxRegionIterator()
544 m_refData
= new wxRIRefData();
548 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
550 m_refData
= new wxRIRefData();
554 void wxRegionIterator::Reset( const wxRegion
& region
)
557 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
561 bool wxRegionIterator::HaveRects() const
563 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
566 wxRegionIterator::operator bool () const
571 void wxRegionIterator::operator ++ ()
573 if (HaveRects()) ++m_current
;
576 void wxRegionIterator::operator ++ (int)
578 if (HaveRects()) ++m_current
;
581 wxCoord
wxRegionIterator::GetX() const
583 if( !HaveRects() ) return 0;
584 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
587 wxCoord
wxRegionIterator::GetY() const
589 if( !HaveRects() ) return 0;
590 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
593 wxCoord
wxRegionIterator::GetW() const
595 if( !HaveRects() ) return -1;
596 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
599 wxCoord
wxRegionIterator::GetH() const
601 if( !HaveRects() ) return -1;
602 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;
605 wxRect
wxRegionIterator::GetRect() const
609 r
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];