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
)
192 rect
.height
= height
;
196 m_refData
= new wxRegionRefData();
198 M_REGIONDATA
->m_region
= gdk_region_rectangle( &rect
);
200 M_REGIONDATA
->m_region
= gdk_region_union_with_rect(wxGdkRegion(), &rect
);
208 gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
210 GdkRegion
*reg
= gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
211 gdk_region_destroy( M_REGIONDATA
->m_region
);
212 M_REGIONDATA
->m_region
= reg
;
219 bool wxRegion::Union( const wxRect
& rect
)
221 return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
224 bool wxRegion::Union( const wxRegion
& region
)
231 m_refData
= new wxRegionRefData();
232 M_REGIONDATA
->m_region
= gdk_region_new();
240 gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
242 GdkRegion
*reg
= gdk_regions_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
243 gdk_region_destroy( M_REGIONDATA
->m_region
);
244 M_REGIONDATA
->m_region
= reg
;
250 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
252 wxRegion
reg( x
, y
, width
, height
);
254 return Intersect( reg
);
257 bool wxRegion::Intersect( const wxRect
& rect
)
259 wxRegion
reg( rect
);
261 return Intersect( reg
);
264 bool wxRegion::Intersect( const wxRegion
& region
)
271 m_refData
= new wxRegionRefData();
272 M_REGIONDATA
->m_region
= gdk_region_new();
283 gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
285 GdkRegion
*reg
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
286 gdk_region_destroy( M_REGIONDATA
->m_region
);
287 M_REGIONDATA
->m_region
= reg
;
293 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
295 wxRegion
reg( x
, y
, width
, height
);
296 return Subtract( reg
);
299 bool wxRegion::Subtract( const wxRect
& rect
)
301 wxRegion
reg( rect
);
302 return Subtract( reg
);
305 bool wxRegion::Subtract( const wxRegion
& region
)
312 m_refData
= new wxRegionRefData();
313 M_REGIONDATA
->m_region
= gdk_region_new();
321 gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
323 GdkRegion
*reg
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
324 gdk_region_destroy( M_REGIONDATA
->m_region
);
325 M_REGIONDATA
->m_region
= reg
;
331 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
333 wxRegion
reg( x
, y
, width
, height
);
337 bool wxRegion::Xor( const wxRect
& rect
)
339 wxRegion
reg( rect
);
343 bool wxRegion::Xor( const wxRegion
& region
)
350 m_refData
= new wxRegionRefData();
351 M_REGIONDATA
->m_region
= gdk_region_new();
359 gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
361 GdkRegion
*reg
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
362 gdk_region_destroy( M_REGIONDATA
->m_region
);
363 M_REGIONDATA
->m_region
= reg
;
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::Offset( wxCoord x
, wxCoord y
)
407 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
412 bool wxRegion::Empty() const
417 return gdk_region_empty( M_REGIONDATA
->m_region
);
420 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
) const
425 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
431 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
441 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
444 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
445 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
446 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
451 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
453 return Contains( pt
.x
, pt
.y
);
456 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
458 return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
461 GdkRegion
*wxRegion::GetRegion() const
464 return (GdkRegion
*) NULL
;
466 return M_REGIONDATA
->m_region
;
469 // ----------------------------------------------------------------------------
471 // ----------------------------------------------------------------------------
475 // the following structures must match the private structures
476 // in X11 region code ( xc/lib/X11/region.h )
478 // this makes the Region type transparent
479 // and we have access to the region rectangles
481 #include <gdk/gdkprivate.h>
484 short x1
, x2
, y1
, y2
;
488 long size
, numRects
;
489 _XBox
*rects
, extents
;
494 class wxRIRefData
: public wxObjectRefData
497 wxRIRefData() { Init(); }
498 virtual ~wxRIRefData();
500 void CreateRects( const wxRegion
& r
);
502 void Init() { m_rects
= NULL
; m_numRects
= 0; }
508 wxRIRefData::~wxRIRefData()
513 void wxRIRefData::CreateRects( const wxRegion
& region
)
519 GdkRegion
*gdkregion
= region
.GetRegion();
524 GdkRectangle
*gdkrects
= NULL
;
526 gdk_region_get_rectangles( gdkregion
, &gdkrects
, &numRects
);
528 m_numRects
= numRects
;
531 m_rects
= new wxRect
[m_numRects
];
532 for (size_t i
=0; i
< m_numRects
; ++i
)
534 GdkRectangle
&gr
= gdkrects
[i
];
535 wxRect
&wr
= m_rects
[i
];
539 wr
.height
= gr
.height
;
544 Region r
= ((GdkRegionPrivate
*)gdkregion
)->xregion
;
547 m_numRects
= r
->numRects
;
550 m_rects
= new wxRect
[m_numRects
];
551 for (size_t i
=0; i
< m_numRects
; ++i
)
553 _XBox
&xr
= r
->rects
[i
];
554 wxRect
&wr
= m_rects
[i
];
557 wr
.width
= xr
.x2
-xr
.x1
;
558 wr
.height
= xr
.y2
-xr
.y1
;
562 #endif // GTK+ 2.0/1.x
565 wxRegionIterator::wxRegionIterator()
567 m_refData
= new wxRIRefData();
571 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
573 m_refData
= new wxRIRefData();
577 void wxRegionIterator::Reset( const wxRegion
& region
)
580 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
584 bool wxRegionIterator::HaveRects() const
586 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
589 wxRegionIterator::operator bool () const
594 void wxRegionIterator::operator ++ ()
596 if (HaveRects()) ++m_current
;
599 void wxRegionIterator::operator ++ (int)
601 if (HaveRects()) ++m_current
;
604 wxCoord
wxRegionIterator::GetX() const
606 if( !HaveRects() ) return 0;
607 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
610 wxCoord
wxRegionIterator::GetY() const
612 if( !HaveRects() ) return 0;
613 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
616 wxCoord
wxRegionIterator::GetW() const
618 if( !HaveRects() ) return -1;
619 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
622 wxCoord
wxRegionIterator::GetH() const
624 if( !HaveRects() ) return -1;
625 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;
628 wxRect
wxRegionIterator::GetRect() const
632 r
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];