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 
 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::DoOffset( 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 // Union region with this. 
 281 bool wxRegion::DoCombine( const wxRegion
& rRegion
, wxRegionOp eOp 
) 
 284     // We can't use the API functions if we don't have a valid region handle 
 288         // combining with an empty/invalid region works differently depending 
 299                 wxFAIL_MSG( _T("unknown region operation") ); 
 304                 // leave empty/invalid 
 308     else // we have a valid region 
 336         return (::GpiCombineRegion( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
 
 339                                    ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion
 
 344 } // end of wxRegion::Combine 
 346 //----------------------------------------------------------------------------- 
 347 //# Information on region 
 348 //----------------------------------------------------------------------------- 
 350 bool wxRegion::DoIsEqual(const wxRegion
& WXUNUSED(region
)) const 
 356 // Outer bounds of region 
 358 bool wxRegion::DoGetBox( 
 370         rc 
= ::GpiQueryRegionBox( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 376         vWidth  
= vRect
.xRight 
- vRect
.xLeft
; 
 377         vHeight 
= vRect
.yTop 
- vRect
.yBottom
; 
 382         x 
= y 
= vWidth 
= vHeight 
= 0L; 
 385 } // end of wxRegion::GetBox 
 390 bool wxRegion::IsEmpty() const 
 405     return ((vWidth 
== 0) && (vHeight 
== 0)); 
 406 } // end of wxRegion::IsEmpty 
 408 //----------------------------------------------------------------------------- 
 410 //----------------------------------------------------------------------------- 
 412 // Does the region contain the point pt? 
 414 wxRegionContain 
wxRegion::DoContainsPoint( wxCoord x
, wxCoord y 
) const 
 416     POINTL vPoint 
= { x
, y 
}; 
 421     LONG lInside 
= ::GpiPtInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
, 
 425     if (lInside 
== PRGN_INSIDE
) 
 429 } // end of wxRegion::Contains 
 432 // Does the region contain the rectangle (x, y, w, h)? 
 434 wxRegionContain 
wxRegion::DoContainsRect(const wxRect
& rect
) const 
 440     vRect
.xLeft   
= rect
.x
; 
 441     vRect
.xRight  
= rect
.x 
+ rect
.width
; 
 442     vRect
.yTop    
= rect
.y 
+ rect
.height
; 
 443     vRect
.yBottom 
= rect
.y
; 
 445     LONG lInside 
= ::GpiRectInRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
, 
 451         case RRGN_INSIDE    
:   return wxInRegion
; 
 452         case RRGN_PARTIAL   
:   return wxPartRegion
; 
 454         default             :   return wxOutRegion
; 
 457 } // end of wxRegion::Contains 
 460 // Get internal region handle 
 462 WXHRGN 
wxRegion::GetHRGN() const 
 466     return (WXHRGN
) M_REGION
; 
 470 // Set a new PS, this means we have to recreate the old region in the new 
 473 void wxRegion::SetPS( 
 480     vRgnData
.ulDirection 
= RECTDIR_LFRT_TOPBOT
; 
 481     if (::GpiQueryRegionRects( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 482                               ,((wxRegionRefData
*)m_refData
)->m_hRegion
 
 488         pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
 489         vRgnData
.crc 
= vRgnData
.crcReturned
; 
 490         vRgnData
.ircStart 
= 1; 
 491         if (::GpiQueryRegionRects( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 492                                   ,((wxRegionRefData
*)m_refData
)->m_hRegion
 
 499             // First destroy the region out of the old PS 
 500             // and then create it in the new and set the new to current 
 502             ::GpiDestroyRegion( ((wxRegionRefData
*)m_refData
)->m_hPS
 
 505             ((wxRegionRefData
*)m_refData
)->m_hRegion 
= ::GpiCreateRegion( hPS
 
 506                                                                          ,vRgnData
.crcReturned
 
 509             ((wxRegionRefData
*)m_refData
)->m_hPS 
= hPS
; 
 513 } // end of wxRegion::SetPS 
 515 /////////////////////////////////////////////////////////////////////////////// 
 517 //                             wxRegionIterator                              // 
 519 /////////////////////////////////////////////////////////////////////////////// 
 522 // Initialize empty iterator 
 524 wxRegionIterator::wxRegionIterator() 
 529 } // end of wxRegionIterator::wxRegionIterator 
 531 wxRegionIterator::~wxRegionIterator() 
 535 } // end of wxRegionIterator::~wxRegionIterator 
 538 // Initialize iterator for region 
 540 wxRegionIterator::wxRegionIterator( 
 541   const wxRegion
&                   rRegion
 
 546 } // end of wxRegionIterator::wxRegionIterator 
 549 // Reset iterator for a new /e region. 
 551 void wxRegionIterator::Reset( 
 552   const wxRegion
&                   rRegion
 
 564     if (m_vRegion
.Empty()) 
 571         vRgnData
.ulDirection 
= RECTDIR_LFRT_TOPBOT
; 
 572         if (::GpiQueryRegionRects( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS     
// Pres space 
 573                                   ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion 
// Handle of region to query 
 574                                   ,NULL                                             
// Return all RECTs 
 575                                   ,&vRgnData                                        
// Will contain number or RECTs in region 
 576                                   ,NULL                                             
// NULL to return number of RECTs 
 579             pRect 
= new RECTL
[vRgnData
.crcReturned
]; 
 580             m_pRects 
= new wxRect
[vRgnData
.crcReturned
]; 
 581             vRgnData
.crc 
= vRgnData
.crcReturned
; 
 582             m_lNumRects 
= vRgnData
.crcReturned
; 
 583             vRgnData
.ircStart 
= 1; 
 584             if (::GpiQueryRegionRects( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS     
// Pres space of source 
 585                                       ,((wxRegionRefData
*)rRegion
.m_refData
)->m_hRegion 
// Handle of source region 
 586                                       ,NULL                                             
// Return all RECTs 
 587                                       ,&vRgnData                                        
// Operations set to return rects 
 588                                       ,pRect                                            
// Will contain the actual RECTS 
 592                 M_REGION 
= ::GpiCreateRegion( ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
 
 593                                              ,vRgnData
.crcReturned
 
 597                 for( LONG i 
= 0; i 
< m_lNumRects
; i
++) 
 599                     m_pRects
[i
].x      
= pRect
[i
].xLeft
; 
 600                     m_pRects
[i
].width  
= pRect
[i
].xRight 
- pRect
[i
].xLeft
; 
 601                     m_pRects
[i
].y      
= pRect
[i
].yBottom
; 
 602                     m_pRects
[i
].height 
= pRect
[i
].yTop 
- pRect
[i
].yBottom
; 
 605                 ((wxRegionRefData
*)m_refData
)->m_hPS 
= ((wxRegionRefData
*)rRegion
.m_refData
)->m_hPS
; 
 610 } // end of wxRegionIterator::Reset 
 613 // Increment iterator. The rectangle returned is the one after the 
 616 void wxRegionIterator::operator++ () 
 618     if (m_lCurrent 
< m_lNumRects
) 
 620 } // end of wxRegionIterator::operator ++ 
 623 // Increment iterator. The rectangle returned is the one before the 
 626 void wxRegionIterator::operator++ (int) 
 628     if (m_lCurrent 
< m_lNumRects
) 
 630 } // end of wxRegionIterator::operator++ 
 632 wxCoord 
wxRegionIterator::GetX() const 
 634     if (m_lCurrent 
< m_lNumRects
) 
 635         return m_pRects
[m_lCurrent
].x
; 
 637 } // end of wxRegionIterator::GetX 
 639 wxCoord 
wxRegionIterator::GetY() const 
 641     if (m_lCurrent 
< m_lNumRects
) 
 642         return m_pRects
[m_lCurrent
].y
; 
 644 } // end of wxRegionIterator::GetY 
 646 wxCoord 
wxRegionIterator::GetW() const 
 648     if (m_lCurrent 
< m_lNumRects
) 
 649         return m_pRects
[m_lCurrent
].width 
; 
 651 } // end of wxRegionIterator::GetW 
 653 wxCoord 
wxRegionIterator::GetH() const 
 655     if (m_lCurrent 
< m_lNumRects
) 
 656         return m_pRects
[m_lCurrent
].height
; 
 658 } // end of wxRegionIterator::GetH