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 
{ 
  37     wxRegionRefData(const wxRegionRefData
& rData
) 
  42         vRgnData
.ulDirection 
= RECTDIR_LFRT_TOPBOT
; 
  43         if (::GpiQueryRegionRects( rData
.m_hPS      
// Pres space 
  44                                   ,rData
.m_hRegion  
// Handle of region to query 
  45                                   ,NULL             
// Return all RECTs 
  46                                   ,&vRgnData        
// Will contain number or RECTs in region 
  47                                   ,NULL             
// NULL to return number of RECTs 
  50             pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
  51             vRgnData
.crc 
= vRgnData
.crcReturned
; 
  52             vRgnData
.ircStart 
= 1; 
  53             if (::GpiQueryRegionRects( rData
.m_hPS     
// Pres space of source 
  54                                       ,rData
.m_hRegion 
// Handle of source region 
  55                                       ,NULL            
// Return all RECTs 
  56                                       ,&vRgnData       
// Operations set to return rects 
  57                                       ,pRect           
// Will contain the actual RECTS 
  60                 m_hRegion 
= ::GpiCreateRegion( rData
.m_hPS
 
  72         ::GpiDestroyRegion(m_hPS
, m_hRegion
); 
  79 #define M_REGION (((wxRegionRefData*)m_refData)->m_hRegion) 
  80 #define M_REGION_OF(rgn) (((wxRegionRefData*)(rgn.m_refData))->m_hRegion) 
  82 //----------------------------------------------------------------------------- 
  84 //----------------------------------------------------------------------------- 
  87  * Create an empty region. 
  91     m_refData 
= new wxRegionRefData
; 
  92 } // end of wxRegion::wxRegion 
  99     m_refData 
= new wxRegionRefData
; 
 100     M_REGION 
= (HRGN
) hRegion
; 
 101     (((wxRegionRefData
*)m_refData
)->m_hPS
) = hPS
; 
 102 } // end of wxRegion::wxRegion 
 112     SIZEL                           vSize 
= {0, 0}; 
 113     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 114     HDC                             hDC 
= ::DevOpenDC( vHabmain
 
 124     vRect
.xRight  
= x 
+ vWidth
; 
 126     vRect
.yTop    
= y 
+ vHeight
; 
 128     m_refData     
= new wxRegionRefData
; 
 131     // Need a PS to create a Region 
 133     ((wxRegionRefData
*)m_refData
)->m_hPS 
= ::GpiCreatePS( vHabmain
 
 136                                                          ,PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
 
 138     M_REGION      
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 142 } // end of wxRegion::wxRegion 
 145   const wxPoint
&                    rTopLeft
 
 146 , const wxPoint
&                    rBottomRight
 
 150     SIZEL                           vSize 
= {0, 0}; 
 151     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 152     HDC                             hDC 
= ::DevOpenDC( vHabmain
 
 160     vRect
.xLeft   
= rTopLeft
.x
; 
 161     vRect
.xRight  
= rBottomRight
.x
; 
 162     vRect
.yBottom 
= rBottomRight
.y
; 
 163     vRect
.yTop    
= rTopLeft
.y
; 
 165     m_refData     
= new wxRegionRefData
; 
 168     // Need a PS to create a Region 
 170     ((wxRegionRefData
*)m_refData
)->m_hPS 
= ::GpiCreatePS( vHabmain
 
 173                                                          ,PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
 
 175     M_REGION      
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 179 } // end of wxRegion::wxRegion 
 186     SIZEL                           vSize 
= {0, 0}; 
 187     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 188     HDC                             hDC 
= ::DevOpenDC( vHabmain
 
 197     vRect
.xLeft   
= rRect
.x
; 
 198     vRect
.xRight  
= rRect
.x 
+ rRect
.width
; 
 199     vRect
.yBottom 
= rRect
.y
; 
 200     vRect
.yTop    
= rRect
.y 
+ rRect
.height
; 
 202     m_refData     
= new wxRegionRefData
; 
 205     // Need a PS to create a Region 
 207     ((wxRegionRefData
*)m_refData
)->m_hPS 
= ::GpiCreatePS( vHabmain
 
 210                                                          ,PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
 
 212     M_REGION      
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 216 } // end of wxRegion::wxRegion 
 219 // Destroy the region. 
 221 wxRegion::~wxRegion() 
 223 } // end of wxRegion::~wxRegion 
 225 wxObjectRefData 
*wxRegion::CreateData() const 
 227     return new wxRegionRefData
; 
 230 wxObjectRefData 
*wxRegion::CloneData(const wxObjectRefData 
*data
) const 
 232     return new wxRegionRefData(*(wxRegionRefData 
*)data
); 
 235 //----------------------------------------------------------------------------- 
 237 //----------------------------------------------------------------------------- 
 239 bool wxRegion::Offset( 
 253     if ( ::OffsetRgn(GetHrgn(), x
, y
) == ERROR 
) 
 255         wxLogLastError(_T("OffsetRgn")); 
 264 // Clear current region 
 266 void wxRegion::Clear() 
 269 } // end of wxRegion::Clear 
 272 // Combine rectangle (x, y, w, h) with this. 
 274 bool wxRegion::Combine( 
 282     return Combine(wxRegion(x
, y
, vWidth
, vHeight
), eOp
); 
 283 } // end of wxRegion::Combine 
 286 // Union region with this. 
 288 bool wxRegion::Combine( 
 289   const wxRegion
&                   rRegion
 
 294     // We can't use the API functions if we don't have a valid region handle 
 298         // combining with an empty/invalid region works differently depending 
 309                 wxFAIL_MSG( _T("unknown region operation") ); 
 314                 // leave empty/invalid 
 318     else // we have a valid region 
 346         return (::GpiCombineRegion( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
 
 349                                    ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion
 
 354 } // end of wxRegion::Combine 
 356 bool wxRegion::Combine( 
 361     return Combine( rRect
.GetLeft() 
 367 } // end of wxRegion::Combine 
 369 //----------------------------------------------------------------------------- 
 370 //# Information on region 
 371 //----------------------------------------------------------------------------- 
 374 // Outer bounds of region 
 376 void wxRegion::GetBox( 
 388         rc 
= ::GpiQueryRegionBox( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 394         vWidth  
= vRect
.xRight 
- vRect
.xLeft
; 
 395         vHeight 
= vRect
.yTop 
- vRect
.yBottom
; 
 399         x 
= y 
= vWidth 
= vHeight 
= 0L; 
 401 } // end of wxRegion::GetBox 
 403 wxRect 
wxRegion::GetBox() const 
 407     return wxRect(x
, y
, w
, h
); 
 413 bool wxRegion::Empty() const 
 428     return ((vWidth 
== 0) && (vHeight 
== 0)); 
 429 } // end of wxRegion::Empty 
 431 //----------------------------------------------------------------------------- 
 433 //----------------------------------------------------------------------------- 
 436 // Does the region contain the point (x,y)? 
 437 wxRegionContain 
wxRegion::Contains( 
 450     LONG                            lInside 
= ::GpiPtInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 454     if (lInside 
== PRGN_INSIDE
) 
 457 } // end of wxRegion::Contains 
 460 // Does the region contain the point pt? 
 462 wxRegionContain 
wxRegion::Contains( 
 463   const wxPoint
&                    rPoint
 
 466     POINTL                          vPoint 
= { rPoint
.x
, rPoint
.y 
}; 
 471     LONG                            lInside 
= ::GpiPtInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 475     if (lInside 
== PRGN_INSIDE
) 
 479 } // end of wxRegion::Contains 
 482 // Does the region contain the rectangle (x, y, w, h)? 
 484 wxRegionContain 
wxRegion::Contains( 
 498     vRect
.xRight  
= x 
+ vWidth
; 
 499     vRect
.yBottom 
= y 
+ vHeight
; 
 501     if (PRGN_INSIDE 
== ::GpiRectInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 508 } // end of wxRegion::Contains 
 511 // Does the region contain the rectangle rect 
 513 wxRegionContain 
wxRegion::Contains( 
 527     vWidth  
= rRect
.GetWidth(); 
 528     vHeight 
= rRect
.GetHeight(); 
 534 } // end of wxRegion::Contains 
 537 // Get internal region handle 
 539 WXHRGN 
wxRegion::GetHRGN() const 
 543     return (WXHRGN
) M_REGION
; 
 547 // Set a new PS, this means we have to recreate the old region in the new 
 550 void wxRegion::SetPS( 
 557     vRgnData
.ulDirection 
= RECTDIR_LFRT_TOPBOT
; 
 558     if (::GpiQueryRegionRects( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 559                               ,((wxRegionRefData
*)m_refData
)->m_hRegion
 
 565         pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
 566         vRgnData
.crc 
= vRgnData
.crcReturned
; 
 567         vRgnData
.ircStart 
= 1; 
 568         if (::GpiQueryRegionRects( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 569                                   ,((wxRegionRefData
*)m_refData
)->m_hRegion
 
 576             // First destroy the region out of the old PS 
 577             // and then create it in the new and set the new to current 
 579             ::GpiDestroyRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 582             ((wxRegionRefData
*)m_refData
)->m_hRegion 
= ::GpiCreateRegion( hPS
 
 583                                                                          ,vRgnData
.crcReturned
 
 586             ((wxRegionRefData
*)m_refData
)->m_hPS 
= hPS
; 
 590 } // end of wxRegion::SetPS 
 592 /////////////////////////////////////////////////////////////////////////////// 
 594 //                             wxRegionIterator                              // 
 596 /////////////////////////////////////////////////////////////////////////////// 
 599 // Initialize empty iterator 
 601 wxRegionIterator::wxRegionIterator() 
 606 } // end of wxRegionIterator::wxRegionIterator 
 608 wxRegionIterator::~wxRegionIterator() 
 612 } // end of wxRegionIterator::~wxRegionIterator 
 615 // Initialize iterator for region 
 617 wxRegionIterator::wxRegionIterator( 
 618   const wxRegion
&                   rRegion
 
 623 } // end of wxRegionIterator::wxRegionIterator 
 626 // Reset iterator for a new /e region. 
 628 void wxRegionIterator::Reset( 
 629   const wxRegion
&                   rRegion
 
 641     if (m_vRegion
.Empty()) 
 648         vRgnData
.ulDirection 
= RECTDIR_LFRT_TOPBOT
; 
 649         if (::GpiQueryRegionRects( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS     
// Pres space 
 650                                   ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion 
// Handle of region to query 
 651                                   ,NULL                                             
// Return all RECTs 
 652                                   ,&vRgnData                                        
// Will contain number or RECTs in region 
 653                                   ,NULL                                             
// NULL to return number of RECTs 
 656             pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
 657             m_pRects 
= new wxRect
[vRgnData
.crcReturned
]; 
 658             vRgnData
.crc 
= vRgnData
.crcReturned
; 
 659             m_lNumRects 
= vRgnData
.crcReturned
; 
 660             vRgnData
.ircStart 
= 1; 
 661             if (::GpiQueryRegionRects( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS     
// Pres space of source 
 662                                       ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion 
// Handle of source region 
 663                                       ,NULL                                             
// Return all RECTs 
 664                                       ,&vRgnData                                        
// Operations set to return rects 
 665                                       ,pRect                                            
// Will contain the actual RECTS 
 669                 M_REGION 
= ::GpiCreateRegion( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
 
 670                                              ,vRgnData
.crcReturned
 
 674                 for( LONG i 
= 0; i 
< m_lNumRects
; i
++) 
 676                     m_pRects
[i
].x      
= pRect
[i
].xLeft
; 
 677                     m_pRects
[i
].width  
= pRect
[i
].xRight 
- pRect
[i
].xLeft
; 
 678                     m_pRects
[i
].y      
= pRect
[i
].yBottom
; 
 679                     m_pRects
[i
].height 
= pRect
[i
].yTop 
- pRect
[i
].yBottom
; 
 682                 ((wxRegionRefData
*)m_refData
)->m_hPS 
= ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
; 
 687 } // end of wxRegionIterator::Reset 
 690 // Increment iterator. The rectangle returned is the one after the 
 693 void wxRegionIterator::operator++ () 
 695     if (m_lCurrent 
< m_lNumRects
) 
 697 } // end of wxRegionIterator::operator ++ 
 700 // Increment iterator. The rectangle returned is the one before the 
 703 void wxRegionIterator::operator++ (int) 
 705     if (m_lCurrent 
< m_lNumRects
) 
 707 } // end of wxRegionIterator::operator++ 
 709 wxCoord 
wxRegionIterator::GetX() const 
 711     if (m_lCurrent 
< m_lNumRects
) 
 712         return m_pRects
[m_lCurrent
].x
; 
 714 } // end of wxRegionIterator::GetX 
 716 wxCoord 
wxRegionIterator::GetY() const 
 718     if (m_lCurrent 
< m_lNumRects
) 
 719         return m_pRects
[m_lCurrent
].y
; 
 721 } // end of wxRegionIterator::GetY 
 723 wxCoord 
wxRegionIterator::GetW() const 
 725     if (m_lCurrent 
< m_lNumRects
) 
 726         return m_pRects
[m_lCurrent
].width 
; 
 728 } // end of wxRegionIterator::GetW 
 730 wxCoord 
wxRegionIterator::GetH() const 
 732     if (m_lCurrent 
< m_lNumRects
) 
 733         return m_pRects
[m_lCurrent
].height
; 
 735 } // end of wxRegionIterator::GetH