1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:   Region class 
   4 // Author:    David Webster 
   8 // Copyright: (c) Davdi Webster 
   9 // Licence:   wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  15 #include "wx/os2/region.h" 
  16 #include "wx/gdicmn.h" 
  18 #include "wx/window.h" 
  19 #include "wx/os2/private.h" 
  21         IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
) 
  22         IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
, wxObject
) 
  24 //----------------------------------------------------------------------------- 
  25 // wxRegionRefData implementation 
  26 //----------------------------------------------------------------------------- 
  28 class WXDLLEXPORT wxRegionRefData 
: public wxGDIRefData 
{ 
  35     wxRegionRefData(const wxRegionRefData
& rData
) 
  40         if (::GpiQueryRegionRects( rData
.m_hPS      
// Pres space 
  41                                   ,rData
.m_hRegion  
// Handle of region to query 
  42                                   ,NULL             
// Return all RECTs 
  43                                   ,&vRgnData        
// Will contain number or RECTs in region 
  44                                   ,NULL             
// NULL to return number of RECTs 
  47             pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
  48             vRgnData
.crc 
= vRgnData
.crcReturned
; 
  49             vRgnData
.ircStart 
= 1; 
  50             if (::GpiQueryRegionRects( rData
.m_hPS     
// Pres space of source 
  51                                       ,rData
.m_hRegion 
// Handle of source region 
  52                                       ,NULL            
// Return all RECTs 
  53                                       ,&vRgnData       
// Operations set to return rects 
  54                                       ,pRect           
// Will contain the actual RECTS 
  57                 m_hRegion 
= ::GpiCreateRegion( rData
.m_hPS
 
  69         ::GpiDestroyRegion(m_hPS
, m_hRegion
); 
  76 #define M_REGION (((wxRegionRefData*)m_refData)->m_hRegion) 
  78 //----------------------------------------------------------------------------- 
  80 //----------------------------------------------------------------------------- 
  83  * Create an empty region. 
  87     m_refData 
= new wxRegionRefData
; 
  88 } // end of wxRegion::wxRegion 
  94     m_refData 
= new wxRegionRefData
; 
  95     M_REGION 
= (HRGN
) hRegion
; 
  96 } // end of wxRegion::wxRegion 
 106     SIZEL                           vSize 
= {0, 0}; 
 107     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 108     HDC                             hDC 
= ::DevOpenDC( vHabmain
 
 118     vRect
.xRight  
= x 
+ vWidth
; 
 120     vRect
.yTop    
= y 
+ vHeight
; 
 122     m_refData     
= new wxRegionRefData
; 
 125     // Need a PS to create a Region 
 127     ((wxRegionRefData
*)m_refData
)->m_hPS 
= ::GpiCreatePS( vHabmain
 
 130                                                          ,PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
 
 132     M_REGION      
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 136 } // end of wxRegion::wxRegion 
 139   const wxPoint
&                    rTopLeft
 
 140 , const wxPoint
&                    rBottomRight
 
 144     SIZEL                           vSize 
= {0, 0}; 
 145     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 146     HDC                             hDC 
= ::DevOpenDC( vHabmain
 
 154     vRect
.xLeft   
= rTopLeft
.x
; 
 155     vRect
.xRight  
= rBottomRight
.x
; 
 156     vRect
.yBottom 
= rBottomRight
.y
; 
 157     vRect
.yTop    
= rTopLeft
.y
; 
 159     m_refData     
= new wxRegionRefData
; 
 162     // Need a PS to create a Region 
 164     ((wxRegionRefData
*)m_refData
)->m_hPS 
= ::GpiCreatePS( vHabmain
 
 167                                                          ,PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
 
 169     M_REGION      
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 173 } // end of wxRegion::wxRegion 
 180     SIZEL                           vSize 
= {0, 0}; 
 181     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 182     HDC                             hDC 
= ::DevOpenDC( vHabmain
 
 191     vRect
.xLeft   
= rRect
.x
; 
 192     vRect
.xRight  
= rRect
.x 
+ rRect
.width
; 
 193     vRect
.yBottom 
= rRect
.y
; 
 194     vRect
.yTop    
= rRect
.y 
+ rRect
.height
; 
 196     m_refData     
= new wxRegionRefData
; 
 199     // Need a PS to create a Region 
 201     ((wxRegionRefData
*)m_refData
)->m_hPS 
= ::GpiCreatePS( vHabmain
 
 204                                                          ,PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
 
 206     M_REGION      
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 210 } // end of wxRegion::wxRegion 
 213 // Destroy the region. 
 215 wxRegion::~wxRegion() 
 217 } // end of wxRegion::~wxRegion 
 219 //----------------------------------------------------------------------------- 
 221 //----------------------------------------------------------------------------- 
 224 // Clear current region 
 226 void wxRegion::Clear() 
 229 } // end of wxRegion::Clear 
 232 // Combine rectangle (x, y, w, h) with this. 
 234 bool wxRegion::Combine( 
 243     // Don't change shared data 
 247         m_refData 
= new wxRegionRefData(); 
 249     else if (m_refData
->GetRefCount() > 1) 
 251         wxRegionRefData
*            pRef 
= (wxRegionRefData
*)m_refData
; 
 254         m_refData 
= new wxRegionRefData(*pRef
); 
 258     // If ref count is 1, that means it's 'ours' anyway so no action. 
 263     vRect
.xRight  
= x 
+ vWidth
; 
 265     vRect
.yTop    
= y 
+ vHeight
; 
 267     HRGN                            hRgn 
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 296     bool                            bSuccess 
= ::GpiCombineRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 302     ::GpiDestroyRegion ( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 307 } // end of wxRegion::Combine 
 310 // Union region with this. 
 312 bool wxRegion::Combine( 
 313   const wxRegion
&                   rRegion
 
 321     // Don't change shared data 
 325         m_refData 
= new wxRegionRefData(); 
 327     else  if (m_refData
->GetRefCount() > 1) 
 329         wxRegionRefData
*            pRef 
= (wxRegionRefData
*)m_refData
; 
 332         m_refData 
= new wxRegionRefData(*pRef
); 
 360     return (::GpiCombineRegion( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
 
 363                                ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion
 
 366 } // end of wxRegion::Combine 
 368 bool wxRegion::Combine( 
 373     return Combine( rRect
.GetLeft() 
 379 } // end of wxRegion::Combine 
 381 //----------------------------------------------------------------------------- 
 382 //# Information on region 
 383 //----------------------------------------------------------------------------- 
 386 // Outer bounds of region 
 388 void wxRegion::GetBox( 
 399         ::GpiQueryRegionBox( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 405         vWidth  
= vRect
.xRight 
- vRect
.xLeft
; 
 406         vHeight 
= vRect
.yTop 
- vRect
.yBottom
; 
 410         x 
= y 
= vWidth 
= vHeight 
= 0L; 
 412 } // end of wxRegion::GetBox 
 414 wxRect 
wxRegion::GetBox() const 
 418     return wxRect(x
, y
, w
, h
); 
 424 bool wxRegion::Empty() const 
 439     return ((vWidth 
== 0) && (vHeight 
== 0)); 
 440 } // end of wxRegion::Empty 
 442 //----------------------------------------------------------------------------- 
 444 //----------------------------------------------------------------------------- 
 447 // Does the region contain the point (x,y)? 
 448 wxRegionContain 
wxRegion::Contains( 
 462     LONG                            lInside 
= ::GpiPtInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 466     if (lInside 
== PRGN_INSIDE
) 
 469 } // end of wxRegion::Contains 
 472 // Does the region contain the point pt? 
 474 wxRegionContain 
wxRegion::Contains( 
 475   const wxPoint
&                    rPoint
 
 478     POINTL                          vPoint 
= { rPoint
.x
, rPoint
.y 
}; 
 483     LONG                            lInside 
= ::GpiPtInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 487     if (lInside 
== PRGN_INSIDE
) 
 491 } // end of wxRegion::Contains 
 494 // Does the region contain the rectangle (x, y, w, h)? 
 496 wxRegionContain 
wxRegion::Contains( 
 510     vRect
.xRight  
= x 
+ vWidth
; 
 511     vRect
.yBottom 
= y 
+ vHeight
; 
 513     if (PRGN_INSIDE 
== ::GpiRectInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 520 } // end of wxRegion::Contains 
 523 // Does the region contain the rectangle rect 
 525 wxRegionContain 
wxRegion::Contains( 
 539     vWidth  
= rRect
.GetWidth(); 
 540     vHeight 
= rRect
.GetHeight(); 
 546 } // end of wxRegion::Contains 
 549 // Get internal region handle 
 551 WXHRGN 
wxRegion::GetHRGN() const 
 555     return (WXHRGN
) M_REGION
; 
 559 // Set a new PS, this means we have to recreate the old region in the new 
 562 void wxRegion::SetPS( 
 569     if (::GpiQueryRegionRects( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 570                               ,((wxRegionRefData
*)m_refData
)->m_hRegion
 
 576         pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
 577         vRgnData
.crc 
= vRgnData
.crcReturned
; 
 578         vRgnData
.ircStart 
= 1; 
 579         if (::GpiQueryRegionRects( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 580                                   ,((wxRegionRefData
*)m_refData
)->m_hRegion
 
 587             // First destroy the region out of the old PS 
 588             // and then create it in the new and set the new to current 
 590             ::GpiDestroyRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 593             ((wxRegionRefData
*)m_refData
)->m_hRegion 
= ::GpiCreateRegion( hPS
 
 594                                                                          ,vRgnData
.crcReturned
 
 597             ((wxRegionRefData
*)m_refData
)->m_hPS 
= hPS
; 
 601 } // end of wxRegion::SetPS 
 603 /////////////////////////////////////////////////////////////////////////////// 
 605 //                             wxRegionIterator                              // 
 607 /////////////////////////////////////////////////////////////////////////////// 
 610 // Initialize empty iterator 
 612 wxRegionIterator::wxRegionIterator() 
 617 } // end of wxRegionIterator::wxRegionIterator 
 619 wxRegionIterator::~wxRegionIterator() 
 623 } // end of wxRegionIterator::~wxRegionIterator 
 626 // Initialize iterator for region 
 628 wxRegionIterator::wxRegionIterator( 
 629   const wxRegion
&                   rRegion
 
 634 } // end of wxRegionIterator::wxRegionIterator 
 637 // Reset iterator for a new /e region. 
 639 void wxRegionIterator::Reset( 
 640   const wxRegion
&                   rRegion
 
 651     if (m_vRegion
.Empty()) 
 658         if (::GpiQueryRegionRects( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS     
// Pres space 
 659                                   ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion 
// Handle of region to query 
 660                                   ,NULL                                             
// Return all RECTs 
 661                                   ,&vRgnData                                        
// Will contain number or RECTs in region 
 662                                   ,NULL                                             
// NULL to return number of RECTs 
 665             pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
 666             m_pRects 
= new wxRect
[vRgnData
.crcReturned
]; 
 667             vRgnData
.crc 
= vRgnData
.crcReturned
; 
 668             m_lNumRects 
= vRgnData
.crcReturned
; 
 669             vRgnData
.ircStart 
= 1; 
 670             if (::GpiQueryRegionRects( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS     
// Pres space of source 
 671                                       ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion 
// Handle of source region 
 672                                       ,NULL                                             
// Return all RECTs 
 673                                       ,&vRgnData                                        
// Operations set to return rects 
 674                                       ,pRect                                            
// Will contain the actual RECTS 
 677                 M_REGION 
= ::GpiCreateRegion( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
 
 678                                              ,vRgnData
.crcReturned
 
 681                 for( LONG i 
= 0; i 
< m_lNumRects
; i
++) 
 683                     m_pRects
[i
].x      
= pRect
[i
].xLeft
; 
 684                     m_pRects
[i
].width  
= pRect
[i
].xRight 
- pRect
[i
].xLeft
; 
 685                     m_pRects
[i
].y      
= pRect
[i
].yBottom
; 
 686                     m_pRects
[i
].height 
= pRect
[i
].yTop 
- pRect
[i
].yBottom
; 
 688                 ((wxRegionRefData
*)m_refData
)->m_hPS 
= ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
; 
 692 } // end of wxRegionIterator::Reset 
 695 // Increment iterator. The rectangle returned is the one after the 
 698 void wxRegionIterator::operator++ () 
 700     if (m_lCurrent 
< m_lNumRects
) 
 702 } // end of wxRegionIterator::operator ++ 
 705 // Increment iterator. The rectangle returned is the one before the 
 708 void wxRegionIterator::operator++ (int) 
 710     if (m_lCurrent 
< m_lNumRects
) 
 712 } // end of wxRegionIterator::operator++ 
 714 wxCoord 
wxRegionIterator::GetX() const 
 716     if (m_lCurrent 
< m_lNumRects
) 
 717         return m_pRects
[m_lCurrent
].x
; 
 719 } // end of wxRegionIterator::GetX 
 721 wxCoord 
wxRegionIterator::GetY() const 
 723     if (m_lCurrent 
< m_lNumRects
) 
 724         return m_pRects
[m_lCurrent
].y
; 
 726 } // end of wxRegionIterator::GetY 
 728 wxCoord 
wxRegionIterator::GetW() const 
 730     if (m_lCurrent 
< m_lNumRects
) 
 731         return m_pRects
[m_lCurrent
].width 
; 
 733 } // end of wxRegionIterator::GetW 
 735 wxCoord 
wxRegionIterator::GetH() const 
 737     if (m_lCurrent 
< m_lNumRects
) 
 738         return m_pRects
[m_lCurrent
].height
; 
 740 } // end of wxRegionIterator::GetH