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"
29 // ----------------------------------------------------------------------------
30 // wxRegionRefData: private class containing the information about the region
31 // ----------------------------------------------------------------------------
33 class wxRegionRefData
: public wxObjectRefData
41 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( GdkRegion
*region
)
100 m_refData
= new wxRegionRefData();
101 M_REGIONDATA
->m_region
= gdk_region_copy( region
);
104 wxRegion::wxRegion( size_t n
, const wxPoint
*points
, int fillStyle
)
106 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
107 for ( size_t i
= 0 ; i
< n
; i
++ )
109 gdkpoints
[i
].x
= points
[i
].x
;
110 gdkpoints
[i
].y
= points
[i
].y
;
113 m_refData
= new wxRegionRefData();
115 GdkRegion
* reg
= gdk_region_polygon
119 fillStyle
== wxWINDING_RULE
? GDK_WINDING_RULE
123 M_REGIONDATA
->m_region
= reg
;
128 wxRegion::~wxRegion()
130 // m_refData unrefed in ~wxObject
133 wxObjectRefData
*wxRegion::CreateRefData() const
135 return new wxRegionRefData
;
138 wxObjectRefData
*wxRegion::CloneRefData(const wxObjectRefData
*data
) const
140 return new wxRegionRefData(*(wxRegionRefData
*)data
);
143 // ----------------------------------------------------------------------------
144 // wxRegion comparison
145 // ----------------------------------------------------------------------------
147 bool wxRegion::operator==( const wxRegion
& region
)
149 if (m_refData
== region
.m_refData
) return TRUE
;
151 if (!m_refData
|| !region
.m_refData
) return FALSE
;
153 // compare the regions themselves, not the pointers to ref data!
154 return gdk_region_equal(M_REGIONDATA
->m_region
,
155 M_REGIONDATA_OF(region
)->m_region
);
158 // ----------------------------------------------------------------------------
159 // wxRegion operations
160 // ----------------------------------------------------------------------------
162 void wxRegion::Clear()
167 bool wxRegion::Union( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
173 rect
.height
= height
;
177 m_refData
= new wxRegionRefData();
179 M_REGIONDATA
->m_region
= gdk_region_rectangle( &rect
);
181 GdkRegion
*reg
= gdk_region_new();
182 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( reg
, &rect
);
183 gdk_region_destroy( reg
);
191 gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
193 GdkRegion
*reg
= gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
194 gdk_region_destroy( M_REGIONDATA
->m_region
);
195 M_REGIONDATA
->m_region
= reg
;
202 bool wxRegion::Union( const wxRect
& rect
)
204 return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
207 bool wxRegion::Union( const wxRegion
& region
)
214 m_refData
= new wxRegionRefData();
215 M_REGIONDATA
->m_region
= gdk_region_new();
223 gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
225 GdkRegion
*reg
= gdk_regions_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
226 gdk_region_destroy( M_REGIONDATA
->m_region
);
227 M_REGIONDATA
->m_region
= reg
;
233 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
235 wxRegion
reg( x
, y
, width
, height
);
237 return Intersect( reg
);
240 bool wxRegion::Intersect( const wxRect
& rect
)
242 wxRegion
reg( rect
);
244 return Intersect( reg
);
247 bool wxRegion::Intersect( const wxRegion
& region
)
254 m_refData
= new wxRegionRefData();
255 M_REGIONDATA
->m_region
= gdk_region_new();
266 gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
268 GdkRegion
*reg
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
269 gdk_region_destroy( M_REGIONDATA
->m_region
);
270 M_REGIONDATA
->m_region
= reg
;
276 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
278 wxRegion
reg( x
, y
, width
, height
);
279 return Subtract( reg
);
282 bool wxRegion::Subtract( const wxRect
& rect
)
284 wxRegion
reg( rect
);
285 return Subtract( reg
);
288 bool wxRegion::Subtract( const wxRegion
& region
)
295 m_refData
= new wxRegionRefData();
296 M_REGIONDATA
->m_region
= gdk_region_new();
304 gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
306 GdkRegion
*reg
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
307 gdk_region_destroy( M_REGIONDATA
->m_region
);
308 M_REGIONDATA
->m_region
= reg
;
314 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
316 wxRegion
reg( x
, y
, width
, height
);
320 bool wxRegion::Xor( const wxRect
& rect
)
322 wxRegion
reg( rect
);
326 bool wxRegion::Xor( const wxRegion
& region
)
333 m_refData
= new wxRegionRefData();
334 M_REGIONDATA
->m_region
= gdk_region_new();
342 gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
344 GdkRegion
*reg
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
345 gdk_region_destroy( M_REGIONDATA
->m_region
);
346 M_REGIONDATA
->m_region
= reg
;
352 // ----------------------------------------------------------------------------
354 // ----------------------------------------------------------------------------
356 void wxRegion::GetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
361 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
376 wxRect
wxRegion::GetBox() const
379 GetBox( x
, y
, w
, h
);
380 return wxRect( x
, y
, w
, h
);
383 bool wxRegion::Offset( wxCoord x
, wxCoord y
)
390 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
395 bool wxRegion::Empty() const
400 return gdk_region_empty( M_REGIONDATA
->m_region
);
403 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
) const
408 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
414 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
424 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
427 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
428 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
429 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
434 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
436 return Contains( pt
.x
, pt
.y
);
439 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
441 return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
444 GdkRegion
*wxRegion::GetRegion() const
447 return (GdkRegion
*) NULL
;
449 return M_REGIONDATA
->m_region
;
452 // ----------------------------------------------------------------------------
454 // ----------------------------------------------------------------------------
458 // the following structures must match the private structures
459 // in X11 region code ( xc/lib/X11/region.h )
461 // this makes the Region type transparent
462 // and we have access to the region rectangles
464 #include <gdk/gdkprivate.h>
467 short x1
, x2
, y1
, y2
;
471 long size
, numRects
;
472 _XBox
*rects
, extents
;
477 class wxRIRefData
: public wxObjectRefData
480 wxRIRefData() { Init(); }
481 virtual ~wxRIRefData();
483 void CreateRects( const wxRegion
& r
);
485 void Init() { m_rects
= NULL
; m_numRects
= 0; }
491 wxRIRefData::~wxRIRefData()
496 void wxRIRefData::CreateRects( const wxRegion
& region
)
502 GdkRegion
*gdkregion
= region
.GetRegion();
507 GdkRectangle
*gdkrects
= NULL
;
509 gdk_region_get_rectangles( gdkregion
, &gdkrects
, &numRects
);
511 m_numRects
= numRects
;
514 m_rects
= new wxRect
[m_numRects
];
515 for (size_t i
=0; i
< m_numRects
; ++i
)
517 GdkRectangle
&gr
= gdkrects
[i
];
518 wxRect
&wr
= m_rects
[i
];
522 wr
.height
= gr
.height
;
527 Region r
= ((GdkRegionPrivate
*)gdkregion
)->xregion
;
530 m_numRects
= r
->numRects
;
533 m_rects
= new wxRect
[m_numRects
];
534 for (size_t i
=0; i
< m_numRects
; ++i
)
536 _XBox
&xr
= r
->rects
[i
];
537 wxRect
&wr
= m_rects
[i
];
540 wr
.width
= xr
.x2
-xr
.x1
;
541 wr
.height
= xr
.y2
-xr
.y1
;
545 #endif // GTK+ 2.0/1.x
548 wxRegionIterator::wxRegionIterator()
550 m_refData
= new wxRIRefData();
554 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
556 m_refData
= new wxRIRefData();
560 void wxRegionIterator::Reset( const wxRegion
& region
)
563 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
567 bool wxRegionIterator::HaveRects() const
569 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
572 wxRegionIterator::operator bool () const
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 if( !HaveRects() ) return 0;
590 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
593 wxCoord
wxRegionIterator::GetY() const
595 if( !HaveRects() ) return 0;
596 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
599 wxCoord
wxRegionIterator::GetW() const
601 if( !HaveRects() ) return -1;
602 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
605 wxCoord
wxRegionIterator::GetH() const
607 if( !HaveRects() ) return -1;
608 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;
611 wxRect
wxRegionIterator::GetRect() const
615 r
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];