1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/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 // ============================================================================ 
  15 // ---------------------------------------------------------------------------- 
  17 // ---------------------------------------------------------------------------- 
  19 // For compilers that support precompilation, includes "wx.h". 
  20 #include "wx/wxprec.h" 
  22 #include "wx/region.h" 
  28 #include "wx/gtk/private.h" 
  31 // ---------------------------------------------------------------------------- 
  32 // wxRegionRefData: private class containing the information about the region 
  33 // ---------------------------------------------------------------------------- 
  35 class wxRegionRefData 
: public wxObjectRefData
 
  43     wxRegionRefData(const wxRegionRefData
& refData
) 
  46         m_region 
= gdk_region_copy(refData
.m_region
); 
  52             gdk_region_destroy( m_region 
); 
  58 // ---------------------------------------------------------------------------- 
  60 // ---------------------------------------------------------------------------- 
  62 #define M_REGIONDATA ((wxRegionRefData *)m_refData) 
  63 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData)) 
  65 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
) 
  66 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
) 
  68 // ---------------------------------------------------------------------------- 
  69 // wxRegion construction 
  70 // ---------------------------------------------------------------------------- 
  72 #define M_REGIONDATA ((wxRegionRefData *)m_refData) 
  74 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) 
  82     m_refData 
= new wxRegionRefData(); 
  84     M_REGIONDATA
->m_region 
= gdk_region_rectangle( &rect 
); 
  87 wxRegion::wxRegion( GdkRegion 
*region 
) 
  89     m_refData 
= new wxRegionRefData(); 
  90     M_REGIONDATA
->m_region 
= gdk_region_copy( region 
); 
  93 wxRegion::wxRegion( size_t n
, const wxPoint 
*points
, int fillStyle 
) 
  95     GdkPoint 
*gdkpoints 
= new GdkPoint
[n
]; 
  96     for ( size_t i 
= 0 ; i 
< n 
; i
++ ) 
  98         gdkpoints
[i
].x 
= points
[i
].x
; 
  99         gdkpoints
[i
].y 
= points
[i
].y
; 
 102     m_refData 
= new wxRegionRefData(); 
 104     GdkRegion
* reg 
= gdk_region_polygon
 
 108                         fillStyle 
== wxWINDING_RULE 
? GDK_WINDING_RULE
 
 112     M_REGIONDATA
->m_region 
= reg
; 
 117 wxRegion::~wxRegion() 
 119     // m_refData unrefed in ~wxObject 
 122 wxObjectRefData 
*wxRegion::CreateRefData() const 
 124     return new wxRegionRefData
; 
 127 wxObjectRefData 
*wxRegion::CloneRefData(const wxObjectRefData 
*data
) const 
 129     return new wxRegionRefData(*(wxRegionRefData 
*)data
); 
 132 // ---------------------------------------------------------------------------- 
 133 // wxRegion comparison 
 134 // ---------------------------------------------------------------------------- 
 136 bool wxRegion::operator==( const wxRegion
& region 
) const 
 138     if (m_refData 
== region
.m_refData
) return true; 
 140     if (!m_refData 
|| !region
.m_refData
) return false; 
 142     // compare the regions themselves, not the pointers to ref data! 
 143     return gdk_region_equal(M_REGIONDATA
->m_region
, 
 144                             M_REGIONDATA_OF(region
)->m_region
); 
 147 // ---------------------------------------------------------------------------- 
 148 // wxRegion operations 
 149 // ---------------------------------------------------------------------------- 
 151 void wxRegion::Clear() 
 156 bool wxRegion::Union( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 158     // workaround for a strange GTK/X11 bug: taking union with an empty 
 159     // rectangle results in an empty region which is definitely not what we 
 161     if ( !width 
|| !height 
) 
 166         InitRect(x
, y
, width
, height
); 
 176         rect
.height 
= height
; 
 178         gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect 
); 
 184 bool wxRegion::Union( const wxRect
& rect 
) 
 186     return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height 
); 
 189 bool wxRegion::Union( const wxRegion
& region 
) 
 196         m_refData 
= new wxRegionRefData(); 
 197         M_REGIONDATA
->m_region 
= gdk_region_new(); 
 204     gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 209 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 211     wxRegion 
reg( x
, y
, width
, height 
); 
 213     return Intersect( reg 
); 
 216 bool wxRegion::Intersect( const wxRect
& rect 
) 
 218     wxRegion 
reg( rect 
); 
 220     return Intersect( reg 
); 
 223 bool wxRegion::Intersect( const wxRegion
& region 
) 
 230         // intersecting with invalid region doesn't make sense 
 236     gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 241 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 243     wxRegion 
reg( x
, y
, width
, height 
); 
 244     return Subtract( reg 
); 
 247 bool wxRegion::Subtract( const wxRect
& rect 
) 
 249     wxRegion 
reg( rect 
); 
 250     return Subtract( reg 
); 
 253 bool wxRegion::Subtract( const wxRegion
& region 
) 
 260         // subtracting from an invalid region doesn't make sense 
 266     gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 271 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 273     wxRegion 
reg( x
, y
, width
, height 
); 
 277 bool wxRegion::Xor( const wxRect
& rect 
) 
 279     wxRegion 
reg( rect 
); 
 283 bool wxRegion::Xor( const wxRegion
& region 
) 
 295     gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 300 bool wxRegion::Offset( wxCoord x
, wxCoord y 
) 
 307     gdk_region_offset( M_REGIONDATA
->m_region
, x
, y 
); 
 312 // ---------------------------------------------------------------------------- 
 314 // ---------------------------------------------------------------------------- 
 316 void wxRegion::GetBox( wxCoord 
&x
, wxCoord 
&y
, wxCoord 
&w
, wxCoord 
&h 
) const 
 321         gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect 
); 
 336 wxRect 
wxRegion::GetBox() const 
 339     GetBox( x
, y
, w
, h 
); 
 340     return wxRect( x
, y
, w
, h 
); 
 343 bool wxRegion::Empty() const 
 348     return gdk_region_empty( M_REGIONDATA
->m_region 
); 
 351 wxRegionContain 
wxRegion::Contains( wxCoord x
, wxCoord y 
) const 
 356     if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y 
)) 
 362 wxRegionContain 
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h 
) const 
 372     GdkOverlapType res 
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect 
); 
 375         case GDK_OVERLAP_RECTANGLE_IN
:   return wxInRegion
; 
 376         case GDK_OVERLAP_RECTANGLE_OUT
:  return wxOutRegion
; 
 377         case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
; 
 382 wxRegionContain 
wxRegion::Contains(const wxPoint
& pt
) const 
 384     return Contains( pt
.x
, pt
.y 
); 
 387 wxRegionContain 
wxRegion::Contains(const wxRect
& rect
) const 
 389     return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height 
); 
 392 GdkRegion 
*wxRegion::GetRegion() const 
 395         return (GdkRegion
*) NULL
; 
 397     return M_REGIONDATA
->m_region
; 
 400 // ---------------------------------------------------------------------------- 
 402 // ---------------------------------------------------------------------------- 
 404 class wxRIRefData
: public wxObjectRefData
 
 407     wxRIRefData() { Init(); } 
 408     virtual ~wxRIRefData(); 
 410     void CreateRects( const wxRegion
& r 
); 
 412     void Init() { m_rects 
= NULL
; m_numRects 
= 0; } 
 418 wxRIRefData::~wxRIRefData() 
 423 void wxRIRefData::CreateRects( const wxRegion
& region 
) 
 429     GdkRegion 
*gdkregion 
= region
.GetRegion(); 
 433     GdkRectangle 
*gdkrects 
= NULL
; 
 435     gdk_region_get_rectangles( gdkregion
, &gdkrects
, &numRects 
); 
 437     m_numRects 
= numRects
; 
 440         m_rects 
= new wxRect
[m_numRects
]; 
 441         for (size_t i
=0; i 
< m_numRects
; ++i
) 
 443             GdkRectangle 
&gr 
= gdkrects
[i
]; 
 444             wxRect 
&wr 
= m_rects
[i
]; 
 448             wr
.height 
= gr
.height
; 
 454 wxRegionIterator::wxRegionIterator() 
 456     m_refData 
= new wxRIRefData(); 
 460 wxRegionIterator::wxRegionIterator( const wxRegion
& region 
) 
 462     m_refData 
= new wxRIRefData(); 
 466 void wxRegionIterator::Reset( const wxRegion
& region 
) 
 469     ((wxRIRefData
*)m_refData
)->CreateRects(region
); 
 473 bool wxRegionIterator::HaveRects() const 
 475     return m_current 
< ((wxRIRefData
*)m_refData
)->m_numRects
; 
 478 wxRegionIterator
& wxRegionIterator::operator ++ () 
 486 wxRegionIterator 
wxRegionIterator::operator ++ (int) 
 488     wxRegionIterator tmp 
= *this; 
 495 wxCoord 
wxRegionIterator::GetX() const 
 497     wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") ); 
 499     return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
; 
 502 wxCoord 
wxRegionIterator::GetY() const 
 504     wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") ); 
 506     return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
; 
 509 wxCoord 
wxRegionIterator::GetW() const 
 511     wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") ); 
 513     return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
; 
 516 wxCoord 
wxRegionIterator::GetH() const 
 518     wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") ); 
 520     return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
; 
 523 wxRect 
wxRegionIterator::GetRect() const 
 527         r 
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];