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
)
198 rect
.height
= height
;
202 m_refData
= new wxRegionRefData();
204 M_REGIONDATA
->m_region
= gdk_region_rectangle( &rect
);
206 M_REGIONDATA
->m_region
= gdk_region_union_with_rect(wxGdkRegion(), &rect
);
214 gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
216 GdkRegion
*reg
= gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
217 gdk_region_destroy( M_REGIONDATA
->m_region
);
218 M_REGIONDATA
->m_region
= reg
;
225 bool wxRegion::Union( const wxRect
& rect
)
227 return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
230 bool wxRegion::Union( const wxRegion
& region
)
237 m_refData
= new wxRegionRefData();
238 M_REGIONDATA
->m_region
= gdk_region_new();
246 gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
248 GdkRegion
*reg
= gdk_regions_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
249 gdk_region_destroy( M_REGIONDATA
->m_region
);
250 M_REGIONDATA
->m_region
= reg
;
256 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
258 wxRegion
reg( x
, y
, width
, height
);
260 return Intersect( reg
);
263 bool wxRegion::Intersect( const wxRect
& rect
)
265 wxRegion
reg( rect
);
267 return Intersect( reg
);
270 bool wxRegion::Intersect( const wxRegion
& region
)
277 m_refData
= new wxRegionRefData();
278 M_REGIONDATA
->m_region
= gdk_region_new();
289 gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
291 GdkRegion
*reg
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
292 gdk_region_destroy( M_REGIONDATA
->m_region
);
293 M_REGIONDATA
->m_region
= reg
;
299 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
301 wxRegion
reg( x
, y
, width
, height
);
302 return Subtract( reg
);
305 bool wxRegion::Subtract( const wxRect
& rect
)
307 wxRegion
reg( rect
);
308 return Subtract( reg
);
311 bool wxRegion::Subtract( const wxRegion
& region
)
318 m_refData
= new wxRegionRefData();
319 M_REGIONDATA
->m_region
= gdk_region_new();
327 gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
329 GdkRegion
*reg
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
330 gdk_region_destroy( M_REGIONDATA
->m_region
);
331 M_REGIONDATA
->m_region
= reg
;
337 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
339 wxRegion
reg( x
, y
, width
, height
);
343 bool wxRegion::Xor( const wxRect
& rect
)
345 wxRegion
reg( rect
);
349 bool wxRegion::Xor( const wxRegion
& region
)
356 m_refData
= new wxRegionRefData();
357 M_REGIONDATA
->m_region
= gdk_region_new();
365 gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
367 GdkRegion
*reg
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
368 gdk_region_destroy( M_REGIONDATA
->m_region
);
369 M_REGIONDATA
->m_region
= reg
;
375 // ----------------------------------------------------------------------------
377 // ----------------------------------------------------------------------------
379 void wxRegion::GetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
384 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
399 wxRect
wxRegion::GetBox() const
402 GetBox( x
, y
, w
, h
);
403 return wxRect( x
, y
, w
, h
);
406 bool wxRegion::Offset( wxCoord x
, wxCoord y
)
413 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
418 bool wxRegion::Empty() const
423 return gdk_region_empty( M_REGIONDATA
->m_region
);
426 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
) const
431 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
437 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
447 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
450 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
451 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
452 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
457 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
459 return Contains( pt
.x
, pt
.y
);
462 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
464 return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
467 GdkRegion
*wxRegion::GetRegion() const
470 return (GdkRegion
*) NULL
;
472 return M_REGIONDATA
->m_region
;
475 // ----------------------------------------------------------------------------
477 // ----------------------------------------------------------------------------
481 // the following structures must match the private structures
482 // in X11 region code ( xc/lib/X11/region.h )
484 // this makes the Region type transparent
485 // and we have access to the region rectangles
487 #include <gdk/gdkprivate.h>
490 short x1
, x2
, y1
, y2
;
494 long size
, numRects
;
495 _XBox
*rects
, extents
;
500 class wxRIRefData
: public wxObjectRefData
503 wxRIRefData() { Init(); }
504 virtual ~wxRIRefData();
506 void CreateRects( const wxRegion
& r
);
508 void Init() { m_rects
= NULL
; m_numRects
= 0; }
514 wxRIRefData::~wxRIRefData()
519 void wxRIRefData::CreateRects( const wxRegion
& region
)
525 GdkRegion
*gdkregion
= region
.GetRegion();
530 GdkRectangle
*gdkrects
= NULL
;
532 gdk_region_get_rectangles( gdkregion
, &gdkrects
, &numRects
);
534 m_numRects
= numRects
;
537 m_rects
= new wxRect
[m_numRects
];
538 for (size_t i
=0; i
< m_numRects
; ++i
)
540 GdkRectangle
&gr
= gdkrects
[i
];
541 wxRect
&wr
= m_rects
[i
];
545 wr
.height
= gr
.height
;
550 Region r
= ((GdkRegionPrivate
*)gdkregion
)->xregion
;
553 m_numRects
= r
->numRects
;
556 m_rects
= new wxRect
[m_numRects
];
557 for (size_t i
=0; i
< m_numRects
; ++i
)
559 _XBox
&xr
= r
->rects
[i
];
560 wxRect
&wr
= m_rects
[i
];
563 wr
.width
= xr
.x2
-xr
.x1
;
564 wr
.height
= xr
.y2
-xr
.y1
;
568 #endif // GTK+ 2.0/1.x
571 wxRegionIterator::wxRegionIterator()
573 m_refData
= new wxRIRefData();
577 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
579 m_refData
= new wxRIRefData();
583 void wxRegionIterator::Reset( const wxRegion
& region
)
586 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
590 bool wxRegionIterator::HaveRects() const
592 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
595 wxRegionIterator::operator bool () const
600 void wxRegionIterator::operator ++ ()
602 if (HaveRects()) ++m_current
;
605 void wxRegionIterator::operator ++ (int)
607 if (HaveRects()) ++m_current
;
610 wxCoord
wxRegionIterator::GetX() const
612 if( !HaveRects() ) return 0;
613 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
616 wxCoord
wxRegionIterator::GetY() const
618 if( !HaveRects() ) return 0;
619 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
622 wxCoord
wxRegionIterator::GetW() const
624 if( !HaveRects() ) return -1;
625 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
628 wxCoord
wxRegionIterator::GetH() const
630 if( !HaveRects() ) return -1;
631 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;
634 wxRect
wxRegionIterator::GetRect() const
638 r
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];