1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gtk/region.cpp
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "region.h"
14 #include "wx/region.h"
19 // Unfortunately the new way of implementing the region iterator
20 // doesn't work with GTK+ 2.0 or above (can't access a Region in
28 //-----------------------------------------------------------------------------
30 //-----------------------------------------------------------------------------
32 class wxRegionRefData
: public wxObjectRefData
44 wxRegionRefData::wxRegionRefData()
46 m_region
= (GdkRegion
*) NULL
;
49 wxRegionRefData::~wxRegionRefData()
51 if (m_region
) gdk_region_destroy( m_region
);
54 wxNode
*node
= m_rects
.First();
57 wxRect
*r
= (wxRect
*)node
->Data();
64 //-----------------------------------------------------------------------------
66 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
68 IMPLEMENT_DYNAMIC_CLASS(wxRegion
,wxGDIObject
);
70 wxRegion::wxRegion( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
72 m_refData
= new wxRegionRefData();
73 GdkRegion
*reg
= gdk_region_new();
80 gdk_region_union_with_rect( reg
, &rect
);
81 M_REGIONDATA
->m_region
= reg
;
83 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( reg
, &rect
);
84 gdk_region_destroy( reg
);
87 M_REGIONDATA
->m_rects
.Append( (wxObject
*) new wxRect(x
,y
,w
,h
) );
91 wxRegion::wxRegion( const wxPoint
& topLeft
, const wxPoint
& bottomRight
)
93 m_refData
= new wxRegionRefData();
94 GdkRegion
*reg
= gdk_region_new();
98 rect
.width
= bottomRight
.x
- rect
.x
;
99 rect
.height
= bottomRight
.y
- rect
.y
;
101 gdk_region_union_with_rect( reg
, &rect
);
102 M_REGIONDATA
->m_region
= reg
;
104 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( reg
, &rect
);
105 gdk_region_destroy( reg
);
108 M_REGIONDATA
->m_rects
.Append( (wxObject
*) new wxRect(topLeft
,bottomRight
) );
112 wxRegion::wxRegion( const wxRect
& rect
)
114 m_refData
= new wxRegionRefData();
115 GdkRegion
*reg
= gdk_region_new();
119 g_rect
.width
= rect
.width
;
120 g_rect
.height
= rect
.height
;
122 gdk_region_union_with_rect( reg
, &g_rect
);
123 M_REGIONDATA
->m_region
= reg
;
125 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( reg
, &g_rect
);
126 gdk_region_destroy( reg
);
129 M_REGIONDATA
->m_rects
.Append( (wxObject
*) new wxRect(rect
.x
,rect
.y
,rect
.width
,rect
.height
) );
137 wxRegion::~wxRegion()
141 bool wxRegion::operator == ( const wxRegion
& region
)
143 return m_refData
== region
.m_refData
;
146 bool wxRegion::operator != ( const wxRegion
& region
)
148 return m_refData
!= region
.m_refData
;
151 void wxRegion::Clear()
156 bool wxRegion::Union( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
162 rect
.height
= height
;
165 m_refData
= new wxRegionRefData();
166 GdkRegion
*reg
= gdk_region_new();
168 gdk_region_union_with_rect( reg
, &rect
);
169 M_REGIONDATA
->m_region
= reg
;
171 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( reg
, &rect
);
172 gdk_region_destroy( reg
);
178 gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
180 GdkRegion
*reg
= gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
181 gdk_region_destroy( M_REGIONDATA
->m_region
);
182 M_REGIONDATA
->m_region
= reg
;
187 M_REGIONDATA
->m_rects
.Append( (wxObject
*) new wxRect(x
,y
,width
,height
) );
193 bool wxRegion::Union( const wxRect
& rect
)
195 return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
198 bool wxRegion::Union( const wxRegion
& region
)
205 m_refData
= new wxRegionRefData();
206 M_REGIONDATA
->m_region
= gdk_region_new();
210 gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
212 GdkRegion
*reg
= gdk_regions_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
213 gdk_region_destroy( M_REGIONDATA
->m_region
);
214 M_REGIONDATA
->m_region
= reg
;
218 wxNode
*node
= region
.GetRectList()->First();
221 wxRect
*r
= (wxRect
*)node
->Data();
222 M_REGIONDATA
->m_rects
.Append( (wxObject
*) new wxRect(r
->x
,r
->y
,r
->width
,r
->height
) );
230 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
234 m_refData
= new wxRegionRefData();
235 M_REGIONDATA
->m_region
= gdk_region_new();
238 wxRegion
reg( x
, y
, width
, height
);
243 bool wxRegion::Intersect( const wxRect
& rect
)
247 m_refData
= new wxRegionRefData();
248 M_REGIONDATA
->m_region
= gdk_region_new();
251 wxRegion
reg( rect
);
256 bool wxRegion::Intersect( const wxRegion
& region
)
263 m_refData
= new wxRegionRefData();
264 M_REGIONDATA
->m_region
= gdk_region_new();
269 gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
271 GdkRegion
*reg
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
272 gdk_region_destroy( M_REGIONDATA
->m_region
);
273 M_REGIONDATA
->m_region
= reg
;
278 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
282 m_refData
= new wxRegionRefData();
283 M_REGIONDATA
->m_region
= gdk_region_new();
286 wxRegion
reg( x
, y
, width
, height
);
291 bool wxRegion::Subtract( const wxRect
& rect
)
295 m_refData
= new wxRegionRefData();
296 M_REGIONDATA
->m_region
= gdk_region_new();
299 wxRegion
reg( rect
);
304 bool wxRegion::Subtract( const wxRegion
& region
)
311 m_refData
= new wxRegionRefData();
312 M_REGIONDATA
->m_region
= gdk_region_new();
316 gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
318 GdkRegion
*reg
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
319 gdk_region_destroy( M_REGIONDATA
->m_region
);
320 M_REGIONDATA
->m_region
= reg
;
325 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
329 m_refData
= new wxRegionRefData();
330 M_REGIONDATA
->m_region
= gdk_region_new();
333 wxRegion
reg( x
, y
, width
, height
);
338 bool wxRegion::Xor( const wxRect
& rect
)
342 m_refData
= new wxRegionRefData();
343 M_REGIONDATA
->m_region
= gdk_region_new();
346 wxRegion
reg( rect
);
351 bool wxRegion::Xor( const wxRegion
& region
)
358 m_refData
= new wxRegionRefData();
359 M_REGIONDATA
->m_region
= gdk_region_new();
363 gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
365 GdkRegion
*reg
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
366 gdk_region_destroy( M_REGIONDATA
->m_region
);
367 M_REGIONDATA
->m_region
= reg
;
371 wxNode
*node
= region
.GetRectList()->First();
374 wxRect
*r
= (wxRect
*)node
->Data();
375 M_REGIONDATA
->m_rects
.Append( (wxObject
*) new wxRect(r
->x
,r
->y
,r
->width
,r
->height
) );
383 void wxRegion::GetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
393 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
400 wxRect
wxRegion::GetBox() const
406 GetBox( x
, y
, w
, h
);
407 return wxRect( x
, y
, w
, h
);
410 bool wxRegion::Empty() const
415 return gdk_region_empty( M_REGIONDATA
->m_region
);
418 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
) const
423 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
429 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
439 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
442 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
443 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
444 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
449 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
451 return Contains( pt
.x
, pt
.y
);
454 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
456 return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
459 GdkRegion
*wxRegion::GetRegion() const
462 return (GdkRegion
*) NULL
;
464 return M_REGIONDATA
->m_region
;
467 wxList
*wxRegion::GetRectList() const
471 return (wxList
*) NULL
;
473 return &(M_REGIONDATA
->m_rects
);
475 return (wxList
*) NULL
;
479 //-----------------------------------------------------------------------------
481 //-----------------------------------------------------------------------------
485 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
);
487 wxRegionIterator::wxRegionIterator()
492 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
497 void wxRegionIterator::Reset( const wxRegion
& region
)
503 wxRegionIterator::operator bool () const
505 return m_region
.GetRectList() && m_current
< (size_t)m_region
.GetRectList()->Number();
508 bool wxRegionIterator::HaveRects() const
510 return m_region
.GetRectList() && m_current
< (size_t)m_region
.GetRectList()->Number();
513 void wxRegionIterator::operator ++ ()
515 if (HaveRects()) ++m_current
;
518 void wxRegionIterator::operator ++ (int)
520 if (HaveRects()) ++m_current
;
523 wxCoord
wxRegionIterator::GetX() const
525 wxNode
*node
= m_region
.GetRectList()->Nth( m_current
);
527 wxRect
*r
= (wxRect
*)node
->Data();
531 wxCoord
wxRegionIterator::GetY() const
533 wxNode
*node
= m_region
.GetRectList()->Nth( m_current
);
535 wxRect
*r
= (wxRect
*)node
->Data();
539 wxCoord
wxRegionIterator::GetW() const
541 wxNode
*node
= m_region
.GetRectList()->Nth( m_current
);
543 wxRect
*r
= (wxRect
*)node
->Data();
547 wxCoord
wxRegionIterator::GetH() const
549 wxNode
*node
= m_region
.GetRectList()->Nth( m_current
);
551 wxRect
*r
= (wxRect
*)node
->Data();
557 // the following structures must match the private structures
558 // in X11 region code ( xc/lib/X11/region.h )
560 // this makes the Region type transparent
561 // and we have access to the region rectangles
564 short x1
, x2
, y1
, y2
;
568 long size
, numRects
;
569 _XBox
*rects
, extents
;
572 class wxRIRefData
: public wxObjectRefData
576 wxRIRefData() : m_rects(0), m_numRects(0){}
582 void CreateRects( const wxRegion
& r
);
585 wxRIRefData::~wxRIRefData()
590 #include <gdk/gdkprivate.h>
592 void wxRIRefData::CreateRects( const wxRegion
& region
)
598 GdkRegion
*gdkregion
= region
.GetRegion();
600 Region r
= ((GdkRegionPrivate
*)gdkregion
)->xregion
;
602 m_numRects
= r
->numRects
;
605 m_rects
= new wxRect
[m_numRects
];
606 for( size_t i
=0; i
<m_numRects
; ++i
)
608 _XBox
&xr
= r
->rects
[i
];
609 wxRect
&wr
= m_rects
[i
];
612 wr
.width
= xr
.x2
-xr
.x1
;
613 wr
.height
= xr
.y2
-xr
.y1
;
620 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
);
622 wxRegionIterator::wxRegionIterator()
624 m_refData
= new wxRIRefData();
628 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
630 m_refData
= new wxRIRefData();
634 void wxRegionIterator::Reset( const wxRegion
& region
)
637 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
641 bool wxRegionIterator::HaveRects() const
643 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
646 wxRegionIterator::operator bool () const
651 void wxRegionIterator::operator ++ ()
653 if (HaveRects()) ++m_current
;
656 void wxRegionIterator::operator ++ (int)
658 if (HaveRects()) ++m_current
;
661 wxCoord
wxRegionIterator::GetX() const
663 if( !HaveRects() ) return 0;
664 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
667 wxCoord
wxRegionIterator::GetY() const
669 if( !HaveRects() ) return 0;
670 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
673 wxCoord
wxRegionIterator::GetW() const
675 if( !HaveRects() ) return -1;
676 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
679 wxCoord
wxRegionIterator::GetH() const
681 if( !HaveRects() ) return -1;
682 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;