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 wxGDIRefData
 
  43     wxRegionRefData(const wxRegionRefData
& refData
) 
  46         m_region 
= gdk_region_copy(refData
.m_region
); 
  49     virtual ~wxRegionRefData() 
  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
, 
  94                     wxPolygonFillMode fillStyle 
) 
  96     GdkPoint 
*gdkpoints 
= new GdkPoint
[n
]; 
  97     for ( size_t i 
= 0 ; i 
< n 
; i
++ ) 
  99         gdkpoints
[i
].x 
= points
[i
].x
; 
 100         gdkpoints
[i
].y 
= points
[i
].y
; 
 103     m_refData 
= new wxRegionRefData(); 
 105     GdkRegion
* reg 
= gdk_region_polygon
 
 109                         fillStyle 
== wxWINDING_RULE 
? GDK_WINDING_RULE
 
 113     M_REGIONDATA
->m_region 
= reg
; 
 118 wxRegion::~wxRegion() 
 120     // m_refData unrefed in ~wxObject 
 123 wxGDIRefData 
*wxRegion::CreateGDIRefData() const 
 125     return new wxRegionRefData
; 
 128 wxGDIRefData 
*wxRegion::CloneGDIRefData(const wxGDIRefData 
*data
) const 
 130     return new wxRegionRefData(*(wxRegionRefData 
*)data
); 
 133 // ---------------------------------------------------------------------------- 
 134 // wxRegion comparison 
 135 // ---------------------------------------------------------------------------- 
 137 bool wxRegion::DoIsEqual(const wxRegion
& region
) const 
 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::DoUnionWithRect(const wxRect
& r
) 
 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 
 162         InitRect(r
.x
, r
.y
, r
.width
, r
.height
); 
 171         rect
.width 
= r
.width
; 
 172         rect
.height 
= r
.height
; 
 174         gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect 
); 
 180 bool wxRegion::DoUnionWithRegion( const wxRegion
& region 
) 
 182     wxCHECK_MSG( region
.Ok(), false, wxT("invalid region") ); 
 186         m_refData 
= new wxRegionRefData(); 
 187         M_REGIONDATA
->m_region 
= gdk_region_new(); 
 194     gdk_region_union( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 199 bool wxRegion::DoIntersect( const wxRegion
& region 
) 
 201     wxCHECK_MSG( region
.Ok(), false, wxT("invalid region") ); 
 205         // intersecting with invalid region doesn't make sense 
 211     gdk_region_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 216 bool wxRegion::DoSubtract( const wxRegion
& region 
) 
 218     wxCHECK_MSG( region
.Ok(), false, wxT("invalid region") ); 
 222         // subtracting from an invalid region doesn't make sense 
 228     gdk_region_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 233 bool wxRegion::DoXor( const wxRegion
& region 
) 
 235     wxCHECK_MSG( region
.Ok(), false, wxT("invalid region") ); 
 244     gdk_region_xor( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 249 bool wxRegion::DoOffset( wxCoord x
, wxCoord y 
) 
 256     gdk_region_offset( M_REGIONDATA
->m_region
, x
, y 
); 
 261 // ---------------------------------------------------------------------------- 
 263 // ---------------------------------------------------------------------------- 
 265 bool wxRegion::DoGetBox( wxCoord 
&x
, wxCoord 
&y
, wxCoord 
&w
, wxCoord 
&h 
) const 
 270         gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect 
); 
 289 bool wxRegion::IsEmpty() const 
 294     return gdk_region_empty( M_REGIONDATA
->m_region 
); 
 297 wxRegionContain 
wxRegion::DoContainsPoint( wxCoord x
, wxCoord y 
) const 
 302     if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y 
)) 
 308 wxRegionContain 
wxRegion::DoContainsRect(const wxRect
& r
) const 
 316     rect
.width 
= r
.width
; 
 317     rect
.height 
= r
.height
; 
 318     GdkOverlapType res 
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect 
); 
 321         case GDK_OVERLAP_RECTANGLE_IN
:   return wxInRegion
; 
 322         case GDK_OVERLAP_RECTANGLE_OUT
:  return wxOutRegion
; 
 323         case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
; 
 328 GdkRegion 
*wxRegion::GetRegion() const 
 333     return M_REGIONDATA
->m_region
; 
 336 // ---------------------------------------------------------------------------- 
 338 // ---------------------------------------------------------------------------- 
 340 wxRegionIterator::wxRegionIterator() 
 346 wxRegionIterator::wxRegionIterator( const wxRegion
& region 
) 
 352 void wxRegionIterator::Init() 
 358 wxRegionIterator::~wxRegionIterator() 
 363 void wxRegionIterator::CreateRects( const wxRegion
& region 
) 
 368     GdkRegion 
*gdkregion 
= region
.GetRegion(); 
 372     GdkRectangle 
*gdkrects 
= NULL
; 
 374     gdk_region_get_rectangles( gdkregion
, &gdkrects
, &numRects 
); 
 376     m_numRects 
= numRects
; 
 379         m_rects 
= new wxRect
[m_numRects
]; 
 380         for (size_t i
=0; i 
< m_numRects
; ++i
) 
 382             GdkRectangle 
&gr 
= gdkrects
[i
]; 
 383             wxRect 
&wr 
= m_rects
[i
]; 
 387             wr
.height 
= gr
.height
; 
 393 void wxRegionIterator::Reset( const wxRegion
& region 
) 
 400 bool wxRegionIterator::HaveRects() const 
 402     return m_current 
< m_numRects
; 
 405 wxRegionIterator
& wxRegionIterator::operator ++ () 
 413 wxRegionIterator 
wxRegionIterator::operator ++ (int) 
 415     wxRegionIterator tmp 
= *this; 
 423 wxCoord 
wxRegionIterator::GetX() const 
 425     wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") ); 
 427     return m_rects
[m_current
].x
; 
 430 wxCoord 
wxRegionIterator::GetY() const 
 432     wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") ); 
 434     return m_rects
[m_current
].y
; 
 437 wxCoord 
wxRegionIterator::GetW() const 
 439     wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") ); 
 441     return m_rects
[m_current
].width
; 
 444 wxCoord 
wxRegionIterator::GetH() const 
 446     wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") ); 
 448     return m_rects
[m_current
].height
; 
 451 wxRect 
wxRegionIterator::GetRect() const 
 455         r 
= m_rects
[m_current
]; 
 460 wxRegionIterator
& wxRegionIterator::operator=(const wxRegionIterator
& ri
) 
 464     m_current 
= ri
.m_current
; 
 465     m_numRects 
= ri
.m_numRects
; 
 468         m_rects 
= new wxRect
[m_numRects
]; 
 469         for ( unsigned int n 
= 0; n 
< m_numRects
; n
++ ) 
 470             m_rects
[n
] = ri
.m_rects
[n
];