1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk1/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/gtk1/private.h" 
  31 // ---------------------------------------------------------------------------- 
  32 // wxGdkRegion: creates a new region in ctor and destroys in dtor 
  33 // ---------------------------------------------------------------------------- 
  38     wxGdkRegion() { m_region 
= gdk_region_new(); } 
  39     ~wxGdkRegion() { gdk_region_destroy(m_region
); } 
  41     operator GdkRegion 
*() const { return m_region
; } 
  48 // ---------------------------------------------------------------------------- 
  49 // wxRegionRefData: private class containing the information about the region 
  50 // ---------------------------------------------------------------------------- 
  52 class wxRegionRefData 
: public wxObjectRefData
 
  60     wxRegionRefData(const wxRegionRefData
& refData
) 
  63         m_region 
= gdk_regions_union(wxGdkRegion(), refData
.m_region
); 
  66     virtual ~wxRegionRefData() 
  69             gdk_region_destroy( m_region 
); 
  75 // ---------------------------------------------------------------------------- 
  77 // ---------------------------------------------------------------------------- 
  79 #define M_REGIONDATA ((wxRegionRefData *)m_refData) 
  80 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData)) 
  82 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
) 
  83 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
,wxObject
) 
  85 // ---------------------------------------------------------------------------- 
  86 // wxRegion construction 
  87 // ---------------------------------------------------------------------------- 
  89 #define M_REGIONDATA ((wxRegionRefData *)m_refData) 
  91 void wxRegion::InitRect(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) 
  99     m_refData 
= new wxRegionRefData(); 
 101     M_REGIONDATA
->m_region 
= gdk_region_union_with_rect( wxGdkRegion(), &rect 
); 
 104 wxRegion::wxRegion( GdkRegion 
*region 
) 
 106     m_refData 
= new wxRegionRefData(); 
 107     M_REGIONDATA
->m_region 
= gdk_regions_union(wxGdkRegion(), region
); 
 110 wxRegion::wxRegion( size_t n
, const wxPoint 
*points
, int fillStyle 
) 
 112     GdkPoint 
*gdkpoints 
= new GdkPoint
[n
]; 
 113     for ( size_t i 
= 0 ; i 
< n 
; i
++ ) 
 115         gdkpoints
[i
].x 
= points
[i
].x
; 
 116         gdkpoints
[i
].y 
= points
[i
].y
; 
 119     m_refData 
= new wxRegionRefData(); 
 121     GdkRegion
* reg 
= gdk_region_polygon
 
 125                         fillStyle 
== wxWINDING_RULE 
? GDK_WINDING_RULE
 
 129     M_REGIONDATA
->m_region 
= reg
; 
 134 wxRegion::~wxRegion() 
 136     // m_refData unrefed in ~wxObject 
 139 wxObjectRefData 
*wxRegion::CreateRefData() const 
 141     return new wxRegionRefData
; 
 144 wxObjectRefData 
*wxRegion::CloneRefData(const wxObjectRefData 
*data
) const 
 146     return new wxRegionRefData(*(wxRegionRefData 
*)data
); 
 149 // ---------------------------------------------------------------------------- 
 150 // wxRegion comparison 
 151 // ---------------------------------------------------------------------------- 
 153 bool wxRegion::DoIsEqual(const wxRegion
& region
) const 
 155     return gdk_region_equal(M_REGIONDATA
->m_region
, 
 156                             M_REGIONDATA_OF(region
)->m_region
); 
 159 // ---------------------------------------------------------------------------- 
 160 // wxRegion operations 
 161 // ---------------------------------------------------------------------------- 
 163 void wxRegion::Clear() 
 168 bool wxRegion::DoUnionWithRect(const wxRect
& r
) 
 170     // workaround for a strange GTK/X11 bug: taking union with an empty 
 171     // rectangle results in an empty region which is definitely not what we 
 178         InitRect(r
.x
, r
.y
, r
.width
, r
.height
); 
 187         rect
.width 
= r
.width
; 
 188         rect
.height 
= r
.height
; 
 190         gdk_region_union_with_rect( M_REGIONDATA
->m_region
, &rect 
); 
 196 bool wxRegion::DoUnionWithRegion( const wxRegion
& region 
) 
 203         m_refData 
= new wxRegionRefData(); 
 204         M_REGIONDATA
->m_region 
= gdk_region_new(); 
 211     GdkRegion 
*reg 
= gdk_regions_union( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 212     gdk_region_destroy( M_REGIONDATA
->m_region 
); 
 213     M_REGIONDATA
->m_region 
= reg
; 
 218 bool wxRegion::DoIntersect( const wxRegion
& region 
) 
 220     wxCHECK_MSG( region
.Ok(), false, _T("invalid region") ); 
 224         // intersecting with invalid region doesn't make sense 
 230     GdkRegion 
*reg 
= gdk_regions_intersect( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 231     gdk_region_destroy( M_REGIONDATA
->m_region 
); 
 232     M_REGIONDATA
->m_region 
= reg
; 
 237 bool wxRegion::DoSubtract( const wxRegion
& region 
) 
 239     wxCHECK_MSG( region
.Ok(), false, _T("invalid region") ); 
 243         // subtracting from an invalid region doesn't make sense 
 249     GdkRegion 
*reg 
= gdk_regions_subtract( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 250     gdk_region_destroy( M_REGIONDATA
->m_region 
); 
 251     M_REGIONDATA
->m_region 
= reg
; 
 256 bool wxRegion::DoXor( const wxRegion
& region 
) 
 258     wxCHECK_MSG( region
.Ok(), false, _T("invalid region") ); 
 267     GdkRegion 
*reg 
= gdk_regions_xor( M_REGIONDATA
->m_region
, region
.GetRegion() ); 
 268     gdk_region_destroy( M_REGIONDATA
->m_region 
); 
 269     M_REGIONDATA
->m_region 
= reg
; 
 274 bool wxRegion::DoOffset( wxCoord x
, wxCoord y 
) 
 281     gdk_region_offset( M_REGIONDATA
->m_region
, x
, y 
); 
 286 // ---------------------------------------------------------------------------- 
 288 // ---------------------------------------------------------------------------- 
 290 bool wxRegion::DoGetBox( wxCoord 
&x
, wxCoord 
&y
, wxCoord 
&w
, wxCoord 
&h 
) const 
 295         gdk_region_get_clipbox( M_REGIONDATA
->m_region
, &rect 
); 
 314 bool wxRegion::IsEmpty() const 
 319     return gdk_region_empty( M_REGIONDATA
->m_region 
); 
 322 wxRegionContain 
wxRegion::DoContainsPoint( wxCoord x
, wxCoord y 
) const 
 327     if (gdk_region_point_in( M_REGIONDATA
->m_region
, x
, y 
)) 
 333 wxRegionContain 
wxRegion::DoContainsRect(const wxRect
& r
) const 
 341     rect
.width 
= r
.width
; 
 342     rect
.height 
= r
.height
; 
 343     GdkOverlapType res 
= gdk_region_rect_in( M_REGIONDATA
->m_region
, &rect 
); 
 346         case GDK_OVERLAP_RECTANGLE_IN
:   return wxInRegion
; 
 347         case GDK_OVERLAP_RECTANGLE_OUT
:  return wxOutRegion
; 
 348         case GDK_OVERLAP_RECTANGLE_PART
: return wxPartRegion
; 
 353 GdkRegion 
*wxRegion::GetRegion() const 
 356         return (GdkRegion
*) NULL
; 
 358     return M_REGIONDATA
->m_region
; 
 361 // ---------------------------------------------------------------------------- 
 363 // ---------------------------------------------------------------------------- 
 365 // the following structures must match the private structures 
 366 // in X11 region code ( xc/lib/X11/region.h ) 
 368 // this makes the Region type transparent 
 369 // and we have access to the region rectangles 
 371 #include <gdk/gdkprivate.h> 
 374     short x1
, x2
, y1
, y2
; 
 378     long   size 
, numRects
; 
 379     _XBox 
*rects
, extents
; 
 383 class wxRIRefData
: public wxObjectRefData
 
 386     wxRIRefData() { Init(); } 
 387     virtual ~wxRIRefData(); 
 389     void CreateRects( const wxRegion
& r 
); 
 391     void Init() { m_rects 
= NULL
; m_numRects 
= 0; } 
 397 wxRIRefData::~wxRIRefData() 
 402 void wxRIRefData::CreateRects( const wxRegion
& region 
) 
 408     GdkRegion 
*gdkregion 
= region
.GetRegion(); 
 412     Region r 
= ((GdkRegionPrivate 
*)gdkregion
)->xregion
; 
 415         m_numRects 
= r
->numRects
; 
 418             m_rects 
= new wxRect
[m_numRects
]; 
 419             for (size_t i
=0; i 
< m_numRects
; ++i
) 
 421                 _XBox 
&xr 
= r
->rects
[i
]; 
 422                 wxRect 
&wr 
= m_rects
[i
]; 
 425                 wr
.width 
= xr
.x2
-xr
.x1
; 
 426                 wr
.height 
= xr
.y2
-xr
.y1
; 
 432 wxRegionIterator::wxRegionIterator() 
 434     m_refData 
= new wxRIRefData(); 
 438 wxRegionIterator::wxRegionIterator( const wxRegion
& region 
) 
 440     m_refData 
= new wxRIRefData(); 
 444 void wxRegionIterator::Reset( const wxRegion
& region 
) 
 447     ((wxRIRefData
*)m_refData
)->CreateRects(region
); 
 451 bool wxRegionIterator::HaveRects() const 
 453     return m_current 
< ((wxRIRefData
*)m_refData
)->m_numRects
; 
 456 wxRegionIterator
& wxRegionIterator::operator ++ () 
 464 wxRegionIterator 
wxRegionIterator::operator ++ (int) 
 466     wxRegionIterator tmp 
= *this; 
 473 wxCoord 
wxRegionIterator::GetX() const 
 475     wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") ); 
 477     return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].x
; 
 480 wxCoord 
wxRegionIterator::GetY() const 
 482     wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") ); 
 484     return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].y
; 
 487 wxCoord 
wxRegionIterator::GetW() const 
 489     wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") ); 
 491     return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].width
; 
 494 wxCoord 
wxRegionIterator::GetH() const 
 496     wxCHECK_MSG( HaveRects(), 0, _T("invalid wxRegionIterator") ); 
 498     return ((wxRIRefData
*)m_refData
)->m_rects
[m_current
].height
; 
 501 wxRect 
wxRegionIterator::GetRect() const 
 505         r 
= ((wxRIRefData
*)m_refData
)->m_rects
[m_current
];