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"
28 // Unfortunately the new way of implementing the region iterator
29 // doesn't work with GTK+ 2.0 or above (can't access a Region in
39 // ----------------------------------------------------------------------------
40 // wxRegionRefData: private class containing the information about the region
41 // ----------------------------------------------------------------------------
43 class wxRegionRefData
: public wxObjectRefData
47 wxRegionRefData(const wxRegionRefData
& refData
);
48 virtual ~wxRegionRefData();
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
61 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
63 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
);
64 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
);
66 // ============================================================================
68 // ============================================================================
70 // ----------------------------------------------------------------------------
72 // ----------------------------------------------------------------------------
74 wxRegionRefData::wxRegionRefData()
76 m_region
= (GdkRegion
*) NULL
;
79 wxRegionRefData::wxRegionRefData(const wxRegionRefData
& refData
)
82 m_region
= gdk_region_copy(refData
.m_region
);
84 m_region
= gdk_region_new();
85 GdkRegion
*regCopy
= gdk_regions_union(m_region
, refData
.m_region
);
86 gdk_region_destroy(m_region
);
91 wxNode
*node
= refData
.m_rects
.First();
94 wxRect
*r
= (wxRect
*)node
->Data();
95 m_rects
.Append( (wxObject
*) new wxRect(*r
) );
101 wxRegionRefData::~wxRegionRefData()
104 gdk_region_destroy( m_region
);
107 wxNode
*node
= m_rects
.First();
110 wxRect
*r
= (wxRect
*)node
->Data();
117 // ----------------------------------------------------------------------------
118 // wxRegion construction
119 // ----------------------------------------------------------------------------
121 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
123 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
125 m_refData
= new wxRegionRefData();
126 GdkRegion
*reg
= gdk_region_new();
133 gdk_region_union_with_rect( reg
, &rect
);
134 M_REGIONDATA
->m_region
= reg
;
136 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( reg
, &rect
);
137 gdk_region_destroy( reg
);
141 M_REGIONDATA
->m_rects
.Append( (wxObject
*) new wxRect(x
, y
, w
, h
) );
145 wxRegion::wxRegion( size_t n
, const wxPoint
*points
, int fillStyle
)
147 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
148 for ( size_t i
= 0 ; i
< n
; i
++ )
150 gdkpoints
[i
].x
= points
[i
].x
;
151 gdkpoints
[i
].y
= points
[i
].y
;
154 m_refData
= new wxRegionRefData();
156 GdkRegion
* reg
= gdk_region_polygon
160 fillStyle
== wxWINDING_RULE
? GDK_WINDING_RULE
164 M_REGIONDATA
->m_region
= reg
;
169 wxRegion::~wxRegion()
173 // ----------------------------------------------------------------------------
174 // wxRegion comparison
175 // ----------------------------------------------------------------------------
177 bool wxRegion::operator==( const wxRegion
& region
)
179 // compare the regions themselves, not the pointers to ref data!
180 return gdk_region_equal(M_REGIONDATA
->m_region
,
181 M_REGIONDATA_OF(region
)->m_region
);
184 bool wxRegion::operator != ( const wxRegion
& region
)
186 return !(*this == region
);
189 // ----------------------------------------------------------------------------
190 // wxRegion operations
191 // ----------------------------------------------------------------------------
193 void wxRegion::Clear()
198 bool wxRegion::Union( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
204 rect
.height
= height
;
207 m_refData
= new wxRegionRefData();
208 GdkRegion
*reg
= gdk_region_new();
210 gdk_region_union_with_rect( reg
, &rect
);
211 M_REGIONDATA
->m_region
= reg
;
213 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( reg
, &rect
);
214 gdk_region_destroy( reg
);
222 gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
224 GdkRegion
*reg
= gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
225 gdk_region_destroy( M_REGIONDATA
->m_region
);
226 M_REGIONDATA
->m_region
= reg
;
231 M_REGIONDATA
->m_rects
.Append( (wxObject
*) new wxRect(x
,y
,width
,height
) );
237 bool wxRegion::Union( const wxRect
& rect
)
239 return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
242 bool wxRegion::Union( const wxRegion
& region
)
250 gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
252 GdkRegion
*reg
= gdk_regions_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
253 gdk_region_destroy( M_REGIONDATA
->m_region
);
254 M_REGIONDATA
->m_region
= reg
;
258 wxNode
*node
= region
.GetRectList()->First();
261 wxRect
*r
= (wxRect
*)node
->Data();
262 M_REGIONDATA
->m_rects
.Append( (wxObject
*) new wxRect(r
->x
,r
->y
,r
->width
,r
->height
) );
270 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
272 wxRegion
reg( x
, y
, width
, height
);
274 return Intersect( reg
);
277 bool wxRegion::Intersect( const wxRect
& rect
)
279 wxRegion
reg( rect
);
280 return Intersect( reg
);
283 // this helper function just computes the region intersection without updating
284 // the list of rectangles each region maintaints: this allows us to call it
285 // from Intersect() itself without going into infinite recursion as we would
286 // if we called Intersect() itself recursively
287 bool wxRegion::IntersectRegionOnly(const wxRegion
& region
)
292 gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
294 GdkRegion
*reg
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
295 gdk_region_destroy( M_REGIONDATA
->m_region
);
296 M_REGIONDATA
->m_region
= reg
;
302 bool wxRegion::Intersect( const wxRegion
& region
)
309 m_refData
= new wxRegionRefData();
310 M_REGIONDATA
->m_region
= gdk_region_new();
314 if ( !IntersectRegionOnly(region
) )
316 GetRectList()->Clear();
321 // we need to update the rect list as well
323 wxList
& list
= *GetRectList();
324 wxNode
*node
= list
.First();
327 wxRect
*r
= (wxRect
*)node
->Data();
329 wxRegion regCopy
= region
;
330 if ( regCopy
.IntersectRegionOnly(*r
) )
332 // replace the node with the intersection
333 *r
= regCopy
.GetBox();
337 // TODO remove the rect from the list
349 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
351 wxRegion
reg( x
, y
, width
, height
);
352 return Subtract( reg
);
355 bool wxRegion::Subtract( const wxRect
& rect
)
357 wxRegion
reg( rect
);
358 return Subtract( reg
);
361 bool wxRegion::Subtract( const wxRegion
& region
)
368 m_refData
= new wxRegionRefData();
369 M_REGIONDATA
->m_region
= gdk_region_new();
375 gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
377 GdkRegion
*reg
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
378 gdk_region_destroy( M_REGIONDATA
->m_region
);
379 M_REGIONDATA
->m_region
= reg
;
385 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
387 wxRegion
reg( x
, y
, width
, height
);
391 bool wxRegion::Xor( const wxRect
& rect
)
393 wxRegion
reg( rect
);
397 bool wxRegion::Xor( const wxRegion
& region
)
404 m_refData
= new wxRegionRefData();
405 M_REGIONDATA
->m_region
= gdk_region_new();
413 gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
415 GdkRegion
*reg
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
416 gdk_region_destroy( M_REGIONDATA
->m_region
);
417 M_REGIONDATA
->m_region
= reg
;
421 wxNode
*node
= region
.GetRectList()->First();
424 wxRect
*r
= (wxRect
*)node
->Data();
425 M_REGIONDATA
->m_rects
.Append( (wxObject
*) new wxRect(r
->x
,r
->y
,r
->width
,r
->height
) );
433 // ----------------------------------------------------------------------------
435 // ----------------------------------------------------------------------------
437 void wxRegion::GetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
442 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
457 wxRect
wxRegion::GetBox() const
460 GetBox( x
, y
, w
, h
);
461 return wxRect( x
, y
, w
, h
);
464 bool wxRegion::Offset( wxCoord x
, wxCoord y
)
471 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
476 bool wxRegion::Empty() const
481 return gdk_region_empty( M_REGIONDATA
->m_region
);
484 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
) const
489 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
495 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
505 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
508 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
509 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
510 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
515 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
517 return Contains( pt
.x
, pt
.y
);
520 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
522 return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
525 GdkRegion
*wxRegion::GetRegion() const
528 return (GdkRegion
*) NULL
;
530 return M_REGIONDATA
->m_region
;
533 wxList
*wxRegion::GetRectList() const
537 return (wxList
*) NULL
;
539 return &(M_REGIONDATA
->m_rects
);
541 return (wxList
*) NULL
;
545 // ----------------------------------------------------------------------------
547 // ----------------------------------------------------------------------------
551 wxRegionIterator::wxRegionIterator()
556 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
561 void wxRegionIterator::Reset( const wxRegion
& region
)
567 wxRegionIterator::operator bool () const
569 return m_region
.GetRectList() && m_current
< (size_t)m_region
.GetRectList()->Number();
572 bool wxRegionIterator::HaveRects() const
574 return m_region
.GetRectList() && m_current
< (size_t)m_region
.GetRectList()->Number();
577 void wxRegionIterator::operator ++ ()
579 if (HaveRects()) ++m_current
;
582 void wxRegionIterator::operator ++ (int)
584 if (HaveRects()) ++m_current
;
587 wxCoord
wxRegionIterator::GetX() const
589 wxNode
*node
= m_region
.GetRectList()->Nth( m_current
);
591 wxRect
*r
= (wxRect
*)node
->Data();
595 wxCoord
wxRegionIterator::GetY() const
597 wxNode
*node
= m_region
.GetRectList()->Nth( m_current
);
599 wxRect
*r
= (wxRect
*)node
->Data();
603 wxCoord
wxRegionIterator::GetW() const
605 wxNode
*node
= m_region
.GetRectList()->Nth( m_current
);
607 wxRect
*r
= (wxRect
*)node
->Data();
611 wxCoord
wxRegionIterator::GetH() const
613 wxNode
*node
= m_region
.GetRectList()->Nth( m_current
);
615 wxRect
*r
= (wxRect
*)node
->Data();
621 // the following structures must match the private structures
622 // in X11 region code ( xc/lib/X11/region.h )
624 // this makes the Region type transparent
625 // and we have access to the region rectangles
628 short x1
, x2
, y1
, y2
;
632 long size
, numRects
;
633 _XBox
*rects
, extents
;
636 class wxRIRefData
: public wxObjectRefData
640 wxRIRefData() : m_rects(0), m_numRects(0){}
646 void CreateRects( const wxRegion
& r
);
649 wxRIRefData::~wxRIRefData()
654 #include <gdk/gdkprivate.h>
656 void wxRIRefData::CreateRects( const wxRegion
& region
)
662 GdkRegion
*gdkregion
= region
.GetRegion();
664 Region r
= ((GdkRegionPrivate
*)gdkregion
)->xregion
;
666 m_numRects
= r
->numRects
;
669 m_rects
= new wxRect
[m_numRects
];
670 for( size_t i
=0; i
<m_numRects
; ++i
)
672 _XBox
&xr
= r
->rects
[i
];
673 wxRect
&wr
= m_rects
[i
];
676 wr
.width
= xr
.x2
-xr
.x1
;
677 wr
.height
= xr
.y2
-xr
.y1
;
684 wxRegionIterator::wxRegionIterator()
686 m_refData
= new wxRIRefData();
690 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
692 m_refData
= new wxRIRefData();
696 void wxRegionIterator::Reset( const wxRegion
& region
)
699 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
703 bool wxRegionIterator::HaveRects() const
705 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
708 wxRegionIterator::operator bool () const
713 void wxRegionIterator::operator ++ ()
715 if (HaveRects()) ++m_current
;
718 void wxRegionIterator::operator ++ (int)
720 if (HaveRects()) ++m_current
;
723 wxCoord
wxRegionIterator::GetX() const
725 if( !HaveRects() ) return 0;
726 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
729 wxCoord
wxRegionIterator::GetY() const
731 if( !HaveRects() ) return 0;
732 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
735 wxCoord
wxRegionIterator::GetW() const
737 if( !HaveRects() ) return -1;
738 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
741 wxCoord
wxRegionIterator::GetH() const
743 if( !HaveRects() ) return -1;
744 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;
747 wxRect
wxRegionIterator::GetRect() const
751 r
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];
756 #endif // OLDCODE/!OLDCODE