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" 
  16 #include "wx/os2/region.h" 
  17 #include "wx/gdicmn.h" 
  19 #include "wx/window.h" 
  20 #include "wx/os2/private.h" 
  22         IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
) 
  23         IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
, wxObject
) 
  25 //----------------------------------------------------------------------------- 
  26 // wxRegionRefData implementation 
  27 //----------------------------------------------------------------------------- 
  29 class WXDLLEXPORT wxRegionRefData 
: public wxGDIRefData 
{ 
  36     wxRegionRefData(const wxRegionRefData
& rData
) 
  41         if (::GpiQueryRegionRects( rData
.m_hPS      
// Pres space 
  42                                   ,rData
.m_hRegion  
// Handle of region to query 
  43                                   ,NULL             
// Return all RECTs 
  44                                   ,&vRgnData        
// Will contain number or RECTs in region 
  45                                   ,NULL             
// NULL to return number of RECTs 
  48             pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
  49             vRgnData
.crc 
= vRgnData
.crcReturned
; 
  50             vRgnData
.ircStart 
= 1; 
  51             if (::GpiQueryRegionRects( rData
.m_hPS     
// Pres space of source 
  52                                       ,rData
.m_hRegion 
// Handle of source region 
  53                                       ,NULL            
// Return all RECTs 
  54                                       ,&vRgnData       
// Operations set to return rects 
  55                                       ,pRect           
// Will contain the actual RECTS 
  58                 m_hRegion 
= ::GpiCreateRegion( rData
.m_hPS
 
  70         ::GpiDestroyRegion(m_hPS
, m_hRegion
); 
  77 #define M_REGION (((wxRegionRefData*)m_refData)->m_hRegion) 
  79 //----------------------------------------------------------------------------- 
  81 //----------------------------------------------------------------------------- 
  84  * Create an empty region. 
  88     m_refData 
= new wxRegionRefData
; 
  89 } // end of wxRegion::wxRegion 
  95     m_refData 
= new wxRegionRefData
; 
  96     M_REGION 
= (HRGN
) hRegion
; 
  97 } // end of wxRegion::wxRegion 
 107     SIZEL                           vSize 
= {0, 0}; 
 108     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 109     HDC                             hDC 
= ::DevOpenDC( vHabmain
 
 119     vRect
.xRight  
= x 
+ vWidth
; 
 121     vRect
.yTop    
= y 
+ vHeight
; 
 123     m_refData     
= new wxRegionRefData
; 
 126     // Need a PS to create a Region 
 128     ((wxRegionRefData
*)m_refData
)->m_hPS 
= ::GpiCreatePS( vHabmain
 
 131                                                          ,PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
 
 133     M_REGION      
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 137 } // end of wxRegion::wxRegion 
 140   const wxPoint
&                    rTopLeft
 
 141 , const wxPoint
&                    rBottomRight
 
 145     SIZEL                           vSize 
= {0, 0}; 
 146     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 147     HDC                             hDC 
= ::DevOpenDC( vHabmain
 
 155     vRect
.xLeft   
= rTopLeft
.x
; 
 156     vRect
.xRight  
= rBottomRight
.x
; 
 157     vRect
.yBottom 
= rBottomRight
.y
; 
 158     vRect
.yTop    
= rTopLeft
.y
; 
 160     m_refData     
= new wxRegionRefData
; 
 163     // Need a PS to create a Region 
 165     ((wxRegionRefData
*)m_refData
)->m_hPS 
= ::GpiCreatePS( vHabmain
 
 168                                                          ,PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
 
 170     M_REGION      
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 174 } // end of wxRegion::wxRegion 
 181     SIZEL                           vSize 
= {0, 0}; 
 182     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 183     HDC                             hDC 
= ::DevOpenDC( vHabmain
 
 192     vRect
.xLeft   
= rRect
.x
; 
 193     vRect
.xRight  
= rRect
.x 
+ rRect
.width
; 
 194     vRect
.yBottom 
= rRect
.y
; 
 195     vRect
.yTop    
= rRect
.y 
+ rRect
.height
; 
 197     m_refData     
= new wxRegionRefData
; 
 200     // Need a PS to create a Region 
 202     ((wxRegionRefData
*)m_refData
)->m_hPS 
= ::GpiCreatePS( vHabmain
 
 205                                                          ,PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
 
 207     M_REGION      
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 211 } // end of wxRegion::wxRegion 
 214 // Destroy the region. 
 216 wxRegion::~wxRegion() 
 218 } // end of wxRegion::~wxRegion 
 220 //----------------------------------------------------------------------------- 
 222 //----------------------------------------------------------------------------- 
 225 // Clear current region 
 227 void wxRegion::Clear() 
 230 } // end of wxRegion::Clear 
 233 // Combine rectangle (x, y, w, h) with this. 
 235 bool wxRegion::Combine( 
 244     // Don't change shared data 
 248         m_refData 
= new wxRegionRefData(); 
 250     else if (m_refData
->GetRefCount() > 1) 
 252         wxRegionRefData
*            pRef 
= (wxRegionRefData
*)m_refData
; 
 255         m_refData 
= new wxRegionRefData(*pRef
); 
 259     // If ref count is 1, that means it's 'ours' anyway so no action. 
 264     vRect
.xRight  
= x 
+ vWidth
; 
 266     vRect
.yTop    
= y 
+ vHeight
; 
 268     HRGN                            hRgn 
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 297     bool                            bSuccess 
= ::GpiCombineRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 303     ::GpiDestroyRegion ( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 308 } // end of wxRegion::Combine 
 311 // Union region with this. 
 313 bool wxRegion::Combine( 
 314   const wxRegion
&                   rRegion
 
 322     // Don't change shared data 
 326         m_refData 
= new wxRegionRefData(); 
 328     else  if (m_refData
->GetRefCount() > 1) 
 330         wxRegionRefData
*            pRef 
= (wxRegionRefData
*)m_refData
; 
 333         m_refData 
= new wxRegionRefData(*pRef
); 
 361     return (::GpiCombineRegion( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
 
 364                                ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion
 
 367 } // end of wxRegion::Combine 
 369 bool wxRegion::Combine( 
 374     return Combine( rRect
.GetLeft() 
 380 } // end of wxRegion::Combine 
 382 //----------------------------------------------------------------------------- 
 383 //# Information on region 
 384 //----------------------------------------------------------------------------- 
 387 // Outer bounds of region 
 389 void wxRegion::GetBox( 
 400         ::GpiQueryRegionBox( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 406         vWidth  
= vRect
.xRight 
- vRect
.xLeft
; 
 407         vHeight 
= vRect
.yTop 
- vRect
.yBottom
; 
 411         x 
= y 
= vWidth 
= vHeight 
= 0L; 
 413 } // end of wxRegion::GetBox 
 415 wxRect 
wxRegion::GetBox() const 
 419     return wxRect(x
, y
, w
, h
); 
 425 bool wxRegion::Empty() const 
 440     return ((vWidth 
== 0) && (vHeight 
== 0)); 
 441 } // end of wxRegion::Empty 
 443 //----------------------------------------------------------------------------- 
 445 //----------------------------------------------------------------------------- 
 448 // Does the region contain the point (x,y)? 
 449 wxRegionContain 
wxRegion::Contains( 
 463     LONG                            lInside 
= ::GpiPtInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 467     if (lInside 
== PRGN_INSIDE
) 
 470 } // end of wxRegion::Contains 
 473 // Does the region contain the point pt? 
 475 wxRegionContain 
wxRegion::Contains( 
 476   const wxPoint
&                    rPoint
 
 479     POINTL                          vPoint 
= { rPoint
.x
, rPoint
.y 
}; 
 484     LONG                            lInside 
= ::GpiPtInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 488     if (lInside 
== PRGN_INSIDE
) 
 492 } // end of wxRegion::Contains 
 495 // Does the region contain the rectangle (x, y, w, h)? 
 497 wxRegionContain 
wxRegion::Contains( 
 511     vRect
.xRight  
= x 
+ vWidth
; 
 512     vRect
.yBottom 
= y 
+ vHeight
; 
 514     if (PRGN_INSIDE 
== ::GpiRectInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 521 } // end of wxRegion::Contains 
 524 // Does the region contain the rectangle rect 
 526 wxRegionContain 
wxRegion::Contains( 
 540     vWidth  
= rRect
.GetWidth(); 
 541     vHeight 
= rRect
.GetHeight(); 
 547 } // end of wxRegion::Contains 
 550 // Get internal region handle 
 552 WXHRGN 
wxRegion::GetHRGN() const 
 556     return (WXHRGN
) M_REGION
; 
 560 // Set a new PS, this means we have to recreate the old region in the new 
 563 void wxRegion::SetPS( 
 570     if (::GpiQueryRegionRects( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 571                               ,((wxRegionRefData
*)m_refData
)->m_hRegion
 
 577         pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
 578         vRgnData
.crc 
= vRgnData
.crcReturned
; 
 579         vRgnData
.ircStart 
= 1; 
 580         if (::GpiQueryRegionRects( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 581                                   ,((wxRegionRefData
*)m_refData
)->m_hRegion
 
 588             // First destroy the region out of the old PS 
 589             // and then create it in the new and set the new to current 
 591             ::GpiDestroyRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 594             ((wxRegionRefData
*)m_refData
)->m_hRegion 
= ::GpiCreateRegion( hPS
 
 595                                                                          ,vRgnData
.crcReturned
 
 598             ((wxRegionRefData
*)m_refData
)->m_hPS 
= hPS
; 
 602 } // end of wxRegion::SetPS 
 604 /////////////////////////////////////////////////////////////////////////////// 
 606 //                             wxRegionIterator                              // 
 608 /////////////////////////////////////////////////////////////////////////////// 
 611 // Initialize empty iterator 
 613 wxRegionIterator::wxRegionIterator() 
 618 } // end of wxRegionIterator::wxRegionIterator 
 620 wxRegionIterator::~wxRegionIterator() 
 624 } // end of wxRegionIterator::~wxRegionIterator 
 627 // Initialize iterator for region 
 629 wxRegionIterator::wxRegionIterator( 
 630   const wxRegion
&                   rRegion
 
 635 } // end of wxRegionIterator::wxRegionIterator 
 638 // Reset iterator for a new /e region. 
 640 void wxRegionIterator::Reset( 
 641   const wxRegion
&                   rRegion
 
 652     if (m_vRegion
.Empty()) 
 659         if (::GpiQueryRegionRects( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS     
// Pres space 
 660                                   ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion 
// Handle of region to query 
 661                                   ,NULL                                             
// Return all RECTs 
 662                                   ,&vRgnData                                        
// Will contain number or RECTs in region 
 663                                   ,NULL                                             
// NULL to return number of RECTs 
 666             pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
 667             m_pRects 
= new wxRect
[vRgnData
.crcReturned
]; 
 668             vRgnData
.crc 
= vRgnData
.crcReturned
; 
 669             m_lNumRects 
= vRgnData
.crcReturned
; 
 670             vRgnData
.ircStart 
= 1; 
 671             if (::GpiQueryRegionRects( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS     
// Pres space of source 
 672                                       ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion 
// Handle of source region 
 673                                       ,NULL                                             
// Return all RECTs 
 674                                       ,&vRgnData                                        
// Operations set to return rects 
 675                                       ,pRect                                            
// Will contain the actual RECTS 
 678                 M_REGION 
= ::GpiCreateRegion( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
 
 679                                              ,vRgnData
.crcReturned
 
 682                 for( LONG i 
= 0; i 
< m_lNumRects
; i
++) 
 684                     m_pRects
[i
].x      
= pRect
[i
].xLeft
; 
 685                     m_pRects
[i
].width  
= pRect
[i
].xRight 
- pRect
[i
].xLeft
; 
 686                     m_pRects
[i
].y      
= pRect
[i
].yBottom
; 
 687                     m_pRects
[i
].height 
= pRect
[i
].yTop 
- pRect
[i
].yBottom
; 
 689                 ((wxRegionRefData
*)m_refData
)->m_hPS 
= ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
; 
 693 } // end of wxRegionIterator::Reset 
 696 // Increment iterator. The rectangle returned is the one after the 
 699 void wxRegionIterator::operator++ () 
 701     if (m_lCurrent 
< m_lNumRects
) 
 703 } // end of wxRegionIterator::operator ++ 
 706 // Increment iterator. The rectangle returned is the one before the 
 709 void wxRegionIterator::operator++ (int) 
 711     if (m_lCurrent 
< m_lNumRects
) 
 713 } // end of wxRegionIterator::operator++ 
 715 wxCoord 
wxRegionIterator::GetX() const 
 717     if (m_lCurrent 
< m_lNumRects
) 
 718         return m_pRects
[m_lCurrent
].x
; 
 720 } // end of wxRegionIterator::GetX 
 722 wxCoord 
wxRegionIterator::GetY() const 
 724     if (m_lCurrent 
< m_lNumRects
) 
 725         return m_pRects
[m_lCurrent
].y
; 
 727 } // end of wxRegionIterator::GetY 
 729 wxCoord 
wxRegionIterator::GetW() const 
 731     if (m_lCurrent 
< m_lNumRects
) 
 732         return m_pRects
[m_lCurrent
].width 
; 
 734 } // end of wxRegionIterator::GetW 
 736 wxCoord 
wxRegionIterator::GetH() const 
 738     if (m_lCurrent 
< m_lNumRects
) 
 739         return m_pRects
[m_lCurrent
].height
; 
 741 } // end of wxRegionIterator::GetH