1 ///////////////////////////////////////////////////////////////////////////// 
   2 // File:      src/os2/region.cpp 
   3 // Purpose:   Region class 
   4 // Author:    David Webster 
   8 // Copyright: (c) David Webster 
   9 // Licence:   wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  17     #include "wx/window.h" 
  18     #include "wx/gdicmn.h" 
  21 #include "wx/os2/region.h" 
  23 #include "wx/os2/private.h" 
  25 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
) 
  26 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
, wxObject
) 
  28 //----------------------------------------------------------------------------- 
  29 // wxRegionRefData implementation 
  30 //----------------------------------------------------------------------------- 
  32 class WXDLLEXPORT wxRegionRefData 
: public wxGDIRefData 
{ 
  40     wxRegionRefData(const wxRegionRefData
& rData
) 
  45         vRgnData
.ulDirection 
= RECTDIR_LFRT_TOPBOT
; 
  46         if (::GpiQueryRegionRects( rData
.m_hPS      
// Pres space 
  47                                   ,rData
.m_hRegion  
// Handle of region to query 
  48                                   ,NULL             
// Return all RECTs 
  49                                   ,&vRgnData        
// Will contain number or RECTs in region 
  50                                   ,NULL             
// NULL to return number of RECTs 
  53             pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
  54             vRgnData
.crc 
= vRgnData
.crcReturned
; 
  55             vRgnData
.ircStart 
= 1; 
  56             if (::GpiQueryRegionRects( rData
.m_hPS     
// Pres space of source 
  57                                       ,rData
.m_hRegion 
// Handle of source region 
  58                                       ,NULL            
// Return all RECTs 
  59                                       ,&vRgnData       
// Operations set to return rects 
  60                                       ,pRect           
// Will contain the actual RECTS 
  63                 m_hRegion 
= ::GpiCreateRegion( rData
.m_hPS
 
  75         ::GpiDestroyRegion(m_hPS
, m_hRegion
); 
  82 #define M_REGION (((wxRegionRefData*)m_refData)->m_hRegion) 
  83 #define M_REGION_OF(rgn) (((wxRegionRefData*)(rgn.m_refData))->m_hRegion) 
  85 //----------------------------------------------------------------------------- 
  87 //----------------------------------------------------------------------------- 
  90 // wxRegion is always basically stored in wx coordinates. However, since 
  91 // OS/2's internal functions rely on "top > bottom", the values of top and 
  92 // bottom values of a region need to be interchanged, as compared to wx. 
  93 // This needs to be taken into account when feeding any rectangle to wx _or_ 
  94 // when accessing the region data via GetBox, wxRegionIterator or otherwise. 
  97  * Create an empty region. 
 101     m_refData 
= new wxRegionRefData
; 
 102 } // end of wxRegion::wxRegion 
 109     m_refData 
= new wxRegionRefData
; 
 110     M_REGION 
= (HRGN
) hRegion
; 
 111     (((wxRegionRefData
*)m_refData
)->m_hPS
) = hPS
; 
 112 } // end of wxRegion::wxRegion 
 122     SIZEL                           vSize 
= {0, 0}; 
 123     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 124     HDC                             hDC 
= ::DevOpenDC( vHabmain
 
 134     vRect
.xRight  
= x 
+ vWidth
; 
 136     vRect
.yTop    
= y 
+ vHeight
; 
 138     m_refData     
= new wxRegionRefData
; 
 141     // Need a PS to create a Region 
 143     ((wxRegionRefData
*)m_refData
)->m_hPS 
= ::GpiCreatePS( vHabmain
 
 146                                                          ,PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
 
 148     M_REGION      
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 152 } // end of wxRegion::wxRegion 
 155   const wxPoint
&                    rTopLeft
 
 156 , const wxPoint
&                    rBottomRight
 
 160     SIZEL                           vSize 
= {0, 0}; 
 161     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 162     HDC                             hDC 
= ::DevOpenDC( vHabmain
 
 170     vRect
.xLeft   
= rTopLeft
.x
; 
 171     vRect
.xRight  
= rBottomRight
.x
; 
 172     vRect
.yBottom 
= rTopLeft
.y
; 
 173     vRect
.yTop    
= rBottomRight
.y
; 
 175     m_refData     
= new wxRegionRefData
; 
 178     // Need a PS to create a Region 
 180     ((wxRegionRefData
*)m_refData
)->m_hPS 
= ::GpiCreatePS( vHabmain
 
 183                                                          ,PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
 
 185     M_REGION      
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 189 } // end of wxRegion::wxRegion 
 196     SIZEL                           vSize 
= {0, 0}; 
 197     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 198     HDC                             hDC 
= ::DevOpenDC( vHabmain
 
 207     vRect
.xLeft   
= rRect
.x
; 
 208     vRect
.xRight  
= rRect
.x 
+ rRect
.width
; 
 209     vRect
.yBottom 
= rRect
.y
; 
 210     vRect
.yTop    
= rRect
.y 
+ rRect
.height
; 
 212     m_refData     
= new wxRegionRefData
; 
 215     // Need a PS to create a Region 
 217     ((wxRegionRefData
*)m_refData
)->m_hPS 
= ::GpiCreatePS( vHabmain
 
 220                                                          ,PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
 
 222     M_REGION      
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 226 } // end of wxRegion::wxRegion 
 229 // Destroy the region. 
 231 wxRegion::~wxRegion() 
 233 } // end of wxRegion::~wxRegion 
 235 wxObjectRefData 
*wxRegion::CreateData() const 
 237     return new wxRegionRefData
; 
 240 wxObjectRefData 
*wxRegion::CloneData(const wxObjectRefData 
*data
) const 
 242     return new wxRegionRefData(*(wxRegionRefData 
*)data
); 
 245 //----------------------------------------------------------------------------- 
 247 //----------------------------------------------------------------------------- 
 249 bool wxRegion::Offset( wxCoord x
, wxCoord y 
) 
 260     if ( ::OffsetRgn(GetHrgn(), x
, y
) == ERROR 
) 
 262         wxLogLastError(_T("OffsetRgn")); 
 271 // Clear current region 
 273 void wxRegion::Clear() 
 276 } // end of wxRegion::Clear 
 279 // Combine rectangle (x, y, w, h) with this. 
 281 bool wxRegion::Combine( 
 289     return Combine(wxRegion(x
, y
, vWidth
, vHeight
), eOp
); 
 290 } // end of wxRegion::Combine 
 293 // Union region with this. 
 295 bool wxRegion::Combine( const wxRegion
& rRegion
, wxRegionOp eOp 
) 
 298     // We can't use the API functions if we don't have a valid region handle 
 302         // combining with an empty/invalid region works differently depending 
 313                 wxFAIL_MSG( _T("unknown region operation") ); 
 318                 // leave empty/invalid 
 322     else // we have a valid region 
 350         return (::GpiCombineRegion( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
 
 353                                    ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion
 
 358 } // end of wxRegion::Combine 
 360 bool wxRegion::Combine( 
 365     return Combine( rRect
.GetLeft() 
 371 } // end of wxRegion::Combine 
 373 //----------------------------------------------------------------------------- 
 374 //# Information on region 
 375 //----------------------------------------------------------------------------- 
 378 // Outer bounds of region 
 380 void wxRegion::GetBox( 
 392         rc 
= ::GpiQueryRegionBox( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 398         vWidth  
= vRect
.xRight 
- vRect
.xLeft
; 
 399         vHeight 
= vRect
.yTop 
- vRect
.yBottom
; 
 403         x 
= y 
= vWidth 
= vHeight 
= 0L; 
 405 } // end of wxRegion::GetBox 
 407 wxRect 
wxRegion::GetBox() const 
 411     return wxRect(x
, y
, w
, h
); 
 417 bool wxRegion::Empty() const 
 432     return ((vWidth 
== 0) && (vHeight 
== 0)); 
 433 } // end of wxRegion::Empty 
 435 //----------------------------------------------------------------------------- 
 437 //----------------------------------------------------------------------------- 
 439 // Does the region contain the point pt? 
 441 wxRegionContain 
wxRegion::Contains( const wxPoint
& rPoint 
) const 
 443     POINTL                          vPoint 
= { rPoint
.x
, rPoint
.y 
}; 
 448     LONG lInside 
= ::GpiPtInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
, 
 452     if (lInside 
== PRGN_INSIDE
) 
 456 } // end of wxRegion::Contains 
 459 // Does the region contain the rectangle (x, y, w, h)? 
 461 wxRegionContain 
wxRegion::Contains( wxCoord x
, 
 464                                     wxCoord vHeight 
) const 
 471     vRect
.xRight  
= x 
+ vWidth
; 
 472     vRect
.yTop    
= y 
+ vHeight
; 
 475     LONG lInside 
= ::GpiRectInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
, 
 481         case RRGN_INSIDE    
:   return wxInRegion
; 
 482         case RRGN_PARTIAL   
:   return wxPartRegion
; 
 484         default             :   return wxOutRegion
; 
 486 } // end of wxRegion::Contains 
 489 // Get internal region handle 
 491 WXHRGN 
wxRegion::GetHRGN() const 
 495     return (WXHRGN
) M_REGION
; 
 499 // Set a new PS, this means we have to recreate the old region in the new 
 502 void wxRegion::SetPS( 
 509     vRgnData
.ulDirection 
= RECTDIR_LFRT_TOPBOT
; 
 510     if (::GpiQueryRegionRects( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 511                               ,((wxRegionRefData
*)m_refData
)->m_hRegion
 
 517         pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
 518         vRgnData
.crc 
= vRgnData
.crcReturned
; 
 519         vRgnData
.ircStart 
= 1; 
 520         if (::GpiQueryRegionRects( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 521                                   ,((wxRegionRefData
*)m_refData
)->m_hRegion
 
 528             // First destroy the region out of the old PS 
 529             // and then create it in the new and set the new to current 
 531             ::GpiDestroyRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 534             ((wxRegionRefData
*)m_refData
)->m_hRegion 
= ::GpiCreateRegion( hPS
 
 535                                                                          ,vRgnData
.crcReturned
 
 538             ((wxRegionRefData
*)m_refData
)->m_hPS 
= hPS
; 
 542 } // end of wxRegion::SetPS 
 544 /////////////////////////////////////////////////////////////////////////////// 
 546 //                             wxRegionIterator                              // 
 548 /////////////////////////////////////////////////////////////////////////////// 
 551 // Initialize empty iterator 
 553 wxRegionIterator::wxRegionIterator() 
 558 } // end of wxRegionIterator::wxRegionIterator 
 560 wxRegionIterator::~wxRegionIterator() 
 564 } // end of wxRegionIterator::~wxRegionIterator 
 567 // Initialize iterator for region 
 569 wxRegionIterator::wxRegionIterator( 
 570   const wxRegion
&                   rRegion
 
 575 } // end of wxRegionIterator::wxRegionIterator 
 578 // Reset iterator for a new /e region. 
 580 void wxRegionIterator::Reset( 
 581   const wxRegion
&                   rRegion
 
 593     if (m_vRegion
.Empty()) 
 600         vRgnData
.ulDirection 
= RECTDIR_LFRT_TOPBOT
; 
 601         if (::GpiQueryRegionRects( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS     
// Pres space 
 602                                   ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion 
// Handle of region to query 
 603                                   ,NULL                                             
// Return all RECTs 
 604                                   ,&vRgnData                                        
// Will contain number or RECTs in region 
 605                                   ,NULL                                             
// NULL to return number of RECTs 
 608             pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
 609             m_pRects 
= new wxRect
[vRgnData
.crcReturned
]; 
 610             vRgnData
.crc 
= vRgnData
.crcReturned
; 
 611             m_lNumRects 
= vRgnData
.crcReturned
; 
 612             vRgnData
.ircStart 
= 1; 
 613             if (::GpiQueryRegionRects( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS     
// Pres space of source 
 614                                       ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion 
// Handle of source region 
 615                                       ,NULL                                             
// Return all RECTs 
 616                                       ,&vRgnData                                        
// Operations set to return rects 
 617                                       ,pRect                                            
// Will contain the actual RECTS 
 621                 M_REGION 
= ::GpiCreateRegion( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
 
 622                                              ,vRgnData
.crcReturned
 
 626                 for( LONG i 
= 0; i 
< m_lNumRects
; i
++) 
 628                     m_pRects
[i
].x      
= pRect
[i
].xLeft
; 
 629                     m_pRects
[i
].width  
= pRect
[i
].xRight 
- pRect
[i
].xLeft
; 
 630                     m_pRects
[i
].y      
= pRect
[i
].yBottom
; 
 631                     m_pRects
[i
].height 
= pRect
[i
].yTop 
- pRect
[i
].yBottom
; 
 634                 ((wxRegionRefData
*)m_refData
)->m_hPS 
= ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
; 
 639 } // end of wxRegionIterator::Reset 
 642 // Increment iterator. The rectangle returned is the one after the 
 645 void wxRegionIterator::operator++ () 
 647     if (m_lCurrent 
< m_lNumRects
) 
 649 } // end of wxRegionIterator::operator ++ 
 652 // Increment iterator. The rectangle returned is the one before the 
 655 void wxRegionIterator::operator++ (int) 
 657     if (m_lCurrent 
< m_lNumRects
) 
 659 } // end of wxRegionIterator::operator++ 
 661 wxCoord 
wxRegionIterator::GetX() const 
 663     if (m_lCurrent 
< m_lNumRects
) 
 664         return m_pRects
[m_lCurrent
].x
; 
 666 } // end of wxRegionIterator::GetX 
 668 wxCoord 
wxRegionIterator::GetY() const 
 670     if (m_lCurrent 
< m_lNumRects
) 
 671         return m_pRects
[m_lCurrent
].y
; 
 673 } // end of wxRegionIterator::GetY 
 675 wxCoord 
wxRegionIterator::GetW() const 
 677     if (m_lCurrent 
< m_lNumRects
) 
 678         return m_pRects
[m_lCurrent
].width 
; 
 680 } // end of wxRegionIterator::GetW 
 682 wxCoord 
wxRegionIterator::GetH() const 
 684     if (m_lCurrent 
< m_lNumRects
) 
 685         return m_pRects
[m_lCurrent
].height
; 
 687 } // end of wxRegionIterator::GetH