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
)
44 m_region
= gdk_region_copy(refData
.m_region
);
46 m_region
= gdk_region_new();
47 GdkRegion
*regCopy
= gdk_regions_union(m_region
, refData
.m_region
);
48 gdk_region_destroy(m_region
);
56 gdk_region_destroy( m_region
);
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
66 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
67 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
69 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
);
70 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
);
72 // ----------------------------------------------------------------------------
73 // wxRegion construction
74 // ----------------------------------------------------------------------------
76 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
78 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
)
86 m_refData
= new wxRegionRefData();
89 M_REGIONDATA
->m_region
= gdk_region_rectangle( &rect
);
91 GdkRegion
*reg
= gdk_region_new();
92 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( reg
, &rect
);
93 gdk_region_destroy( reg
);
97 wxRegion::wxRegion( size_t n
, const wxPoint
*points
, int fillStyle
)
99 GdkPoint
*gdkpoints
= new GdkPoint
[n
];
100 for ( size_t i
= 0 ; i
< n
; i
++ )
102 gdkpoints
[i
].x
= points
[i
].x
;
103 gdkpoints
[i
].y
= points
[i
].y
;
106 m_refData
= new wxRegionRefData();
108 GdkRegion
* reg
= gdk_region_polygon
112 fillStyle
== wxWINDING_RULE
? GDK_WINDING_RULE
116 M_REGIONDATA
->m_region
= reg
;
121 wxRegion::~wxRegion()
123 // m_refData unrefed in ~wxObject
126 wxObjectRefData
*wxRegion::CreateRefData() const
128 return new wxRegionRefData
;
131 wxObjectRefData
*wxRegion::CloneRefData(const wxObjectRefData
*data
) const
133 return new wxRegionRefData(*(wxRegionRefData
*)data
);
136 // ----------------------------------------------------------------------------
137 // wxRegion comparison
138 // ----------------------------------------------------------------------------
140 bool wxRegion::operator==( const wxRegion
& region
)
142 if (m_refData
== region
.m_refData
) return TRUE
;
144 if (!m_refData
|| !region
.m_refData
) return FALSE
;
146 // compare the regions themselves, not the pointers to ref data!
147 return gdk_region_equal(M_REGIONDATA
->m_region
,
148 M_REGIONDATA_OF(region
)->m_region
);
151 // ----------------------------------------------------------------------------
152 // wxRegion operations
153 // ----------------------------------------------------------------------------
155 void wxRegion::Clear()
160 bool wxRegion::Union( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
166 rect
.height
= height
;
170 m_refData
= new wxRegionRefData();
172 M_REGIONDATA
->m_region
= gdk_region_rectangle( &rect
);
174 GdkRegion
*reg
= gdk_region_new();
175 M_REGIONDATA
->m_region
= gdk_region_union_with_rect( reg
, &rect
);
176 gdk_region_destroy( reg
);
184 gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
186 GdkRegion
*reg
= gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect
);
187 gdk_region_destroy( M_REGIONDATA
->m_region
);
188 M_REGIONDATA
->m_region
= reg
;
195 bool wxRegion::Union( const wxRect
& rect
)
197 return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
200 bool wxRegion::Union( const wxRegion
& region
)
207 m_refData
= new wxRegionRefData();
208 M_REGIONDATA
->m_region
= gdk_region_new();
216 gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
218 GdkRegion
*reg
= gdk_regions_union( M_REGIONDATA
->m_region
, region
.GetRegion() );
219 gdk_region_destroy( M_REGIONDATA
->m_region
);
220 M_REGIONDATA
->m_region
= reg
;
226 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
228 wxRegion
reg( x
, y
, width
, height
);
230 return Intersect( reg
);
233 bool wxRegion::Intersect( const wxRect
& rect
)
235 wxRegion
reg( rect
);
237 return Intersect( reg
);
240 bool wxRegion::Intersect( const wxRegion
& region
)
247 m_refData
= new wxRegionRefData();
248 M_REGIONDATA
->m_region
= gdk_region_new();
259 gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
261 GdkRegion
*reg
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() );
262 gdk_region_destroy( M_REGIONDATA
->m_region
);
263 M_REGIONDATA
->m_region
= reg
;
269 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
271 wxRegion
reg( x
, y
, width
, height
);
272 return Subtract( reg
);
275 bool wxRegion::Subtract( const wxRect
& rect
)
277 wxRegion
reg( rect
);
278 return Subtract( reg
);
281 bool wxRegion::Subtract( const wxRegion
& region
)
288 m_refData
= new wxRegionRefData();
289 M_REGIONDATA
->m_region
= gdk_region_new();
297 gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
299 GdkRegion
*reg
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() );
300 gdk_region_destroy( M_REGIONDATA
->m_region
);
301 M_REGIONDATA
->m_region
= reg
;
307 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
309 wxRegion
reg( x
, y
, width
, height
);
313 bool wxRegion::Xor( const wxRect
& rect
)
315 wxRegion
reg( rect
);
319 bool wxRegion::Xor( const wxRegion
& region
)
326 m_refData
= new wxRegionRefData();
327 M_REGIONDATA
->m_region
= gdk_region_new();
335 gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
337 GdkRegion
*reg
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() );
338 gdk_region_destroy( M_REGIONDATA
->m_region
);
339 M_REGIONDATA
->m_region
= reg
;
345 // ----------------------------------------------------------------------------
347 // ----------------------------------------------------------------------------
349 void wxRegion::GetBox( wxCoord
&x
, wxCoord
&y
, wxCoord
&w
, wxCoord
&h
) const
354 gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect
);
369 wxRect
wxRegion::GetBox() const
372 GetBox( x
, y
, w
, h
);
373 return wxRect( x
, y
, w
, h
);
376 bool wxRegion::Offset( wxCoord x
, wxCoord y
)
383 gdk_region_offset( M_REGIONDATA
->m_region
, x
, y
);
388 bool wxRegion::Empty() const
393 return gdk_region_empty( M_REGIONDATA
->m_region
);
396 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
) const
401 if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y
))
407 wxRegionContain
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) const
417 GdkOverlapType res
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect
);
420 case GDK_OVERLAP_RECTANGLE_IN
: return wxInRegion
;
421 case GDK_OVERLAP_RECTANGLE_OUT
: return wxOutRegion
;
422 case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
;
427 wxRegionContain
wxRegion::Contains(const wxPoint
& pt
) const
429 return Contains( pt
.x
, pt
.y
);
432 wxRegionContain
wxRegion::Contains(const wxRect
& rect
) const
434 return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
437 GdkRegion
*wxRegion::GetRegion() const
440 return (GdkRegion
*) NULL
;
442 return M_REGIONDATA
->m_region
;
445 // ----------------------------------------------------------------------------
447 // ----------------------------------------------------------------------------
451 // the following structures must match the private structures
452 // in X11 region code ( xc/lib/X11/region.h )
454 // this makes the Region type transparent
455 // and we have access to the region rectangles
457 #include <gdk/gdkprivate.h>
460 short x1
, x2
, y1
, y2
;
464 long size
, numRects
;
465 _XBox
*rects
, extents
;
470 class wxRIRefData
: public wxObjectRefData
474 wxRIRefData() : m_rects(0), m_numRects(0){}
480 void CreateRects( const wxRegion
& r
);
483 wxRIRefData::~wxRIRefData()
488 void wxRIRefData::CreateRects( const wxRegion
& region
)
496 GdkRegion
*gdkregion
= region
.GetRegion();
497 if (!gdkregion
) return;
500 GdkRectangle
*gdkrects
= NULL
;
502 gdk_region_get_rectangles( gdkregion
, &gdkrects
, &numRects
);
504 m_numRects
= numRects
;
507 m_rects
= new wxRect
[m_numRects
];
508 for (size_t i
=0; i
< m_numRects
; ++i
)
510 GdkRectangle
&gr
= gdkrects
[i
];
511 wxRect
&wr
= m_rects
[i
];
515 wr
.height
= gr
.height
;
520 Region r
= ((GdkRegionPrivate
*)gdkregion
)->xregion
;
523 m_numRects
= r
->numRects
;
526 m_rects
= new wxRect
[m_numRects
];
527 for (size_t i
=0; i
< m_numRects
; ++i
)
529 _XBox
&xr
= r
->rects
[i
];
530 wxRect
&wr
= m_rects
[i
];
533 wr
.width
= xr
.x2
-xr
.x1
;
534 wr
.height
= xr
.y2
-xr
.y1
;
538 #endif // GTK+ 2.0/1.x
541 wxRegionIterator::wxRegionIterator()
543 m_refData
= new wxRIRefData();
547 wxRegionIterator::wxRegionIterator( const wxRegion
& region
)
549 m_refData
= new wxRIRefData();
553 void wxRegionIterator::Reset( const wxRegion
& region
)
556 ((wxRIRefData
*)m_refData
)->CreateRects(region
);
560 bool wxRegionIterator::HaveRects() const
562 return m_current
< ((wxRIRefData
*)m_refData
)->m_numRects
;
565 wxRegionIterator::operator bool () const
570 void wxRegionIterator::operator ++ ()
572 if (HaveRects()) ++m_current
;
575 void wxRegionIterator::operator ++ (int)
577 if (HaveRects()) ++m_current
;
580 wxCoord
wxRegionIterator::GetX() const
582 if( !HaveRects() ) return 0;
583 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
;
586 wxCoord
wxRegionIterator::GetY() const
588 if( !HaveRects() ) return 0;
589 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
;
592 wxCoord
wxRegionIterator::GetW() const
594 if( !HaveRects() ) return -1;
595 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
;
598 wxCoord
wxRegionIterator::GetH() const
600 if( !HaveRects() ) return -1;
601 return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
;
604 wxRect
wxRegionIterator::GetRect() const
608 r
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];