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 // ============================================================================ 
  15 // ---------------------------------------------------------------------------- 
  17 // ---------------------------------------------------------------------------- 
  19 // For compilers that support precompilation, includes "wx.h". 
  20 #include "wx/wxprec.h" 
  22 #include "wx/region.h" 
  24 #include "wx/gtk/private.h" 
  27 // ---------------------------------------------------------------------------- 
  28 // wxRegionRefData: private class containing the information about the region 
  29 // ---------------------------------------------------------------------------- 
  31 class wxRegionRefData 
: public wxObjectRefData
 
  39     wxRegionRefData(const wxRegionRefData
& refData
) 
  42         m_region 
= gdk_region_copy(refData
.m_region
); 
  48             gdk_region_destroy( m_region 
); 
  54 // ---------------------------------------------------------------------------- 
  56 // ---------------------------------------------------------------------------- 
  58 #define M_REGIONDATA ((wxRegionRefData *)m_refData) 
  59 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData)) 
  61 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
) 
  62 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
) 
  64 // ---------------------------------------------------------------------------- 
  65 // wxRegion construction 
  66 // ---------------------------------------------------------------------------- 
  68 #define M_REGIONDATA ((wxRegionRefData *)m_refData) 
  70 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) 
  78     m_refData 
= new wxRegionRefData(); 
  80     M_REGIONDATA
->m_region 
= gdk_region_rectangle( &rect 
); 
  83 wxRegion::wxRegion( GdkRegion 
*region 
) 
  85     m_refData 
= new wxRegionRefData(); 
  86     M_REGIONDATA
->m_region 
= gdk_region_copy( region 
); 
  89 wxRegion::wxRegion( size_t n
, const wxPoint 
*points
, int fillStyle 
) 
  91     GdkPoint 
*gdkpoints 
= new GdkPoint
[n
]; 
  92     for ( size_t i 
= 0 ; i 
< n 
; i
++ ) 
  94         gdkpoints
[i
].x 
= points
[i
].x
; 
  95         gdkpoints
[i
].y 
= points
[i
].y
; 
  98     m_refData 
= new wxRegionRefData(); 
 100     GdkRegion
* reg 
= gdk_region_polygon
 
 104                         fillStyle 
== wxWINDING_RULE 
? GDK_WINDING_RULE
 
 108     M_REGIONDATA
->m_region 
= reg
; 
 113 wxRegion::~wxRegion() 
 115     // m_refData unrefed in ~wxObject 
 118 wxObjectRefData 
*wxRegion::CreateRefData() const 
 120     return new wxRegionRefData
; 
 123 wxObjectRefData 
*wxRegion::CloneRefData(const wxObjectRefData 
*data
) const 
 125     return new wxRegionRefData(*(wxRegionRefData 
*)data
); 
 128 // ---------------------------------------------------------------------------- 
 129 // wxRegion comparison 
 130 // ---------------------------------------------------------------------------- 
 132 bool wxRegion::operator==( const wxRegion
& region 
) const 
 134     if (m_refData 
== region
.m_refData
) return TRUE
; 
 136     if (!m_refData 
|| !region
.m_refData
) return FALSE
; 
 138     // compare the regions themselves, not the pointers to ref data! 
 139     return gdk_region_equal(M_REGIONDATA
->m_region
, 
 140                             M_REGIONDATA_OF(region
)->m_region
); 
 143 // ---------------------------------------------------------------------------- 
 144 // wxRegion operations 
 145 // ---------------------------------------------------------------------------- 
 147 void wxRegion::Clear() 
 152 bool wxRegion::Union( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 154     // workaround for a strange GTK/X11 bug: taking union with an empty 
 155     // rectangle results in an empty region which is definitely not what we 
 157     if ( !width 
|| !height 
) 
 162         InitRect(x
, y
, width
, height
); 
 172         rect
.height 
= height
; 
 174         gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect 
); 
 180 bool wxRegion::Union( const wxRect
& rect 
) 
 182     return Union( rect
.x
, rect
.y
, rect
.width
, rect
.height 
); 
 185 bool wxRegion::Union( const wxRegion
& region 
) 
 192         m_refData 
= new wxRegionRefData(); 
 193         M_REGIONDATA
->m_region 
= gdk_region_new(); 
 200     gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 205 bool wxRegion::Intersect( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 207     wxRegion 
reg( x
, y
, width
, height 
); 
 209     return Intersect( reg 
); 
 212 bool wxRegion::Intersect( const wxRect
& rect 
) 
 214     wxRegion 
reg( rect 
); 
 216     return Intersect( reg 
); 
 219 bool wxRegion::Intersect( const wxRegion
& region 
) 
 226         // intersecting with invalid region doesn't make sense 
 232     gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 237 bool wxRegion::Subtract( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 239     wxRegion 
reg( x
, y
, width
, height 
); 
 240     return Subtract( reg 
); 
 243 bool wxRegion::Subtract( const wxRect
& rect 
) 
 245     wxRegion 
reg( rect 
); 
 246     return Subtract( reg 
); 
 249 bool wxRegion::Subtract( const wxRegion
& region 
) 
 256         // subtracting from an invalid region doesn't make sense 
 262     gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 267 bool wxRegion::Xor( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 269     wxRegion 
reg( x
, y
, width
, height 
); 
 273 bool wxRegion::Xor( const wxRect
& rect 
) 
 275     wxRegion 
reg( rect 
); 
 279 bool wxRegion::Xor( const wxRegion
& region 
) 
 291     gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 296 bool wxRegion::Offset( wxCoord x
, wxCoord y 
) 
 303     gdk_region_offset( M_REGIONDATA
->m_region
, x
, y 
); 
 308 // ---------------------------------------------------------------------------- 
 310 // ---------------------------------------------------------------------------- 
 312 void wxRegion::GetBox( wxCoord 
&x
, wxCoord 
&y
, wxCoord 
&w
, wxCoord 
&h 
) const 
 317         gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect 
); 
 332 wxRect 
wxRegion::GetBox() const 
 335     GetBox( x
, y
, w
, h 
); 
 336     return wxRect( x
, y
, w
, h 
); 
 339 bool wxRegion::Empty() const 
 344     return gdk_region_empty( M_REGIONDATA
->m_region 
); 
 347 wxRegionContain 
wxRegion::Contains( wxCoord x
, wxCoord y 
) const 
 352     if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y 
)) 
 358 wxRegionContain 
wxRegion::Contains( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h 
) const 
 368     GdkOverlapType res 
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect 
); 
 371         case GDK_OVERLAP_RECTANGLE_IN
:   return wxInRegion
; 
 372         case GDK_OVERLAP_RECTANGLE_OUT
:  return wxOutRegion
; 
 373         case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
; 
 378 wxRegionContain 
wxRegion::Contains(const wxPoint
& pt
) const 
 380     return Contains( pt
.x
, pt
.y 
); 
 383 wxRegionContain 
wxRegion::Contains(const wxRect
& rect
) const 
 385     return Contains( rect
.x
, rect
.y
, rect
.width
, rect
.height 
); 
 388 GdkRegion 
*wxRegion::GetRegion() const 
 391         return (GdkRegion
*) NULL
; 
 393     return M_REGIONDATA
->m_region
; 
 396 // ---------------------------------------------------------------------------- 
 398 // ---------------------------------------------------------------------------- 
 400 class wxRIRefData
: public wxObjectRefData
 
 403     wxRIRefData() { Init(); } 
 404     virtual ~wxRIRefData(); 
 406     void CreateRects( const wxRegion
& r 
); 
 408     void Init() { m_rects 
= NULL
; m_numRects 
= 0; } 
 414 wxRIRefData::~wxRIRefData() 
 419 void wxRIRefData::CreateRects( const wxRegion
& region 
) 
 425     GdkRegion 
*gdkregion 
= region
.GetRegion(); 
 429     GdkRectangle 
*gdkrects 
= NULL
; 
 431     gdk_region_get_rectangles( gdkregion
, &gdkrects
, &numRects 
); 
 433     m_numRects 
= numRects
; 
 436         m_rects 
= new wxRect
[m_numRects
]; 
 437         for (size_t i
=0; i 
< m_numRects
; ++i
) 
 439             GdkRectangle 
&gr 
= gdkrects
[i
]; 
 440             wxRect 
&wr 
= m_rects
[i
]; 
 444             wr
.height 
= gr
.height
; 
 450 wxRegionIterator::wxRegionIterator() 
 452     m_refData 
= new wxRIRefData(); 
 456 wxRegionIterator::wxRegionIterator( const wxRegion
& region 
) 
 458     m_refData 
= new wxRIRefData(); 
 462 void wxRegionIterator::Reset( const wxRegion
& region 
) 
 465     ((wxRIRefData
*)m_refData
)->CreateRects(region
); 
 469 bool wxRegionIterator::HaveRects() const 
 471     return m_current 
< ((wxRIRefData
*)m_refData
)->m_numRects
; 
 474 wxRegionIterator
& wxRegionIterator::operator ++ () 
 482 wxRegionIterator 
wxRegionIterator::operator ++ (int) 
 484     wxRegionIterator tmp 
= *this; 
 491 wxCoord 
wxRegionIterator::GetX() const 
 493     wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") ); 
 495     return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
; 
 498 wxCoord 
wxRegionIterator::GetY() const 
 500     wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") ); 
 502     return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
; 
 505 wxCoord 
wxRegionIterator::GetW() const 
 507     wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") ); 
 509     return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
; 
 512 wxCoord 
wxRegionIterator::GetH() const 
 514     wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") ); 
 516     return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
; 
 519 wxRect 
wxRegionIterator::GetRect() const 
 523         r 
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];