Changeset 74
- Timestamp:
- Mar 26, 2006, 4:09:02 PM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/canvas/qcanvas.cpp
r73 r74 49 49 #include <stdlib.h> 50 50 51 //#define QT_NO_CANVAS_ROUNDING_FIX 51 // QT_NO_CANVAS_ROUNDING_FIX macro encloses some hacks to QCanvas intended 52 // to get rid of artefacts and distortions caused by rounding errors. These 53 // hacks give much better results when the canvas is scaled, sheared or 54 // rotated in the canvas view; however they are just quick patches and not 55 // perfect -- there are still some artefacts possible in rare cases. As far 56 // as I understand, there is a general problem in the QCanvas design: it 57 // operates on integers (instead of doubles) when doing series of direct and 58 // inverse transformations in a row, that results in a big inaccuracy (more 59 // than one pixel in some cases). 60 // 61 // So far, this fix is tested on OS/2 only, so it is disabled for other 62 // platforms. 63 64 #if !defined(Q_WS_PM) 65 #define QT_NO_CANVAS_ROUNDING_FIX 66 #endif 52 67 53 68 #if !defined(QT_NO_TRANSFORMATIONS) && !defined(QT_NO_CANVAS_ROUNDING_FIX) … … 193 208 } 194 209 195 /*!196 * \internal197 *198 * Similar to mapRectMax, but with the opposite meaning. Tries to return199 * a region that is completely inside the given rectangle after transformation.200 * \a br is the target bounding rectangle (to minimize calculations).201 *202 * Using this function to clip out areas of the canvas view not covered by the203 * canvas eliminates garbage at canvas edges that can be well seen when the204 * canvas is rotated in the view.205 */206 static207 QRegion mapRectMin( const QWMatrix &m, const QRect &r, const QRect &br )208 {209 QRegion rgn;210 211 if ( m.isIdentity() ) {212 rgn = QRegion( r );213 return rgn;214 }215 216 if ( m.m12() == 0.0 && m.m21() == 0.0 ) {217 QRect rect = r;218 // make bottom right exclusive219 ++ rect.rBottom();220 ++ rect.rRight();221 double x1, y1, x2, y2;222 // no shear or rotation, map two coords223 m.map( rect.left(), rect.top(), &x1, &y1 );224 m.map( rect.right(), rect.bottom(), &x2, &y2 );225 // get integers (partially covered points are excluded)226 x1 = ceil( x1 );227 y1 = ceil( y1 );228 x2 = floor( x2 );229 y2 = floor( y2 );230 // compose the result231 rect.setCoords( int( x1 ), int( y1 ), int( x2 ), int( y2 ) );232 // make bottom right inclusive again233 -- rect.rBottom();234 -- rect.rRight();235 rgn = QRegion( rect );236 } else {237 // make the rectangle smaller to compensate for differences in238 // line drawing routines of the underlying OS (when defining regions239 // from polygons) and by Qt tansformations (when transforming images240 // or when determining invalid chunks)241 QPointArray pa( r );242 pa = m.map( pa );243 rgn = QRegion( pa );244 // limit to the bounding rect (expanded to compensate shifts)245 QRect rect = br;246 rect.addCoords( -1, 0, 1, 0 );247 rgn &= QRegion( rect );248 // create a copy of the region and shift each towards other by 1 pixel249 // to compensate for (clip out) differences in line drawing routines of250 // the underlying OS (when defining regions from polygons) and in Qt251 // tansformation routines (when transforming images or when determining252 // invalid chunks)253 QRegion rgn2 = rgn;254 rgn.translate( 1, 0 );255 rgn2.translate( -1, 0 );256 // take an intersection257 rgn &= rgn2;258 }259 260 return rgn;261 }262 263 210 #endif 264 211 … … 1226 1173 QRect ivr = vr; 1227 1174 if ( wm.m12() != 0.0 || wm.m21() != 0.0 ) { 1228 // compensate for rounding errors happeningon the path1175 // Compensate for rounding errors happening somewhere on the path 1229 1176 // update() -> drawViewArea() after many transformations (can be seen 1230 // when moving items in a canvas view that makes the canvas smaller1177 // when moving items in a canvas view that scales the canvas down 1231 1178 // and rotates it to ~270 degress clockwise) 1232 1179 ivr.addCoords( -1, -1, 1, 1 ); … … 1248 1195 1249 1196 #ifndef QT_NO_TRANSFORMATIONS 1250 #if !defined(QT_NO_CANVAS_ROUNDING_FIX)1251 QRect cvr = vr; cvr.moveBy(tl.x(),tl.y());1252 QRegion ra = mapRectMin( wm * twm, all, cvr );1253 #else1254 1197 #if !defined(Q_WS_PM) 1255 1198 // For translation-only transformation, it is safe to include the right … … 1267 1210 QPointArray a( all ); 1268 1211 #endif 1212 #if !defined(QT_NO_CANVAS_ROUNDING_FIX) 1213 QWMatrix::TransformationMode oldMode = QWMatrix::transformationMode(); 1214 QWMatrix::setTransformationMode( QWMatrix::Areas ); 1215 #endif 1269 1216 a = (wm*twm).map(a); 1217 #if !defined(QT_NO_CANVAS_ROUNDING_FIX) 1218 QWMatrix::setTransformationMode( oldMode ); 1270 1219 #endif 1271 #else 1220 #else // QT_NO_TRANSFORMATIONS 1272 1221 #if !defined(Q_WS_PM) 1273 1222 QPointArray a( QRect(all.x(),all.y(),all.width()+1,all.height()+1) ); … … 1277 1226 #endif 1278 1227 if ( view->viewport()->backgroundMode() == NoBackground ) { 1279 #if !defined(QT_NO_CANVAS_ROUNDING_FIX)1280 p->setClipRegion( QRegion( cvr ) - ra );1281 #else1282 1228 QRect cvr = vr; cvr.moveBy(tl.x(),tl.y()); 1283 1229 p->setClipRegion(QRegion(cvr)-QRegion(a)); 1284 #endif1285 1230 p->fillRect(vr,view->viewport()->palette() 1286 1231 .brush(QPalette::Active,QColorGroup::Background)); 1287 1232 } 1288 #if !defined(QT_NO_CANVAS_ROUNDING_FIX)1289 p->setClipRegion( ra );1290 #else1291 1233 p->setClipRegion(a); 1292 #endif1293 1234 } 1294 1235 … … 1364 1305 p.translate(tl.x(),tl.y()); 1365 1306 #if !defined(QT_NO_CANVAS_ROUNDING_FIX) 1366 drawViewArea( view, &p, mapRectMax( wm, r ), dblbuf ); 1307 QRect vr = mapRectMax( wm, r ); 1308 if ( wm.m12() != 0.0 || wm.m21() != 0.0 ) { 1309 // Compensate for rounding errors happening sometimes 1310 // after two direct and inverse transformations 1311 vr.addCoords( 0, 0, 1, 1 ); 1312 } 1313 drawViewArea( view, &p, vr, dblbuf ); 1367 1314 #else 1368 1315 drawViewArea( view, &p, wm.map(r), dblbuf ); … … 1614 1561 allvisible.sort(); 1615 1562 1563 #if !defined(QT_NO_CANVAS_ROUNDING_FIX) 1564 QRect safeArea = area; 1565 if (p && !p->worldMatrix().isIdentity()) { 1566 // Increase bounds that lay on the edges to get rid of drawing artefacts 1567 // caused by differeces in regions defined using 4 points and rectangles 1568 // drawn under the non-identity matrix 1569 if ( area.x() == 0 ) safeArea.rLeft() -= 2; 1570 if ( area.y() == 0 ) safeArea.rTop() -= 2; 1571 if ( area.right() == width() - 1 ) safeArea.rRight() += 2; 1572 if ( area.bottom() == height() - 1 ) safeArea.rBottom() += 2; 1573 } 1574 1575 // Force the transformation mode to Areas. W/o this, drawBackground() and 1576 // drawForeground() will not fill the canvas correctly when scaling up 1577 // takes place. 1578 QWMatrix::TransformationMode oldMode = QWMatrix::transformationMode(); 1579 QWMatrix::setTransformationMode( QWMatrix::Areas ); 1580 #endif 1581 1616 1582 if ( double_buffer ) 1617 1583 ensureOffScrSize( area.width(), area.height() ); … … 1622 1588 painter.translate(-area.x(),-area.y()); 1623 1589 if ( p ) { 1590 #if !defined(QT_NO_CANVAS_ROUNDING_FIX) 1591 QRect r = safeArea; 1592 r.moveBy (-area.x(), -area.y()); 1593 painter.setClipRect(r); 1594 #else 1624 1595 painter.setClipRect(QRect(0,0,area.width(),area.height())); 1596 #endif 1625 1597 } else { 1626 1598 painter.setClipRegion(rgn); 1627 1599 } 1600 #if !defined(QT_NO_CANVAS_ROUNDING_FIX) 1601 drawBackground(painter,safeArea); 1602 #else 1628 1603 drawBackground(painter,area); 1604 #endif 1629 1605 allvisible.drawUnique(painter); 1606 #if !defined(QT_NO_CANVAS_ROUNDING_FIX) 1607 drawForeground(painter,safeArea); 1608 #else 1630 1609 drawForeground(painter,area); 1610 #endif 1631 1611 painter.end(); 1632 1612 if ( p ) { 1633 1613 p->drawPixmap( area.x(), area.y(), offscr, 1634 1614 0, 0, area.width(), area.height() ); 1635 return;1636 1615 } 1637 1616 } else if ( p ) { 1617 #if !defined(QT_NO_CANVAS_ROUNDING_FIX) 1618 drawBackground(*p,safeArea); 1619 #else 1638 1620 drawBackground(*p,area); 1621 #endif 1639 1622 allvisible.drawUnique(*p); 1623 #if !defined(QT_NO_CANVAS_ROUNDING_FIX) 1624 drawForeground(*p,safeArea); 1625 #else 1640 1626 drawForeground(*p,area); 1641 return; 1642 } 1643 1627 #endif 1628 } 1629 1630 if ( p ) 1631 return; 1632 1633 #if !defined(QT_NO_CANVAS_ROUNDING_FIX) 1634 QWMatrix::setTransformationMode( oldMode ); 1635 #endif 1636 1644 1637 QPoint trtr; // keeps track of total translation of rgn 1645 1638
Note:
See TracChangeset
for help on using the changeset viewer.