1///////////////////////////////////////////////////////////////////////////// 2// File: src/os2/region.cpp 3// Purpose: Region class 4// Author: David Webster 5// Modified by: 6// Created: 10/15/99 7// RCS-ID: $Id: region.cpp 43288 2006-11-10 20:35:39Z ABX $ 8// Copyright: (c) David Webster 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#ifndef WX_PRECOMP 16 #include "wx/app.h" 17 #include "wx/window.h" 18 #include "wx/gdicmn.h" 19#endif 20 21#include "wx/os2/region.h" 22 23#include "wx/os2/private.h" 24 25IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject) 26IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject) 27 28//----------------------------------------------------------------------------- 29// wxRegionRefData implementation 30//----------------------------------------------------------------------------- 31 32class WXDLLEXPORT wxRegionRefData : public wxGDIRefData { 33public: 34 wxRegionRefData() 35 { 36 m_hRegion = 0; 37 m_hPS = 0; 38 } 39 40 wxRegionRefData(const wxRegionRefData& rData) 41 { 42 RGNRECT vRgnData; 43 PRECTL pRect = NULL; 44 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 51 )) 52 { 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 61 )) 62 { 63 m_hRegion = ::GpiCreateRegion( rData.m_hPS 64 ,vRgnData.crcReturned 65 ,pRect 66 ); 67 m_hPS = rData.m_hPS; 68 } 69 delete [] pRect; 70 } 71 } 72 73 virtual ~wxRegionRefData() 74 { 75 ::GpiDestroyRegion(m_hPS, m_hRegion); 76 } 77 78 HRGN m_hRegion; 79 HPS m_hPS; 80}; 81 82#define M_REGION (((wxRegionRefData*)m_refData)->m_hRegion) 83#define M_REGION_OF(rgn) (((wxRegionRefData*)(rgn.m_refData))->m_hRegion) 84 85//----------------------------------------------------------------------------- 86// wxRegion 87//----------------------------------------------------------------------------- 88 89// General remark: 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. 95 96/*! 97 * Create an empty region. 98 */ 99wxRegion::wxRegion() 100{ 101 m_refData = new wxRegionRefData; 102} // end of wxRegion::wxRegion 103 104wxRegion::wxRegion( 105 WXHRGN hRegion, 106 WXHDC hPS 107) 108{ 109 m_refData = new wxRegionRefData; 110 M_REGION = (HRGN) hRegion; 111 (((wxRegionRefData*)m_refData)->m_hPS) = hPS; 112} // end of wxRegion::wxRegion 113 114wxRegion::wxRegion( 115 wxCoord x 116, wxCoord y 117, wxCoord vWidth 118, wxCoord vHeight 119) 120{ 121 RECTL vRect; 122 SIZEL vSize = {0, 0}; 123 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L}; 124 HDC hDC = ::DevOpenDC( vHabmain 125 ,OD_MEMORY 126 ,"*" 127 ,5L 128 ,(PDEVOPENDATA)&vDop 129 ,NULLHANDLE 130 ); 131 132 133 vRect.xLeft = x; 134 vRect.xRight = x + vWidth; 135 vRect.yBottom = y; 136 vRect.yTop = y + vHeight; 137 138 m_refData = new wxRegionRefData; 139 140 // 141 // Need a PS to create a Region 142 // 143 ((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain 144 ,hDC 145 ,&vSize 146 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC 147 ); 148 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS 149 ,1 150 ,&vRect 151 ); 152} // end of wxRegion::wxRegion 153 154wxRegion::wxRegion(const wxPoint& rTopLeft, 155 const wxPoint& rBottomRight) 156{ 157 RECTL vRect; 158 SIZEL vSize = {0, 0}; 159 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L}; 160 HDC hDC = ::DevOpenDC( vHabmain 161 ,OD_MEMORY 162 ,"*" 163 ,5L 164 ,(PDEVOPENDATA)&vDop 165 ,NULLHANDLE 166 ); 167 168 vRect.xLeft = rTopLeft.x; 169 vRect.xRight = rBottomRight.x; 170 vRect.yBottom = rTopLeft.y; 171 vRect.yTop = rBottomRight.y; 172 173 m_refData = new wxRegionRefData; 174 175 // 176 // Need a PS to create a Region 177 // 178 ((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain 179 ,hDC 180 ,&vSize 181 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC 182 ); 183 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS 184 ,1 185 ,&vRect 186 ); 187} // end of wxRegion::wxRegion 188 189wxRegion::wxRegion(const wxRect& rRect) 190{ 191 RECTL vRect; 192 SIZEL vSize = {0, 0}; 193 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L}; 194 HDC hDC = ::DevOpenDC( vHabmain 195 ,OD_MEMORY 196 ,"*" 197 ,5L 198 ,(PDEVOPENDATA)&vDop 199 ,NULLHANDLE 200 ); 201 202 203 vRect.xLeft = rRect.x; 204 vRect.xRight = rRect.x + rRect.width; 205 vRect.yBottom = rRect.y; 206 vRect.yTop = rRect.y + rRect.height; 207 208 m_refData = new wxRegionRefData; 209 210 // 211 // Need a PS to create a Region 212 // 213 ((wxRegionRefData*)m_refData)->m_hPS = ::GpiCreatePS( vHabmain 214 ,hDC 215 ,&vSize 216 ,PU_PELS | GPIT_MICRO | GPIA_ASSOC 217 ); 218 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS 219 ,1 220 ,&vRect 221 ); 222} // end of wxRegion::wxRegion 223 224wxRegion::wxRegion(size_t n, const wxPoint *points, int WXUNUSED(fillStyle)) 225{ 226 // TO DO 227} 228 229// 230// Destroy the region. 231// 232wxRegion::~wxRegion() 233{ 234} // end of wxRegion::~wxRegion 235 236wxObjectRefData *wxRegion::CreateData() const 237{ 238 return new wxRegionRefData; 239} 240 241wxObjectRefData *wxRegion::CloneData(const wxObjectRefData *data) const 242{ 243 return new wxRegionRefData(*(wxRegionRefData *)data); 244} 245 246//----------------------------------------------------------------------------- 247//# Modify region 248//----------------------------------------------------------------------------- 249 250bool wxRegion::DoOffset( wxCoord x, wxCoord y ) 251{ 252 if ( !x && !y ) 253 { 254 // nothing to do 255 return true; 256 } 257 258 AllocExclusive(); 259 260#if 0 261 if ( ::OffsetRgn(GetHrgn(), x, y) == ERROR ) 262 { 263 wxLogLastError(_T("OffsetRgn")); 264 265 return false; 266 } 267#endif 268 return true; 269} 270 271// 272// Clear current region 273// 274void wxRegion::Clear() 275{ 276 UnRef(); 277} // end of wxRegion::Clear 278 279// 280// Union region with this. 281// 282bool wxRegion::DoCombine( const wxRegion& rRegion, wxRegionOp eOp ) 283{ 284 // 285 // We can't use the API functions if we don't have a valid region handle 286 // 287 if (!m_refData) 288 { 289 // combining with an empty/invalid region works differently depending 290 // on the operation 291 switch (eOp) 292 { 293 case wxRGN_COPY: 294 case wxRGN_OR: 295 case wxRGN_XOR: 296 *this = rRegion; 297 break; 298 299 default: 300 wxFAIL_MSG( _T("unknown region operation") ); 301 // fall through 302 303 case wxRGN_AND: 304 case wxRGN_DIFF: 305 // leave empty/invalid 306 return false; 307 } 308 } 309 else // we have a valid region 310 { 311 312 LONG lMode = 0; 313 314 switch (eOp) 315 { 316 case wxRGN_AND: 317 lMode = CRGN_AND; 318 break; 319 320 case wxRGN_OR: 321 lMode = CRGN_OR; 322 break; 323 324 case wxRGN_XOR: 325 lMode = CRGN_XOR; 326 break; 327 328 case wxRGN_DIFF: 329 lMode = CRGN_DIFF; 330 break; 331 332 case wxRGN_COPY: 333 default: 334 lMode = CRGN_COPY; 335 break; 336 } 337 return (::GpiCombineRegion( ((wxRegionRefData*)rRegion.m_refData)->m_hPS 338 ,M_REGION 339 ,M_REGION 340 ,((wxRegionRefData*)rRegion.m_refData)->m_hRegion 341 ,lMode 342 ) != RGN_ERROR); 343 } 344 return true; 345} // end of wxRegion::Combine 346 347//----------------------------------------------------------------------------- 348//# Information on region 349//----------------------------------------------------------------------------- 350 351bool wxRegion::DoIsEqual(const wxRegion& WXUNUSED(region)) const 352{ 353 return false; 354} 355 356// 357// Outer bounds of region 358// 359bool wxRegion::DoGetBox( 360 wxCoord& x 361, wxCoord& y 362, wxCoord& vWidth 363, wxCoord& vHeight 364) const 365{ 366 if (m_refData) 367 { 368 RECTL vRect; 369 APIRET rc; 370 371 rc = ::GpiQueryRegionBox( ((wxRegionRefData*)m_refData)->m_hPS 372 ,M_REGION 373 ,&vRect 374 ); 375 x = vRect.xLeft; 376 y = vRect.yBottom; 377 vWidth = vRect.xRight - vRect.xLeft; 378 vHeight = vRect.yTop - vRect.yBottom; 379 return true; 380 } 381 else 382 { 383 x = y = vWidth = vHeight = 0L; 384 return false; 385 } 386} // end of wxRegion::GetBox 387 388// 389// Is region empty? 390// 391bool wxRegion::IsEmpty() const 392{ 393 wxCoord x; 394 wxCoord y; 395 wxCoord vWidth; 396 wxCoord vHeight; 397 398 if (M_REGION == 0) 399 return true; 400 401 GetBox( x 402 ,y 403 ,vWidth 404 ,vHeight 405 ); 406 return ((vWidth == 0) && (vHeight == 0)); 407} // end of wxRegion::IsEmpty 408 409//----------------------------------------------------------------------------- 410// Tests 411//----------------------------------------------------------------------------- 412// 413// Does the region contain the point pt? 414// 415wxRegionContain wxRegion::DoContainsPoint( wxCoord x, wxCoord y ) const 416{ 417 POINTL vPoint = { x, y }; 418 419 if (!m_refData) 420 return wxOutRegion; 421 422 LONG lInside = ::GpiPtInRegion( ((wxRegionRefData*)m_refData)->m_hPS, 423 M_REGION, 424 &vPoint 425 ); 426 if (lInside == PRGN_INSIDE) 427 return wxInRegion; 428 else 429 return wxOutRegion; 430} // end of wxRegion::Contains 431 432// 433// Does the region contain the rectangle (x, y, w, h)? 434// 435wxRegionContain wxRegion::DoContainsRect(const wxRect& rect) const 436{ 437 if (!m_refData) 438 return wxOutRegion; 439 440 RECTL vRect; 441 vRect.xLeft = rect.x; 442 vRect.xRight = rect.x + rect.width; 443 vRect.yTop = rect.y + rect.height; 444 vRect.yBottom = rect.y; 445 446 LONG lInside = ::GpiRectInRegion( ((wxRegionRefData*)m_refData)->m_hPS, 447 M_REGION, 448 &vRect 449 ); 450 switch (lInside) 451 { 452 case RRGN_INSIDE : return wxInRegion; 453 case RRGN_PARTIAL : return wxPartRegion; 454 case RRGN_ERROR : 455 default : return wxOutRegion; 456 } 457 458} // end of wxRegion::Contains 459 460// 461// Get internal region handle 462// 463WXHRGN wxRegion::GetHRGN() const 464{ 465 if (!m_refData) 466 return (WXHRGN) 0; 467 return (WXHRGN) M_REGION; 468} 469 470// 471// Set a new PS, this means we have to recreate the old region in the new 472// PS 473// 474void wxRegion::SetPS( 475 HPS hPS 476) 477{ 478 RGNRECT vRgnData; 479 PRECTL pRect = NULL; 480 481 vRgnData.ulDirection = RECTDIR_LFRT_TOPBOT; 482 if (::GpiQueryRegionRects( ((wxRegionRefData*)m_refData)->m_hPS 483 ,((wxRegionRefData*)m_refData)->m_hRegion 484 ,NULL 485 ,&vRgnData 486 ,NULL 487 )) 488 { 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 494 ,NULL 495 ,&vRgnData 496 ,pRect 497 )) 498 { 499 // 500 // First destroy the region out of the old PS 501 // and then create it in the new and set the new to current 502 // 503 ::GpiDestroyRegion( ((wxRegionRefData*)m_refData)->m_hPS 504 ,M_REGION 505 ); 506 ((wxRegionRefData*)m_refData)->m_hRegion = ::GpiCreateRegion( hPS 507 ,vRgnData.crcReturned 508 ,pRect 509 ); 510 ((wxRegionRefData*)m_refData)->m_hPS = hPS; 511 } 512 delete [] pRect; 513 } 514} // end of wxRegion::SetPS 515 516/////////////////////////////////////////////////////////////////////////////// 517// // 518// wxRegionIterator // 519// // 520/////////////////////////////////////////////////////////////////////////////// 521 522// 523// Initialize empty iterator 524// 525wxRegionIterator::wxRegionIterator() 526: m_lCurrent(0) 527, m_lNumRects(0) 528, m_pRects(NULL) 529{ 530} // end of wxRegionIterator::wxRegionIterator 531 532wxRegionIterator::~wxRegionIterator() 533{ 534 if (m_pRects) 535 delete[] m_pRects; 536} // end of wxRegionIterator::~wxRegionIterator 537 538// 539// Initialize iterator for region 540// 541wxRegionIterator::wxRegionIterator( 542 const wxRegion& rRegion 543) 544{ 545 m_pRects = NULL; 546 Reset(rRegion); 547} // end of wxRegionIterator::wxRegionIterator 548 549// 550// Reset iterator for a new /e region. 551// 552void wxRegionIterator::Reset( 553 const wxRegion& rRegion 554) 555{ 556 m_lCurrent = 0; 557 m_lNumRects = 0; 558 m_vRegion = rRegion; 559 560 if (m_pRects) 561 delete[] m_pRects; 562 563 m_pRects = NULL; 564 565 if (m_vRegion.Empty()) 566 m_lNumRects = 0; 567 else 568 { 569 RGNRECT vRgnData; 570 PRECTL pRect; 571 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 578 )) 579 { 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 590 )) 591 { 592#if 0 593 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)rRegion.m_refData)->m_hPS 594 ,vRgnData.crcReturned 595 ,pRect 596 ); 597#endif 598 for( LONG i = 0; i < m_lNumRects; i++) 599 { 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; 604 } 605#if 0 606 ((wxRegionRefData*)m_refData)->m_hPS = ((wxRegionRefData*)rRegion.m_refData)->m_hPS; 607#endif 608 } 609 } 610 } 611} // end of wxRegionIterator::Reset 612 613// 614// Increment iterator. The rectangle returned is the one after the 615// incrementation. 616// 617void wxRegionIterator::operator++ () 618{ 619 if (m_lCurrent < m_lNumRects) 620 ++m_lCurrent; 621} // end of wxRegionIterator::operator ++ 622 623// 624// Increment iterator. The rectangle returned is the one before the 625// incrementation. 626// 627void wxRegionIterator::operator++ (int) 628{ 629 if (m_lCurrent < m_lNumRects) 630 ++m_lCurrent; 631} // end of wxRegionIterator::operator++ 632 633wxCoord wxRegionIterator::GetX() const 634{ 635 if (m_lCurrent < m_lNumRects) 636 return m_pRects[m_lCurrent].x; 637 return 0L; 638} // end of wxRegionIterator::GetX 639 640wxCoord wxRegionIterator::GetY() const 641{ 642 if (m_lCurrent < m_lNumRects) 643 return m_pRects[m_lCurrent].y; 644 return 0L; 645} // end of wxRegionIterator::GetY 646 647wxCoord wxRegionIterator::GetW() const 648{ 649 if (m_lCurrent < m_lNumRects) 650 return m_pRects[m_lCurrent].width ; 651 return 0L; 652} // end of wxRegionIterator::GetW 653 654wxCoord wxRegionIterator::GetH() const 655{ 656 if (m_lCurrent < m_lNumRects) 657 return m_pRects[m_lCurrent].height; 658 return 0L; 659} // end of wxRegionIterator::GetH 660