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
 
  73     virtual ~wxRegionRefData() 
  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 
 154 wxRegion::wxRegion(const wxPoint
& rTopLeft
, 
 155                    const wxPoint
& rBottomRight
) 
 158     SIZEL                           vSize 
= {0, 0}; 
 159     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 160     HDC                             hDC 
= ::DevOpenDC( vHabmain
 
 168     vRect
.xLeft   
= rTopLeft
.x
; 
 169     vRect
.xRight  
= rBottomRight
.x
; 
 170     vRect
.yBottom 
= rTopLeft
.y
; 
 171     vRect
.yTop    
= rBottomRight
.y
; 
 173     m_refData     
= new wxRegionRefData
; 
 176     // Need a PS to create a Region 
 178     ((wxRegionRefData
*)m_refData
)->m_hPS 
= ::GpiCreatePS( vHabmain
 
 181                                                          ,PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
 
 183     M_REGION      
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 187 } // end of wxRegion::wxRegion 
 189 wxRegion::wxRegion(const wxRect
& rRect
) 
 192     SIZEL                           vSize 
= {0, 0}; 
 193     DEVOPENSTRUC                    vDop 
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L}; 
 194     HDC                             hDC 
= ::DevOpenDC( vHabmain
 
 203     vRect
.xLeft   
= rRect
.x
; 
 204     vRect
.xRight  
= rRect
.x 
+ rRect
.width
; 
 205     vRect
.yBottom 
= rRect
.y
; 
 206     vRect
.yTop    
= rRect
.y 
+ rRect
.height
; 
 208     m_refData     
= new wxRegionRefData
; 
 211     // Need a PS to create a Region 
 213     ((wxRegionRefData
*)m_refData
)->m_hPS 
= ::GpiCreatePS( vHabmain
 
 216                                                          ,PU_PELS 
| GPIT_MICRO 
| GPIA_ASSOC
 
 218     M_REGION      
= ::GpiCreateRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 222 } // end of wxRegion::wxRegion 
 224 wxRegion::wxRegion(size_t n
, const wxPoint 
*points
, int WXUNUSED(fillStyle
)) 
 230 // Destroy the region. 
 232 wxRegion::~wxRegion() 
 234 } // end of wxRegion::~wxRegion 
 236 wxGDIRefData 
*wxRegion::CreateGDIRefData() const 
 238     return new wxRegionRefData
; 
 241 wxGDIRefData 
*wxRegion::CloneGDIRefData(const wxGDIRefData 
*data
) const 
 243     return new wxRegionRefData(*(wxRegionRefData 
*)data
); 
 246 //----------------------------------------------------------------------------- 
 248 //----------------------------------------------------------------------------- 
 250 bool wxRegion::DoOffset( wxCoord x
, wxCoord y 
) 
 261     if ( ::OffsetRgn(GetHrgn(), x
, y
) == ERROR 
) 
 263         wxLogLastError(_T("OffsetRgn")); 
 272 // Clear current region 
 274 void wxRegion::Clear() 
 277 } // end of wxRegion::Clear 
 280 // Union region with this. 
 282 bool wxRegion::DoCombine( const wxRegion
& rRegion
, wxRegionOp eOp 
) 
 285     // We can't use the API functions if we don't have a valid region handle 
 289         // combining with an empty/invalid region works differently depending 
 300                 wxFAIL_MSG( _T("unknown region operation") ); 
 305                 // leave empty/invalid 
 309     else // we have a valid region 
 337         return (::GpiCombineRegion( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
 
 340                                    ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion
 
 345 } // end of wxRegion::Combine 
 347 //----------------------------------------------------------------------------- 
 348 //# Information on region 
 349 //----------------------------------------------------------------------------- 
 351 bool wxRegion::DoIsEqual(const wxRegion
& WXUNUSED(region
)) const 
 357 // Outer bounds of region 
 359 bool wxRegion::DoGetBox( 
 371         rc 
= ::GpiQueryRegionBox( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 377         vWidth  
= vRect
.xRight 
- vRect
.xLeft
; 
 378         vHeight 
= vRect
.yTop 
- vRect
.yBottom
; 
 383         x 
= y 
= vWidth 
= vHeight 
= 0L; 
 386 } // end of wxRegion::GetBox 
 391 bool wxRegion::IsEmpty() const 
 406     return ((vWidth 
== 0) && (vHeight 
== 0)); 
 407 } // end of wxRegion::IsEmpty 
 409 //----------------------------------------------------------------------------- 
 411 //----------------------------------------------------------------------------- 
 413 // Does the region contain the point pt? 
 415 wxRegionContain 
wxRegion::DoContainsPoint( wxCoord x
, wxCoord y 
) const 
 417     POINTL vPoint 
= { x
, y 
}; 
 422     LONG lInside 
= ::GpiPtInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
, 
 426     if (lInside 
== PRGN_INSIDE
) 
 430 } // end of wxRegion::Contains 
 433 // Does the region contain the rectangle (x, y, w, h)? 
 435 wxRegionContain 
wxRegion::DoContainsRect(const wxRect
& rect
) const 
 441     vRect
.xLeft   
= rect
.x
; 
 442     vRect
.xRight  
= rect
.x 
+ rect
.width
; 
 443     vRect
.yTop    
= rect
.y 
+ rect
.height
; 
 444     vRect
.yBottom 
= rect
.y
; 
 446     LONG lInside 
= ::GpiRectInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
, 
 452         case RRGN_INSIDE    
:   return wxInRegion
; 
 453         case RRGN_PARTIAL   
:   return wxPartRegion
; 
 455         default             :   return wxOutRegion
; 
 458 } // end of wxRegion::Contains 
 461 // Get internal region handle 
 463 WXHRGN 
wxRegion::GetHRGN() const 
 467     return (WXHRGN
) M_REGION
; 
 471 // Set a new PS, this means we have to recreate the old region in the new 
 474 void wxRegion::SetPS( 
 481     vRgnData
.ulDirection 
= RECTDIR_LFRT_TOPBOT
; 
 482     if (::GpiQueryRegionRects( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 483                               ,((wxRegionRefData
*)m_refData
)->m_hRegion
 
 489         pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
 490         vRgnData
.crc 
= vRgnData
.crcReturned
; 
 491         vRgnData
.ircStart 
= 1; 
 492         if (::GpiQueryRegionRects( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 493                                   ,((wxRegionRefData
*)m_refData
)->m_hRegion
 
 500             // First destroy the region out of the old PS 
 501             // and then create it in the new and set the new to current 
 503             ::GpiDestroyRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 506             ((wxRegionRefData
*)m_refData
)->m_hRegion 
= ::GpiCreateRegion( hPS
 
 507                                                                          ,vRgnData
.crcReturned
 
 510             ((wxRegionRefData
*)m_refData
)->m_hPS 
= hPS
; 
 514 } // end of wxRegion::SetPS 
 516 /////////////////////////////////////////////////////////////////////////////// 
 518 //                             wxRegionIterator                              // 
 520 /////////////////////////////////////////////////////////////////////////////// 
 523 // Initialize empty iterator 
 525 wxRegionIterator::wxRegionIterator() 
 530 } // end of wxRegionIterator::wxRegionIterator 
 532 wxRegionIterator::~wxRegionIterator() 
 536 } // end of wxRegionIterator::~wxRegionIterator 
 539 // Initialize iterator for region 
 541 wxRegionIterator::wxRegionIterator( 
 542   const wxRegion
&                   rRegion
 
 547 } // end of wxRegionIterator::wxRegionIterator 
 550 // Reset iterator for a new /e region. 
 552 void wxRegionIterator::Reset( 
 553   const wxRegion
&                   rRegion
 
 565     if (m_vRegion
.Empty()) 
 572         vRgnData
.ulDirection 
= RECTDIR_LFRT_TOPBOT
; 
 573         if (::GpiQueryRegionRects( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS     
// Pres space 
 574                                   ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion 
// Handle of region to query 
 575                                   ,NULL                                             
// Return all RECTs 
 576                                   ,&vRgnData                                        
// Will contain number or RECTs in region 
 577                                   ,NULL                                             
// NULL to return number of RECTs 
 580             pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
 581             m_pRects 
= new wxRect
[vRgnData
.crcReturned
]; 
 582             vRgnData
.crc 
= vRgnData
.crcReturned
; 
 583             m_lNumRects 
= vRgnData
.crcReturned
; 
 584             vRgnData
.ircStart 
= 1; 
 585             if (::GpiQueryRegionRects( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS     
// Pres space of source 
 586                                       ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion 
// Handle of source region 
 587                                       ,NULL                                             
// Return all RECTs 
 588                                       ,&vRgnData                                        
// Operations set to return rects 
 589                                       ,pRect                                            
// Will contain the actual RECTS 
 593                 M_REGION 
= ::GpiCreateRegion( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
 
 594                                              ,vRgnData
.crcReturned
 
 598                 for( LONG i 
= 0; i 
< m_lNumRects
; i
++) 
 600                     m_pRects
[i
].x      
= pRect
[i
].xLeft
; 
 601                     m_pRects
[i
].width  
= pRect
[i
].xRight 
- pRect
[i
].xLeft
; 
 602                     m_pRects
[i
].y      
= pRect
[i
].yBottom
; 
 603                     m_pRects
[i
].height 
= pRect
[i
].yTop 
- pRect
[i
].yBottom
; 
 606                 ((wxRegionRefData
*)m_refData
)->m_hPS 
= ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
; 
 611 } // end of wxRegionIterator::Reset 
 614 // Increment iterator. The rectangle returned is the one after the 
 617 void wxRegionIterator::operator++ () 
 619     if (m_lCurrent 
< m_lNumRects
) 
 621 } // end of wxRegionIterator::operator ++ 
 624 // Increment iterator. The rectangle returned is the one before the 
 627 void wxRegionIterator::operator++ (int) 
 629     if (m_lCurrent 
< m_lNumRects
) 
 631 } // end of wxRegionIterator::operator++ 
 633 wxCoord 
wxRegionIterator::GetX() const 
 635     if (m_lCurrent 
< m_lNumRects
) 
 636         return m_pRects
[m_lCurrent
].x
; 
 638 } // end of wxRegionIterator::GetX 
 640 wxCoord 
wxRegionIterator::GetY() const 
 642     if (m_lCurrent 
< m_lNumRects
) 
 643         return m_pRects
[m_lCurrent
].y
; 
 645 } // end of wxRegionIterator::GetY 
 647 wxCoord 
wxRegionIterator::GetW() const 
 649     if (m_lCurrent 
< m_lNumRects
) 
 650         return m_pRects
[m_lCurrent
].width 
; 
 652 } // end of wxRegionIterator::GetW 
 654 wxCoord 
wxRegionIterator::GetH() const 
 656     if (m_lCurrent 
< m_lNumRects
) 
 657         return m_pRects
[m_lCurrent
].height
; 
 659 } // end of wxRegionIterator::GetH