Changeset 61 for trunk/src/kernel/qregion_pm.cpp
- Timestamp:
- Feb 6, 2006, 10:43:39 PM (20 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel/qregion_pm.cpp
r8 r61 43 43 #include "qt_os2.h" 44 44 45 // We always create a GPI resuorce for a region with top and bottom corner 46 // points made negative and swapped. This gives us no-cost top to bottom 47 // flipping but requires to call GpiOffsetRegion() to offset the region up by 48 // the height of the presentation space viewport before it is actually used on 49 // that presentation space (usually for clipping) and, on the contrary, offset 50 // the region got from GPI down before it is stored in QRegion. 45 // To compensate the difference between Qt (where y axis goes downwards) and 46 // GPI (where y axis goes upwards) coordinate spaces when dealing with regions 47 // we use the following technique: when a GPI resource is allocated for a Qt 48 // region, we simply change the sign of all y coordinates to quickly flip it 49 // top to bottom in a manner that doesn't depend on the target device height. 50 // All we have to do to apply the created GPI region to a particular GPI device 51 // is to align its y axis to the top of the device (i.e. offset the region 52 // up by the height of the device), and unalign it afterwards to bring it back 53 // to the coordinate space of other device-independent (unaligned) regions. 54 // To optimize this, we remember (in data->hgt) the last height value used to 55 // align the region, and align it again only if the target device height 56 // changes. Zero height indicates a device-independent target (such as other 57 // unaligned Qt region). 58 // 59 // The handle() function, used for external access to the region, takes an 60 // argument that must be always set to the height of the target device to 61 // guarantee the correct coordinate space alignment. 62 63 #if defined(Q_CC_GNU) && !defined(USE_OS2_TOOLKIT_HEADERS) 64 65 // Innotek GCC lacks some API functions in its version of OS/2 Toolkit headers 66 67 extern "C" HRGN APIENTRY GpiCreateEllipticRegion( HPS hps, 68 PRECTL prclRect ); 69 70 extern "C" HRGN APIENTRY GpiCreatePolygonRegion( HPS hps, 71 ULONG ulCount, 72 PPOLYGON paplgn, 73 ULONG flOptions ); 74 #endif 51 75 52 76 QRegion::QRegion() … … 55 79 Q_CHECK_PTR( data ); 56 80 data->rgn = 0; 81 data->hgt = 0; 57 82 data->is_null = TRUE; 58 83 } … … 63 88 Q_CHECK_PTR( data ); 64 89 data->rgn = 0; 90 data->hgt = 0; 65 91 data->is_null = is_null; 66 92 } 67 93 68 QRegion::QRegion( const QRect &r, RegionTypet )94 QRegion::QRegion( HRGN hrgn, int target_height ) 69 95 { 70 96 data = new QRegionData; 71 97 Q_CHECK_PTR( data ); 98 data->rgn = hrgn; 99 data->hgt = target_height; 100 data->is_null = FALSE; 101 } 102 103 QRegion::QRegion( const QRect &r, RegionType t ) 104 { 105 data = new QRegionData; 106 Q_CHECK_PTR( data ); 107 data->hgt = 0; 72 108 data->is_null = FALSE; 73 109 if ( r.isEmpty() ) { … … 79 115 data->rgn = GpiCreateRegion( hps, 1, &rcl ); 80 116 } else if ( t == Ellipse ) { // elliptic region 81 //@@TODO (dmik): create elliptic regions using GpiCreateEllipticRegion() later. 82 // now simply create it as rectangular. 83 RECTL rcl = { r.left(), -(r.bottom()+1), r.right()+1, -r.top() }; 84 data->rgn = GpiCreateRegion( hps, 1, &rcl ); 117 // if the width or height of the ellipse is odd, GPI always 118 // converts it to a nearest even value, which is obviously stupid 119 // (see also QPainter::drawArcInternal()). So, we don't use 120 // GpiCreateEllipticRegion(), but create an array of points to 121 // call GpiCreatePolygonRegion() instead. 122 QPointArray a; 123 a.makeArc( r.x(), r.y(), r.width(), r.height(), 0, 360 * 16 ); 124 for ( uint i = 0; i < a.size(); ++ i ) 125 a[i].ry() = -(a[i].y() + 1); 126 // GpiCreatePolygonRegion() is bogus and always starts a poligon from 127 // the current position. Make the last point the current one and reduce 128 // the number of points by one. 129 GpiMove( hps, (PPOINTL) &a[ a.size() - 1 ] ); 130 POLYGON poly = { a.size() - 1, (PPOINTL) a.data() }; 131 data->rgn = GpiCreatePolygonRegion( hps, 1, &poly, POLYGON_ALTERNATE ); 85 132 } 86 133 } … … 91 138 data = new QRegionData; 92 139 Q_CHECK_PTR( data ); 140 data->hgt = 0; 93 141 data->is_null = FALSE; 94 142 QRect r = a.boundingRect(); … … 96 144 data->rgn = 0; 97 145 } else { 98 //@@TODO (dmik): create poligonal regions using GpiCreatePolygonRegion() later. 99 // now simply create as bounding rectangle. 100 RECTL rcl = { r.left(), -(r.bottom()+1), r.right()+1, -r.top() }; 101 data->rgn = GpiCreateRegion( qt_display_ps(), 1, &rcl ); 146 HPS hps = qt_display_ps(); 147 POINTL *pts = new POINTL[ a.size() ]; 148 for ( uint i = 0; i < a.size(); ++ i ) { 149 pts[i].x = a[i].x(); 150 pts[i].y = - (a[i].y() + 1); 151 } 152 // GpiCreatePolygonRegion() is bogus and always starts a poligon from 153 // the current position. Make the last point the current one and reduce 154 // the number of points by one. 155 GpiMove( hps, &pts[ a.size() - 1 ] ); 156 POLYGON poly = { a.size() - 1, pts }; 157 ULONG opts = winding ? POLYGON_WINDING : POLYGON_ALTERNATE; 158 data->rgn = GpiCreatePolygonRegion( hps, 1, &poly, opts ); 159 delete[] pts; 102 160 } 103 161 } … … 192 250 data = new QRegionData; 193 251 Q_CHECK_PTR( data ); 252 data->hgt = 0; 194 253 data->is_null = FALSE; 195 254 if ( bm.isNull() ) … … 225 284 { 226 285 QRegion r ( data->is_null ); 286 r.data->hgt = 0; 227 287 if ( !data->is_null && data->rgn ) { 228 288 HPS hps = qt_display_ps(); 229 289 r.data->rgn = GpiCreateRegion( hps, 0, NULL ); 230 290 GpiCombineRegion( hps, r.data->rgn, data->rgn, NULL, CRGN_COPY ); 291 r.data->hgt = data->hgt; 231 292 } 232 293 return r; … … 252 313 LONG rc = PRGN_OUTSIDE; 253 314 if ( data->rgn ) { 254 POINTL ptl = { p.x(), -(p.y()+1) };315 POINTL ptl = { p.x(), data->hgt - (p.y() + 1) }; 255 316 rc = GpiPtInRegion( qt_display_ps(), data->rgn, &ptl ); 256 317 } … … 262 323 LONG rc = PRGN_OUTSIDE; 263 324 if ( data->rgn ) { 264 RECTL rcl = { r.left(), -(r.bottom()+1), r.right()+1, -r.top() }; 325 RECTL rcl = { r.left(), data->hgt - (r.bottom() + 1), 326 r.right() + 1, data->hgt - r.top() }; 265 327 rc = GpiRectInRegion( qt_display_ps(), data->rgn, &rcl ); 266 328 } … … 318 380 HPS hps = qt_display_ps(); 319 381 result.data->rgn = GpiCreateRegion( hps, 0, NULL ); 320 if ( data->rgn && r.data->rgn ) 321 GpiCombineRegion( hps, result.data->rgn, data->rgn, r.data->rgn, both ); 322 else if ( data->rgn && left != CRGN_NOP ) 323 GpiCombineRegion( hps, result.data->rgn, data->rgn, NULL, left ); 324 else if ( r.data->rgn && right != CRGN_NOP ) 325 GpiCombineRegion( hps, result.data->rgn, r.data->rgn, NULL, right ); 382 LONG rc = RGN_NULL; 383 if ( data->rgn && r.data->rgn ) { 384 updateHandle( r.data->hgt ); // bring to the same coordinate space 385 rc = GpiCombineRegion( hps, result.data->rgn, data->rgn, r.data->rgn, both ); 386 result.data->hgt = r.data->hgt; 387 } else if ( data->rgn && left != CRGN_NOP ) { 388 rc = GpiCombineRegion( hps, result.data->rgn, data->rgn, 0, left ); 389 result.data->hgt = data->hgt; 390 } else if ( r.data->rgn && right != CRGN_NOP ) { 391 rc = GpiCombineRegion( hps, result.data->rgn, r.data->rgn, 0, right ); 392 result.data->hgt = r.data->hgt; 393 } 394 if ( rc == RGN_NULL || rc == RGN_ERROR ) { 395 GpiDestroyRegion( hps, result.data->rgn ); 396 result.data->rgn = result.data->hgt = 0; 397 } 326 398 return result; 327 399 } … … 354 426 if ( data->rgn ) 355 427 rc = GpiQueryRegionBox( qt_display_ps(), data->rgn, &rcl ); 356 if ( rc == RGN_NULL )428 if ( rc == RGN_NULL || rc == RGN_ERROR ) 357 429 return QRect(0,0,0,0); 358 430 else 359 return QRect(rcl.xLeft, -rcl.yTop, rcl.xRight-rcl.xLeft, rcl.yTop-rcl.yBottom ); 431 return QRect( rcl.xLeft, data->hgt - rcl.yTop, 432 rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom ); 360 433 } 361 434 … … 382 455 PRECTL r = rcls; 383 456 for ( int i=0; i<(int)a.size(); i++ ) { 384 a[i].setRect( r->xLeft, -r->yTop, r->xRight-r->xLeft, r->yTop-r->yBottom ); 457 a[i].setRect( r->xLeft, data->hgt - r->yTop, 458 r->xRight - r->xLeft, r->yTop - r->yBottom ); 385 459 r++; 386 460 } … … 407 481 if ( (is_empty ^ r_is_empty ) ) // one is empty, not both 408 482 return FALSE; 409 return is_empty ? 410 TRUE : // both empty 411 GpiEqualRegion( qt_display_ps(), data->rgn, r.data->rgn ) == EQRGN_EQUAL; 412 } 413 414 void QRegion::update() const 415 { 416 // lazy initialization. this method should be called only from handle() 417 data->rgn = GpiCreateRegion( qt_display_ps(), 0, NULL ); 418 } 483 if ( is_empty ) // both empty 484 return TRUE; 485 updateHandle( r.data->hgt ); // bring to the same coordinate space 486 return 487 GpiEqualRegion( qt_display_ps(), data->rgn, r.data->rgn ) == EQRGN_EQUAL; 488 } 489 490 /*! 491 * \internal 492 * Updates the region handle so that it is suitable for selection to 493 * a device with the given \a height. 494 */ 495 void QRegion::updateHandle( int target_height ) const 496 { 497 QRegion *that = const_cast< QRegion *>( this ); // we're const here 498 if ( !data->rgn ) { 499 // a handle of a null region is requested, allocate an empty region 500 that->data->rgn = GpiCreateRegion( qt_display_ps(), 0, NULL ); 501 that->data->hgt = target_height; 502 } else if ( data->hgt != target_height ) { 503 // align region y axis to the top of the device 504 POINTL ptl = { 0, target_height - data->hgt }; 505 GpiOffsetRegion( qt_display_ps(), data->rgn, &ptl ); 506 that->data->hgt = target_height; 507 } 508 }
Note:
See TracChangeset
for help on using the changeset viewer.