Changeset 561 for trunk/src/gui/painting/qpainter.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/gui/painting/qpainter.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 76 76 #define QPaintEngine_OpaqueBackground 0x40000000 77 77 78 // use the same rounding as in qrasterizer.cpp (6 bit fixed point)79 static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;80 81 78 // #define QT_DEBUG_DRAW 82 79 #ifdef QT_DEBUG_DRAW … … 166 163 { 167 164 Q_ASSERT(extended); 165 if (extended->flags() & QPaintEngineEx::DoNotEmulate) 166 return; 167 168 168 bool doEmulation = false; 169 169 if (state->bgMode == Qt::OpaqueMode) … … 185 185 extended->setState(state); 186 186 } 187 } else if (emulationEngine && emulationEngine != extended) {187 } else if (emulationEngine == extended) { 188 188 extended = emulationEngine->real_engine; 189 189 } … … 260 260 sp->d_ptr->d_ptrs_size = 4; 261 261 sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *)); 262 Q_CHECK_PTR(sp->d_ptr->d_ptrs); 262 263 } else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) { 263 264 // However, to support corner cases we grow the array dynamically if needed. 264 265 sp->d_ptr->d_ptrs_size <<= 1; 265 266 const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *); 266 sp->d_ptr->d_ptrs = (QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize); 267 } 268 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr; 269 q->d_ptr = sp->d_ptr; 267 sp->d_ptr->d_ptrs = q_check_ptr((QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize)); 268 } 269 sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data(); 270 q->d_ptr.take(); 271 q->d_ptr.reset(sp->d_ptr.data()); 270 272 271 273 Q_ASSERT(q->d_ptr->state); … … 282 284 283 285 // Update matrix. 284 if (q->d_ptr->state->WxF) 285 q->d_ptr->state->worldMatrix.translate(-offset.x(), -offset.y()); 286 else 287 q->d_ptr->state->redirection_offset = offset; 286 if (q->d_ptr->state->WxF) { 287 q->d_ptr->state->redirectionMatrix = q->d_ptr->state->matrix; 288 q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y()); 289 q->d_ptr->state->worldMatrix = QTransform(); 290 q->d_ptr->state->WxF = false; 291 } else { 292 q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y()); 293 } 288 294 q->d_ptr->updateMatrix(); 289 295 … … 316 322 d_ptrs[refcount - 1] = 0; 317 323 q->restore(); 318 q->d_ptr = original; 324 q->d_ptr.take(); 325 q->d_ptr.reset(original); 319 326 320 327 if (emulationEngine) { … … 411 418 QTransform old_invMatrix = invMatrix; 412 419 txinv = true; 413 invMatrix = QTransform() .translate(-state->redirection_offset.x(), -state->redirection_offset.y());420 invMatrix = QTransform(); 414 421 QPainterPath clipPath = q->clipPath(); 415 422 QRectF r = clipPath.boundingRect().intersected(absPathRect); … … 469 476 470 477 q->save(); 471 q->resetMatrix(); 478 state->matrix = QTransform(); 479 state->dirtyFlags |= QPaintEngine::DirtyTransform; 472 480 updateState(state); 473 481 engine->drawImage(absPathRect, … … 635 643 636 644 txinv = false; // no inverted matrix 637 if (!state->redirection_offset.isNull()) { 638 // We want to translate in dev space so we do the adding of the redirection 639 // offset manually. 640 if (state->matrix.isAffine()) { 641 state->matrix = QTransform(state->matrix.m11(), state->matrix.m12(), 642 state->matrix.m21(), state->matrix.m22(), 643 state->matrix.dx()-state->redirection_offset.x(), 644 state->matrix.dy()-state->redirection_offset.y()); 645 } else { 646 QTransform temp; 647 temp.translate(-state->redirection_offset.x(), -state->redirection_offset.y()); 648 state->matrix *= temp; 649 } 650 } 645 state->matrix *= state->redirectionMatrix; 651 646 if (extended) 652 647 extended->transformChanged(); … … 663 658 Q_ASSERT(txinv == false); 664 659 txinv = true; // creating inverted matrix 665 QTransform m; 666 667 if (state->VxF) 668 m = viewTransform(); 669 670 if (state->WxF) { 671 if (state->VxF) 672 m = state->worldMatrix * m; 673 else 674 m = state->worldMatrix; 675 } 676 invMatrix = m.inverted(); // invert matrix 660 invMatrix = state->matrix.inverted(); 677 661 } 678 662 … … 945 929 other paint devices. 946 930 947 \ingroup multimedia948 \mainclass 931 \ingroup painting 932 949 933 \reentrant 950 934 … … 1026 1010 the origin of widget's background. 1027 1011 1028 \o viewport(), window(), world Matrix() make up the painter's coordinate1012 \o viewport(), window(), worldTransform() make up the painter's coordinate 1029 1013 transformation system. For more information, see the \l 1030 1014 {Coordinate Transformations} section and the \l {The Coordinate … … 1037 1021 painter when drawing text. 1038 1022 1039 \o matrixEnabled() tells whether world transformation is enabled.1023 \o worldMatrixEnabled() tells whether world transformation is enabled. 1040 1024 1041 1025 \o viewTransformEnabled() tells whether view transformation is … … 1233 1217 1234 1218 All the tranformation operations operate on the transformation 1235 world Matrix(). A matrix transforms a point in the plane to another1219 worldTransform(). A matrix transforms a point in the plane to another 1236 1220 point. For more information about the transformation matrix, see 1237 the \l {The Coordinate System} and Q Matrixdocumentation.1238 1239 The setWorld Matrix() function can replace or add to the currently1240 set world Matrix(). The resetMatrix() function resets any1221 the \l {The Coordinate System} and QTransform documentation. 1222 1223 The setWorldTransform() function can replace or add to the currently 1224 set worldTransform(). The resetTransform() function resets any 1241 1225 transformations that were made using translate(), scale(), 1242 shear(), rotate(), setWorld Matrix(), setViewport() and setWindow()1243 functions. The device Matrix() returns the matrix that transforms1226 shear(), rotate(), setWorldTransform(), setViewport() and setWindow() 1227 functions. The deviceTransform() returns the matrix that transforms 1244 1228 from logical coordinates to device coordinates of the platform 1245 1229 dependent paint device. The latter function is only needed when … … 1250 1234 coordinates which then are converted into the physical coordinates 1251 1235 of the paint device. The mapping of the logical coordinates to the 1252 physical coordinates are handled by QPainter's combined Matrix(), a1253 combination of viewport() and window() and world Matrix().The1236 physical coordinates are handled by QPainter's combinedTransform(), a 1237 combination of viewport() and window() and worldTransform(). The 1254 1238 viewport() represents the physical coordinates specifying an 1255 1239 arbitrary rectangle, the window() describes the same rectangle in 1256 logical coordinates, and the world Matrix() is identical with the1240 logical coordinates, and the worldTransform() is identical with the 1257 1241 transformation matrix. 1258 1242 … … 1334 1318 polygons instead. 1335 1319 1336 \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example} 1320 \section1 Performance 1321 1322 QPainter is a rich framework that allows developers to do a great 1323 variety of graphical operations, such as gradients, composition 1324 modes and vector graphics. And QPainter can do this across a 1325 variety of different hardware and software stacks. Naturally the 1326 underlying combination of hardware and software has some 1327 implications for performance, and ensuring that every single 1328 operation is fast in combination with all the various combinations 1329 of composition modes, brushes, clipping, transformation, etc, is 1330 close to an impossible task because of the number of 1331 permutations. As a compromise we have selected a subset of the 1332 QPainter API and backends, were performance is guaranteed to be as 1333 good as we can sensibly get it for the given combination of 1334 hardware and software. 1335 1336 The backends we focus on as high-performance engines are: 1337 1338 \list 1339 1340 \o Raster - This backend implements all rendering in pure software 1341 and is always used to render into QImages. For optimal performance 1342 only use the format types QImage::Format_ARGB32_Premultiplied, 1343 QImage::Format_RGB32 or QImage::Format_RGB16. Any other format, 1344 including QImage::Format_ARGB32, has significantly worse 1345 performance. This engine is also used by default on Windows and on 1346 QWS. It can be used as default graphics system on any 1347 OS/hardware/software combination by passing \c {-graphicssystem 1348 raster} on the command line 1349 1350 \o OpenGL 2.0 (ES) - This backend is the primary backend for 1351 hardware accelerated graphics. It can be run on desktop machines 1352 and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0 1353 specification. This includes most graphics chips produced in the 1354 last couple of years. The engine can be enabled by using QPainter 1355 onto a QGLWidget or by passing \c {-graphicssystem opengl} on the 1356 command line when the underlying system supports it. 1357 1358 \o OpenVG - This backend implements the Khronos standard for 2D 1359 and Vector Graphics. It is primarily for embedded devices with 1360 hardware support for OpenVG. The engine can be enabled by 1361 passing \c {-graphicssystem openvg} on the command line when 1362 the underlying system supports it. 1363 1364 \endlist 1365 1366 These operations are: 1367 1368 \list 1369 1370 \o Simple transformations, meaning translation and scaling, pluss 1371 0, 90, 180, 270 degree rotations. 1372 1373 \o \c drawPixmap() in combination with simple transformations and 1374 opacity with non-smooth transformation mode 1375 (\c QPainter::SmoothPixmapTransform not enabled as a render hint). 1376 1377 \o Text drawing with regular font sizes with simple 1378 transformations with solid colors using no or 8-bit antialiasing. 1379 1380 \o Rectangle fills with solid color, two-color linear gradients 1381 and simple transforms. 1382 1383 \o Rectangular clipping with simple transformations and intersect 1384 clip. 1385 1386 \o Composition Modes \c QPainter::CompositionMode_Source and 1387 QPainter::CompositionMode_SourceOver 1388 1389 \o Rounded rectangle filling using solid color and two-color 1390 linear gradients fills. 1391 1392 \o 3x3 patched pixmaps, via qDrawBorderPixmap. 1393 1394 \endlist 1395 1396 This list gives an indication of which features to safely use in 1397 an application where performance is critical. For certain setups, 1398 other operations may be fast too, but before making extensive use 1399 of them, it is recommended to benchmark and verify them on the 1400 system where the software will run in the end. There are also 1401 cases where expensive operations are ok to use, for instance when 1402 the result is cached in a QPixmap. 1403 1404 \sa QPaintDevice, QPaintEngine, {QtSvg Module}, {Basic Drawing Example}, 1405 {Drawing Utility Functions} 1337 1406 */ 1338 1407 … … 1375 1444 1376 1445 QPainter::QPainter() 1377 { 1378 d_ptr = new QPainterPrivate(this); 1446 : d_ptr(new QPainterPrivate(this)) 1447 { 1379 1448 } 1380 1449 … … 1408 1477 Q_ASSERT(pd != 0); 1409 1478 if (!QPainterPrivate::attachPainterPrivate(this, pd)) { 1410 d_ptr = new QPainterPrivate(this);1479 d_ptr.reset(new QPainterPrivate(this)); 1411 1480 begin(pd); 1412 1481 } … … 1420 1489 { 1421 1490 d_ptr->inDestructor = true; 1422 if (isActive()) 1423 end(); 1424 else if (d_ptr->refcount > 1) 1425 d_ptr->detachPainterPrivate(this); 1426 1491 QT_TRY { 1492 if (isActive()) 1493 end(); 1494 else if (d_ptr->refcount > 1) 1495 d_ptr->detachPainterPrivate(this); 1496 } QT_CATCH(...) { 1497 // don't throw anything in the destructor. 1498 } 1427 1499 if (d_ptr) { 1428 1500 // Make sure we haven't messed things up. … … 1432 1504 if (d_ptr->d_ptrs) 1433 1505 free(d_ptr->d_ptrs); 1434 delete d_ptr;1435 1506 } 1436 1507 } … … 1485 1556 d->state->deviceFont = QFont(widget->font(), const_cast<QWidget*> (widget)); 1486 1557 d->state->font = d->state->deviceFont; 1487 if (d->engine) { 1558 if (d->extended) { 1559 d->extended->penChanged(); 1560 } else if (d->engine) { 1488 1561 d->engine->setDirty(QPaintEngine::DirtyPen); 1489 1562 d->engine->setDirty(QPaintEngine::DirtyBrush); … … 1571 1644 for (int i=0; i<d->state->clipInfo.size(); ++i) { 1572 1645 const QPainterClipInfo &info = d->state->clipInfo.at(i); 1573 tmp->matrix.setMatrix(info.matrix.m11(), info.matrix.m12(), info.matrix.m13(), 1574 info.matrix.m21(), info.matrix.m22(), info.matrix.m23(), 1575 info.matrix.dx() - d->state->redirection_offset.x(), 1576 info.matrix.dy() - d->state->redirection_offset.y(), info.matrix.m33()); 1646 tmp->matrix = info.matrix; 1647 tmp->matrix *= d->state->redirectionMatrix; 1577 1648 tmp->clipOperation = info.operation; 1578 1649 if (info.clipType == QPainterClipInfo::RectClip) { … … 1622 1693 time. 1623 1694 1695 \warning Painting on a QImage with the format 1696 QImage::Format_Indexed8 is not supported. 1697 1624 1698 \sa end(), QPainter() 1625 1699 */ 1700 1701 static inline void qt_cleanup_painter_state(QPainterPrivate *d) 1702 { 1703 d->states.clear(); 1704 delete d->state; 1705 d->state = 0; 1706 d->engine = 0; 1707 d->device = 0; 1708 } 1626 1709 1627 1710 bool QPainter::begin(QPaintDevice *pd) … … 1670 1753 #endif 1671 1754 1672 1673 d->device = pd;1674 1755 if (pd->devType() == QInternal::Pixmap) 1675 1756 static_cast<QPixmap *>(pd)->detach(); … … 1678 1759 1679 1760 d->engine = pd->paintEngine(); 1680 d->extended = d->engine && d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0; 1761 1762 if (!d->engine) { 1763 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType()); 1764 return false; 1765 } 1766 1767 d->device = pd; 1768 1769 d->extended = d->engine->isExtended() ? static_cast<QPaintEngineEx *>(d->engine) : 0; 1681 1770 if (d->emulationEngine) 1682 1771 d->emulationEngine->real_engine = d->extended; … … 1688 1777 d->states.push_back(d->state); 1689 1778 1690 d->state->redirection _offset = redirectionOffset;1779 d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y()); 1691 1780 d->state->brushOrigin = QPointF(); 1692 1693 if (!d->engine) {1694 qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType());1695 return true;1696 }1697 1781 1698 1782 // Slip a painter state into the engine before we do any other operations … … 1714 1798 qWarning("QPainter::begin: Widget painting can only begin as a " 1715 1799 "result of a paintEvent"); 1716 d->engine = 0; 1717 d->device = 0; 1800 qt_cleanup_painter_state(d); 1718 1801 return false; 1719 1802 } … … 1722 1805 if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId() 1723 1806 && widget->testAttribute(Qt::WA_WState_Created)) { 1724 d->state->redirection_offset -= widget->mapTo(widget->nativeParentWidget(), QPoint()); 1807 const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint()); 1808 d->state->redirectionMatrix.translate(offset.x(), offset.y()); 1725 1809 } 1726 1810 break; … … 1732 1816 if (pm->isNull()) { 1733 1817 qWarning("QPainter::begin: Cannot paint on a null pixmap"); 1734 d->engine = 0; 1735 d->device = 0; 1818 qt_cleanup_painter_state(d); 1736 1819 return false; 1737 1820 } … … 1749 1832 if (img->isNull()) { 1750 1833 qWarning("QPainter::begin: Cannot paint on a null image"); 1751 d->engine = 0; 1752 d->device = 0; 1834 qt_cleanup_painter_state(d); 1835 return false; 1836 } else if (img->format() == QImage::Format_Indexed8) { 1837 // Painting on indexed8 images is not supported. 1838 qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format"); 1839 qt_cleanup_painter_state(d); 1753 1840 return false; 1754 1841 } … … 1773 1860 end(); 1774 1861 } else { 1775 d->states.clear(); 1776 delete d->state; 1777 d->state = 0; 1862 qt_cleanup_painter_state(d); 1778 1863 } 1779 d->engine = 0;1780 d->device = 0;1781 1864 return false; 1782 1865 } else { … … 1804 1887 } 1805 1888 1806 d->state->redirection_offset += d->engine->coordinateOffset(); 1889 const QPoint coordinateOffset = d->engine->coordinateOffset(); 1890 d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y()); 1807 1891 1808 1892 Q_ASSERT(d->engine->isActive()); 1809 1893 1810 if (!d->state->redirection _offset.isNull())1894 if (!d->state->redirectionMatrix.isIdentity()) 1811 1895 d->updateMatrix(); 1812 1896 … … 1840 1924 if (!d->engine) { 1841 1925 qWarning("QPainter::end: Painter not active, aborted"); 1842 d->states.clear(); 1843 delete d->state; 1844 d->state = 0; 1845 d->device = 0; 1926 qt_cleanup_painter_state(d); 1846 1927 return false; 1847 1928 } … … 1850 1931 d->detachPainterPrivate(this); 1851 1932 return true; 1852 }1853 1854 if (d->states.size() > 1) {1855 qWarning("QPainter::end: Painter ended with %d saved states",1856 d->states.size());1857 1933 } 1858 1934 … … 1870 1946 } 1871 1947 1948 if (d->states.size() > 1) { 1949 qWarning("QPainter::end: Painter ended with %d saved states", 1950 d->states.size()); 1951 } 1952 1872 1953 if (d->engine->autoDestruct()) { 1873 1954 delete d->engine; 1874 1955 } 1875 1876 d->engine = 0;1877 1956 1878 1957 if (d->emulationEngine) { … … 1885 1964 } 1886 1965 1887 d->states.clear(); 1888 delete d->state; 1889 d->state = 0; 1890 1891 d->device = 0; 1966 qt_cleanup_painter_state(d); 1967 1892 1968 return ended; 1893 1969 } … … 1906 1982 } 1907 1983 1984 /*! 1985 \since 4.6 1986 1987 Flushes the painting pipeline and prepares for the user issuing 1988 commands directly to the underlying graphics context. Must be 1989 followed by a call to endNativePainting(). 1990 1991 Here is an example that shows intermixing of painter commands 1992 and raw OpenGL commands: 1993 1994 \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21 1995 1996 \sa endNativePainting() 1997 */ 1998 void QPainter::beginNativePainting() 1999 { 2000 Q_D(QPainter); 2001 if (!d->engine) { 2002 qWarning("QPainter::beginNativePainting: Painter not active"); 2003 return; 2004 } 2005 2006 if (d->extended) 2007 d->extended->beginNativePainting(); 2008 } 2009 2010 /*! 2011 \since 4.6 2012 2013 Restores the painter after manually issuing native painting commands. 2014 Lets the painter restore any native state that it relies on before 2015 calling any other painter commands. 2016 2017 \sa beginNativePainting() 2018 */ 2019 void QPainter::endNativePainting() 2020 { 2021 Q_D(const QPainter); 2022 if (!d->engine) { 2023 qWarning("QPainter::beginNativePainting: Painter not active"); 2024 return; 2025 } 2026 2027 if (d->extended) 2028 d->extended->endNativePainting(); 2029 else 2030 d->engine->syncState(); 2031 } 1908 2032 1909 2033 /*! … … 2015 2139 2016 2140 The brush origin specifies the (0, 0) coordinate of the painter's 2017 brush. This setting only applies to pattern brushes and pixmap 2018 brushes. 2141 brush. 2019 2142 2020 2143 Note that while the brushOrigin() was necessary to adopt the … … 2237 2360 Sets the composition mode to the given \a mode. 2238 2361 2239 \warning You can only set the composition mode for QPainter 2240 objects that operates on a QImage. 2362 \warning Only a QPainter operating on a QImage fully supports all 2363 composition modes. The RasterOp modes are supported for X11 as 2364 described in compositionMode(). 2241 2365 2242 2366 \sa compositionMode() … … 2372 2496 is given in logical coordinates. 2373 2497 2498 \warning QPainter does not store the combined clip explicitly as 2499 this is handled by the underlying QPaintEngine, so the path is 2500 recreated on demand and transformed to the current logical 2501 coordinate system. This is potentially an expensive operation. 2502 2374 2503 \sa setClipRegion(), clipPath(), setClipping() 2375 2504 */ … … 2392 2521 for (int i=0; i<d->state->clipInfo.size(); ++i) { 2393 2522 const QPainterClipInfo &info = d->state->clipInfo.at(i); 2394 QRegion other;2395 2523 switch (info.clipType) { 2396 2524 … … 2445 2573 continue; 2446 2574 } 2447 if (info.operation == Qt::IntersectClip) 2448 region &= QRegion(info.rect) * matrix; 2449 else if (info.operation == Qt::UniteClip) 2575 if (info.operation == Qt::IntersectClip) { 2576 // Use rect intersection if possible. 2577 if (matrix.type() <= QTransform::TxScale) 2578 region &= matrix.mapRect(info.rect); 2579 else 2580 region &= matrix.map(QRegion(info.rect)); 2581 } else if (info.operation == Qt::UniteClip) { 2450 2582 region |= QRegion(info.rect) * matrix; 2451 else if (info.operation == Qt::NoClip) {2583 } else if (info.operation == Qt::NoClip) { 2452 2584 lastWasNothing = true; 2453 2585 region = QRegion(); 2454 } else 2586 } else { 2455 2587 region = QRegion(info.rect) * matrix; 2588 } 2456 2589 break; 2457 2590 } … … 2464 2597 continue; 2465 2598 } 2466 if (info.operation == Qt::IntersectClip) 2467 region &= QRegion(info.rectf.toRect()) * matrix; 2468 else if (info.operation == Qt::UniteClip) 2599 if (info.operation == Qt::IntersectClip) { 2600 // Use rect intersection if possible. 2601 if (matrix.type() <= QTransform::TxScale) 2602 region &= matrix.mapRect(info.rectf.toRect()); 2603 else 2604 region &= matrix.map(QRegion(info.rectf.toRect())); 2605 } else if (info.operation == Qt::UniteClip) { 2469 2606 region |= QRegion(info.rectf.toRect()) * matrix; 2470 else if (info.operation == Qt::NoClip) {2607 } else if (info.operation == Qt::NoClip) { 2471 2608 lastWasNothing = true; 2472 2609 region = QRegion(); 2473 } else 2610 } else { 2474 2611 region = QRegion(info.rectf.toRect()) * matrix; 2612 } 2475 2613 break; 2476 2614 } … … 2486 2624 Returns the currently clip as a path. Note that the clip path is 2487 2625 given in logical coordinates. 2626 2627 \warning QPainter does not store the combined clip explicitly as 2628 this is handled by the underlying QPaintEngine, so the path is 2629 recreated on demand and transformed to the current logical 2630 coordinate system. This is potentially an expensive operation. 2488 2631 2489 2632 \sa setClipPath(), clipRegion(), setClipping() … … 2545 2688 2546 2689 if (d->extended) { 2690 if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip)) 2691 op = Qt::ReplaceClip; 2692 2547 2693 if (!d->engine) { 2548 2694 qWarning("QPainter::setClipRect: Painter not active"); … … 2558 2704 d->state->clipEnabled = true; 2559 2705 d->extended->clip(vp, op); 2560 d->state->clipInfo << QPainterClipInfo(rect, op, combinedTransform()); 2706 if (op == Qt::ReplaceClip || op == Qt::NoClip) 2707 d->state->clipInfo.clear(); 2708 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix); 2561 2709 d->state->clipOperation = op; 2562 2710 return; … … 2598 2746 } 2599 2747 2748 if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip)) 2749 op = Qt::ReplaceClip; 2750 2600 2751 if (d->extended) { 2601 2752 d->state->clipEnabled = true; 2602 2753 d->extended->clip(rect, op); 2603 d->state->clipInfo << QPainterClipInfo(rect, op, combinedTransform()); 2754 if (op == Qt::ReplaceClip || op == Qt::NoClip) 2755 d->state->clipInfo.clear(); 2756 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix); 2604 2757 d->state->clipOperation = op; 2605 2758 return; 2606 2759 } 2607 2608 if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip))2609 op = Qt::ReplaceClip;2610 2760 2611 2761 d->state->clipRegion = rect; … … 2613 2763 if (op == Qt::NoClip || op == Qt::ReplaceClip) 2614 2764 d->state->clipInfo.clear(); 2615 d->state->clipInfo << QPainterClipInfo(rect, op, combinedTransform());2765 d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix); 2616 2766 d->state->clipEnabled = true; 2617 2767 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled; … … 2651 2801 } 2652 2802 2803 if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip)) 2804 op = Qt::ReplaceClip; 2805 2653 2806 if (d->extended) { 2654 2807 d->state->clipEnabled = true; 2655 2808 d->extended->clip(r, op); 2656 d->state->clipInfo << QPainterClipInfo(r, op, combinedTransform()); 2809 if (op == Qt::NoClip || op == Qt::ReplaceClip) 2810 d->state->clipInfo.clear(); 2811 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix); 2657 2812 d->state->clipOperation = op; 2658 2813 return; 2659 2814 } 2660 2661 if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip))2662 op = Qt::ReplaceClip;2663 2815 2664 2816 d->state->clipRegion = r; … … 2666 2818 if (op == Qt::NoClip || op == Qt::ReplaceClip) 2667 2819 d->state->clipInfo.clear(); 2668 d->state->clipInfo << QPainterClipInfo(r, op, combinedTransform());2820 d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix); 2669 2821 d->state->clipEnabled = true; 2670 2822 d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled; … … 2674 2826 /*! 2675 2827 \since 4.2 2828 \obsolete 2676 2829 2677 2830 Sets the transformation matrix to \a matrix and enables transformations. … … 2712 2865 documentation. 2713 2866 2714 \sa worldMatrixEnabled(), QMatrix2867 \sa setWorldTransform(), QTransform 2715 2868 */ 2716 2869 … … 2722 2875 /*! 2723 2876 \since 4.2 2877 \obsolete 2724 2878 2725 2879 Returns the world transformation matrix. … … 2771 2925 /*! 2772 2926 \since 4.2 2927 \obsolete 2773 2928 2774 2929 Returns the transformation matrix combining the current … … 2778 2933 function to preserve the properties of perspective transformations. 2779 2934 2780 \sa setWorld Matrix(), setWindow(), setViewport()2935 \sa setWorldTransform(), setWindow(), setViewport() 2781 2936 */ 2782 2937 QMatrix QPainter::combinedMatrix() const … … 2787 2942 2788 2943 /*! 2944 \obsolete 2945 2789 2946 Returns the matrix that transforms from logical coordinates to 2790 2947 device coordinates of the platform dependent paint device. … … 2814 2971 2815 2972 /*! 2973 \obsolete 2974 2816 2975 Resets any transformations that were made using translate(), scale(), 2817 2976 shear(), rotate(), setWorldMatrix(), setViewport() and … … 2838 2997 matrix is not changed. 2839 2998 2840 \sa worldMatrixEnabled(), world Matrix(), {QPainter#Coordinate2999 \sa worldMatrixEnabled(), worldTransform(), {QPainter#Coordinate 2841 3000 Transformations}{Coordinate Transformations} 2842 3001 */ … … 2867 3026 false. 2868 3027 2869 \sa setWorldMatrixEnabled(), world Matrix(), {The Coordinate System}3028 \sa setWorldMatrixEnabled(), worldTransform(), {The Coordinate System} 2870 3029 */ 2871 3030 … … 2909 3068 Scales the coordinate system by (\a{sx}, \a{sy}). 2910 3069 2911 \sa setWorld Matrix() {QPainter#Coordinate Transformations}{Coordinate3070 \sa setWorldTransform() {QPainter#Coordinate Transformations}{Coordinate 2912 3071 Transformations} 2913 3072 */ … … 2933 3092 Shears the coordinate system by (\a{sh}, \a{sv}). 2934 3093 2935 \sa setWorld Matrix(), {QPainter#Coordinate Transformations}{Coordinate3094 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate 2936 3095 Transformations} 2937 3096 */ … … 2959 3118 Rotates the coordinate system the given \a angle clockwise. 2960 3119 2961 \sa setWorld Matrix(), {QPainter#Coordinate Transformations}{Coordinate3120 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate 2962 3121 Transformations} 2963 3122 */ … … 2984 3143 given \a offset is added to points. 2985 3144 2986 \sa setWorld Matrix(), {QPainter#Coordinate Transformations}{Coordinate3145 \sa setWorldTransform(), {QPainter#Coordinate Transformations}{Coordinate 2987 3146 Transformations} 2988 3147 */ … … 3048 3207 } 3049 3208 3209 if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip)) 3210 op = Qt::ReplaceClip; 3211 3050 3212 if (d->extended) { 3051 3213 d->state->clipEnabled = true; 3052 3214 d->extended->clip(path, op); 3053 d->state->clipInfo << QPainterClipInfo(path, op, combinedTransform()); 3215 if (op == Qt::NoClip || op == Qt::ReplaceClip) 3216 d->state->clipInfo.clear(); 3217 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix); 3054 3218 d->state->clipOperation = op; 3055 3219 return; 3056 3220 } 3057 3058 3059 3060 if (!hasClipping() && (op == Qt::IntersectClip || op == Qt::UniteClip))3061 op = Qt::ReplaceClip;3062 3221 3063 3222 d->state->clipPath = path; … … 3065 3224 if (op == Qt::NoClip || op == Qt::ReplaceClip) 3066 3225 d->state->clipInfo.clear(); 3067 d->state->clipInfo << QPainterClipInfo(path, op, combinedTransform());3226 d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix); 3068 3227 d->state->clipEnabled = true; 3069 3228 d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled; … … 3713 3872 return; 3714 3873 3874 d->state->pen = pen; 3875 3715 3876 if (d->extended) { 3716 d->state->pen = pen;3717 3877 d->checkEmulation(); 3718 3878 d->extended->penChanged(); … … 3720 3880 } 3721 3881 3722 // Do some checks to see if we are the same pen.3723 Qt::PenStyle currentStyle = d->state->pen.style();3724 if (currentStyle == pen.style() && currentStyle != Qt::CustomDashLine) {3725 if (currentStyle == Qt::NoPen ||3726 (d->state->pen.isSolid() && pen.isSolid()3727 && d->state->pen.color() == pen.color()3728 && d->state->pen.widthF() == pen.widthF()3729 && d->state->pen.capStyle() == pen.capStyle()3730 && d->state->pen.joinStyle() == pen.joinStyle()3731 && d->state->pen.isCosmetic() == pen.isCosmetic()))3732 return;3733 }3734 3735 d->state->pen = pen;3736 3882 d->state->dirtyFlags |= QPaintEngine::DirtyPen; 3737 3883 } … … 3816 3962 } 3817 3963 3818 Qt::BrushStyle currentStyle = d->state->brush.style();3819 if (currentStyle == brush.style()) {3820 if (currentStyle == Qt::NoBrush3821 || (currentStyle == Qt::SolidPattern3822 && d->state->brush.color() == brush.color()))3823 return;3824 }3825 3826 3964 d->state->brush = brush; 3827 3965 d->state->dirtyFlags |= QPaintEngine::DirtyBrush; … … 3971 4109 \sa drawRect(), QPen 3972 4110 */ 3973 // FALCON: Should we add a specialized method in QPaintEngineEx?3974 4111 void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode) 3975 4112 { … … 3989 4126 3990 4127 if (d->extended) { 3991 QPainterPath::ElementType types[] = { 3992 QPainterPath::MoveToElement, 3993 QPainterPath::LineToElement, 3994 QPainterPath::CurveToElement, 3995 QPainterPath::CurveToDataElement, 3996 QPainterPath::CurveToDataElement, 3997 QPainterPath::LineToElement, 3998 QPainterPath::CurveToElement, 3999 QPainterPath::CurveToDataElement, 4000 QPainterPath::CurveToDataElement, 4001 QPainterPath::LineToElement, 4002 QPainterPath::CurveToElement, 4003 QPainterPath::CurveToDataElement, 4004 QPainterPath::CurveToDataElement, 4005 QPainterPath::LineToElement, 4006 QPainterPath::CurveToElement, 4007 QPainterPath::CurveToDataElement, 4008 QPainterPath::CurveToDataElement 4009 }; 4010 4011 qreal x1 = rect.left(); 4012 qreal x2 = rect.right(); 4013 qreal y1 = rect.top(); 4014 qreal y2 = rect.bottom(); 4015 4016 if (mode == Qt::RelativeSize) { 4017 xRadius = xRadius * rect.width() / 200.; 4018 yRadius = yRadius * rect.height() / 200.; 4019 } 4020 4021 xRadius = qMin(xRadius, rect.width() / 2); 4022 yRadius = qMin(yRadius, rect.height() / 2); 4023 4024 qreal pts[] = { 4025 x1 + xRadius, y1, // MoveTo 4026 x2 - xRadius, y1, // LineTo 4027 x2 - (1 - KAPPA) * xRadius, y1, // CurveTo 4028 x2, y1 + (1 - KAPPA) * yRadius, 4029 x2, y1 + yRadius, 4030 x2, y2 - yRadius, // LineTo 4031 x2, y2 - (1 - KAPPA) * yRadius, // CurveTo 4032 x2 - (1 - KAPPA) * xRadius, y2, 4033 x2 - xRadius, y2, 4034 x1 + xRadius, y2, // LineTo 4035 x1 + (1 - KAPPA) * xRadius, y2, // CurveTo 4036 x1, y2 - (1 - KAPPA) * yRadius, 4037 x1, y2 - yRadius, 4038 x1, y1 + yRadius, // LineTo 4039 x1, y1 + KAPPA * yRadius, // CurveTo 4040 x1 + (1 - KAPPA) * xRadius, y1, 4041 x1 + xRadius, y1 4042 }; 4043 4044 QVectorPath path(pts, 17, types); 4045 d->extended->draw(path); 4128 d->extended->drawRoundedRect(rect, xRadius, yRadius, mode); 4046 4129 return; 4047 4130 } … … 4085 4168 void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd) 4086 4169 { 4087 #ifdef QT_DEBUG_DRAW 4088 if (qt_show_painter_debug_output) 4089 printf("QPainter::drawRoundRectangle(), [%.2f,%.2f,%.2f,%.2f]\n", r.x(), r.y(), r.width(), r.height()); 4090 #endif 4091 Q_D(QPainter); 4092 4093 if (!d->engine) 4094 return; 4095 4096 if(xRnd <= 0 || yRnd <= 0) { // draw normal rectangle 4097 drawRect(r); 4098 return; 4099 } 4100 4101 QPainterPath path; 4102 path.addRoundRect(r, xRnd, yRnd); 4103 drawPath(path); 4170 drawRoundedRect(r, xRnd, yRnd, Qt::RelativeSize); 4104 4171 } 4105 4172 … … 5122 5189 } 5123 5190 5191 static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m) 5192 { 5193 return m.inverted().map(QPointF(m.map(p).toPoint())); 5194 } 5195 5124 5196 /*! 5125 5197 \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source) … … 5174 5246 int h = pm.height(); 5175 5247 5248 if (w <= 0) 5249 return; 5250 5176 5251 // Emulate opaque background for bitmaps 5177 5252 if (d->state->bgMode == Qt::OpaqueMode && pm.isQBitmap()) { … … 5187 5262 { 5188 5263 save(); 5189 // If there is no scaling or transformation involved we have to make sure we use the5264 // If there is no rotation involved we have to make sure we use the 5190 5265 // antialiased and not the aliased coordinate system by rounding the coordinates. 5191 if (d->state->matrix.type() <= QTransform::TxTranslate) { 5192 x = qRound(x + d->state->matrix.dx()) - d->state->matrix.dx(); 5193 y = qRound(y + d->state->matrix.dy()) - d->state->matrix.dy(); 5266 if (d->state->matrix.type() <= QTransform::TxScale) { 5267 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix); 5268 x = p.x(); 5269 y = p.y(); 5194 5270 } 5195 5271 translate(x, y); … … 5301 5377 { 5302 5378 save(); 5303 // If there is no scaling or transformation involved we have to make sure we use the5379 // If there is no rotation involved we have to make sure we use the 5304 5380 // antialiased and not the aliased coordinate system by rounding the coordinates. 5381 if (d->state->matrix.type() <= QTransform::TxScale) { 5382 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix); 5383 x = p.x(); 5384 y = p.y(); 5385 } 5386 5305 5387 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) { 5306 x = qRound(x + d->state->matrix.dx()) - d->state->matrix.dx();5307 y = qRound(y + d->state->matrix.dy()) - d->state->matrix.dy();5308 5388 sx = qRound(sx); 5309 5389 sy = qRound(sy); … … 5311 5391 sh = qRound(sh); 5312 5392 } 5393 5313 5394 translate(x, y); 5314 5395 scale(w / sw, h / sh); … … 5460 5541 { 5461 5542 save(); 5462 // If there is no scaling or transformation involved we have to make sure we use the5543 // If there is no rotation involved we have to make sure we use the 5463 5544 // antialiased and not the aliased coordinate system by rounding the coordinates. 5464 if (d->state->matrix.type() <= QTransform::TxTranslate) { 5465 x = qRound(x + d->state->matrix.dx()) - d->state->matrix.dx(); 5466 y = qRound(y + d->state->matrix.dy()) - d->state->matrix.dy(); 5545 if (d->state->matrix.type() <= QTransform::TxScale) { 5546 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix); 5547 x = p.x(); 5548 y = p.y(); 5467 5549 } 5468 5550 translate(x, y); … … 5563 5645 { 5564 5646 save(); 5565 // If there is no scaling or transformation involved we have to make sure we use the5647 // If there is no rotation involved we have to make sure we use the 5566 5648 // antialiased and not the aliased coordinate system by rounding the coordinates. 5649 if (d->state->matrix.type() <= QTransform::TxScale) { 5650 const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix); 5651 x = p.x(); 5652 y = p.y(); 5653 } 5654 5567 5655 if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) { 5568 x = qRound(x + d->state->matrix.dx()) - d->state->matrix.dx();5569 y = qRound(y + d->state->matrix.dy()) - d->state->matrix.dy();5570 5656 sx = qRound(sx); 5571 5657 sy = qRound(sy); … … 5659 5745 } 5660 5746 QFixed x = QFixed::fromReal(p.x()); 5661 QFixed ox = x;5662 5747 5663 5748 for (int i = 0; i < nItems; ++i) { … … 5886 5971 */ 5887 5972 5888 /*! \internal 5973 /*! 5974 \fn void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti) 5975 5976 \internal 5977 \since 4.1 5978 5889 5979 Draws the text item \a ti at position \a p. 5890 5980 … … 5899 5989 underlining and strikeout. 5900 5990 */ 5901 static QPainterPath generateWavyPath(qreal minWidth, qreal maxRadius, QPaintDevice *device) 5902 { 5903 extern int qt_defaultDpi(); 5991 5992 static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen) 5993 { 5994 const qreal radiusBase = qMax(qreal(1), maxRadius); 5995 5996 QString key = QLatin1String("WaveUnderline-"); 5997 key += pen.color().name(); 5998 key += QLatin1Char('-'); 5999 key += QString::number(radiusBase); 6000 6001 QPixmap pixmap; 6002 if (QPixmapCache::find(key, pixmap)) 6003 return pixmap; 6004 6005 const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio 6006 const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod); 6007 const int radius = qFloor(radiusBase); 6008 5904 6009 QPainterPath path; 5905 6010 5906 bool up = true; 5907 const qreal radius = qMax(qreal(.5), qMin(qreal(1.25 * device->logicalDpiY() / qt_defaultDpi()), maxRadius)); 5908 qreal xs, ys; 5909 int i = 0; 5910 path.moveTo(0, radius); 5911 do { 5912 xs = i*(2*radius); 5913 ys = 0; 5914 5915 qreal remaining = minWidth - xs; 5916 qreal angle = 180; 5917 5918 // cut-off at the last arc segment 5919 if (remaining < 2 * radius) 5920 angle = 180 * remaining / (2 * radius); 5921 5922 path.arcTo(xs, ys, 2*radius, 2*radius, 180, up ? angle : -angle); 5923 5924 up = !up; 5925 ++i; 5926 } while (xs + 2*radius < minWidth); 5927 5928 return path; 6011 qreal xs = 0; 6012 qreal ys = radius; 6013 6014 while (xs < width) { 6015 xs += halfPeriod; 6016 ys = -ys; 6017 path.quadTo(xs - halfPeriod / 2, ys, xs, 0); 6018 } 6019 6020 pixmap = QPixmap(width, radius * 2); 6021 pixmap.fill(Qt::transparent); 6022 { 6023 QPen wavePen = pen; 6024 wavePen.setCapStyle(Qt::SquareCap); 6025 6026 // This is to protect against making the line too fat, as happens on Mac OS X 6027 // due to it having a rather thick width for the regular underline. 6028 const qreal maxPenWidth = .8 * radius; 6029 if (wavePen.widthF() > maxPenWidth) 6030 wavePen.setWidth(maxPenWidth); 6031 6032 QPainter imgPainter(&pixmap); 6033 imgPainter.setPen(wavePen); 6034 imgPainter.setRenderHint(QPainter::Antialiasing); 6035 imgPainter.translate(0, radius); 6036 imgPainter.drawPath(path); 6037 } 6038 6039 QPixmapCache::insert(key, pixmap); 6040 6041 return pixmap; 5929 6042 } 5930 6043 … … 5947 6060 5948 6061 QLineF line(pos.x(), pos.y(), pos.x() + ti.width.toReal(), pos.y()); 6062 6063 const qreal underlineOffset = fe->underlinePosition().toReal(); 5949 6064 // deliberately ceil the offset to avoid the underline coming too close to 5950 6065 // the text above it. 5951 const qreal underlinePos = pos.y() + qCeil( fe->underlinePosition().toReal());6066 const qreal underlinePos = pos.y() + qCeil(underlineOffset); 5952 6067 5953 6068 if (underlineStyle == QTextCharFormat::SpellCheckUnderline) { … … 5957 6072 if (underlineStyle == QTextCharFormat::WaveUnderline) { 5958 6073 painter->save(); 5959 painter->setRenderHint(QPainter::Antialiasing); 5960 painter->translate(pos.x(), underlinePos); 6074 painter->translate(0, pos.y() + 1); 5961 6075 5962 6076 QColor uc = ti.charFormat.underlineColor(); 5963 6077 if (uc.isValid()) 5964 painter->setPen(uc); 5965 5966 painter->drawPath(generateWavyPath(ti.width.toReal(), 5967 fe->underlinePosition().toReal(), 5968 painter->device())); 6078 pen.setColor(uc); 6079 6080 // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms 6081 const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen); 6082 const int descent = (int) ti.descent.toReal(); 6083 6084 painter->setBrushOrigin(painter->brushOrigin().x(), 0); 6085 painter->fillRect(pos.x(), 0, qCeil(ti.width.toReal()), qMin(wave.height(), descent), wave); 5969 6086 painter->restore(); 5970 6087 } else if (underlineStyle != QTextCharFormat::NoUnderline) { … … 6001 6118 } 6002 6119 6003 /*!6004 \internal6005 \since 4.16006 */6007 6120 void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) 6008 6121 { … … 6043 6156 if (d->state->matrix.type() < QTransform::TxShear) { 6044 6157 bool isPlain90DegreeRotation = 6045 (qFuzzy Compare(m.m11() + 1, qreal(1))6046 && qFuzzy Compare(m.m12(),qreal(1))6047 && qFuzzy Compare(m.m21(), qreal(-1))6048 && qFuzzy Compare(m.m22() + 1, qreal(1))6158 (qFuzzyIsNull(m.m11()) 6159 && qFuzzyIsNull(m.m12() - qreal(1)) 6160 && qFuzzyIsNull(m.m21() + qreal(1)) 6161 && qFuzzyIsNull(m.m22()) 6049 6162 ) 6050 6163 || 6051 (qFuzzy Compare(m.m11(), qreal(-1))6052 && qFuzzy Compare(m.m12() + 1, qreal(1))6053 && qFuzzy Compare(m.m21() + 1, qreal(1))6054 && qFuzzy Compare(m.m22(), qreal(-1))6164 (qFuzzyIsNull(m.m11() + qreal(1)) 6165 && qFuzzyIsNull(m.m12()) 6166 && qFuzzyIsNull(m.m21()) 6167 && qFuzzyIsNull(m.m22() + qreal(1)) 6055 6168 ) 6056 6169 || 6057 (qFuzzy Compare(m.m11() + 1, qreal(1))6058 && qFuzzy Compare(m.m12(), qreal(-1))6059 && qFuzzy Compare(m.m21(),qreal(1))6060 && qFuzzy Compare(m.m22() + 1, qreal(1))6170 (qFuzzyIsNull(m.m11()) 6171 && qFuzzyIsNull(m.m12() + qreal(1)) 6172 && qFuzzyIsNull(m.m21() - qreal(1)) 6173 && qFuzzyIsNull(m.m22()) 6061 6174 ) 6062 6175 ; … … 6310 6423 setPen(Qt::NoPen); 6311 6424 6312 // If there is no scaling or transformation involved we have to make sure we use the6425 // If there is no rotation involved we have to make sure we use the 6313 6426 // antialiased and not the aliased coordinate system by rounding the coordinates. 6314 if (d->state->matrix.type() <= QTransform::TxTranslate) { 6315 qreal x = qRound(r.x() + d->state->matrix.dx()) - d->state->matrix.dx(); 6316 qreal y = qRound(r.y() + d->state->matrix.dy()) - d->state->matrix.dy(); 6317 qreal w = qRound(r.width()); 6318 qreal h = qRound(r.height()); 6319 sx = qRound(sx); 6320 sy = qRound(sy); 6427 if (d->state->matrix.type() <= QTransform::TxScale) { 6428 const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix); 6429 6430 if (d->state->matrix.type() <= QTransform::TxTranslate) { 6431 sx = qRound(sx); 6432 sy = qRound(sy); 6433 } 6434 6321 6435 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy)); 6322 drawRect(QRectF( x, y, w, h));6436 drawRect(QRectF(p, r.size())); 6323 6437 } else { 6324 6438 setBrushOrigin(QPointF(r.x()-sx, r.y()-sy)); … … 6748 6862 false. 6749 6863 6750 \sa setViewTransformEnabled(), world Matrix()6864 \sa setViewTransformEnabled(), worldTransform() 6751 6865 */ 6752 6866 … … 6904 7018 \compat 6905 7019 6906 Use reset Matrix() instead.7020 Use resetTransform() instead. 6907 7021 */ 6908 7022 … … 6950 7064 6951 7065 /*! 6952 Use the worldMatrix() combined with QMatrix::dx() instead. 7066 \obsolete 7067 7068 Use the worldTransform() combined with QTransform::dx() instead. 6953 7069 6954 7070 \oldcode … … 6957 7073 \newcode 6958 7074 QPainter painter(this); 6959 qreal x = painter.world Matrix().dx();7075 qreal x = painter.worldTransform().dx(); 6960 7076 \endcode 6961 7077 */ … … 6971 7087 6972 7088 /*! 6973 Use the worldMatrix() combined with QMatrix::dy() instead. 7089 \obsolete 7090 7091 Use the worldTransform() combined with QTransform::dy() instead. 6974 7092 6975 7093 \oldcode … … 6978 7096 \newcode 6979 7097 QPainter painter(this); 6980 qreal y = painter.world Matrix().dy();7098 qreal y = painter.worldTransform().dy(); 6981 7099 \endcode 6982 7100 */ … … 7076 7194 \newcode 7077 7195 QPainter painter(this); 7078 QPolygon transformed = polygon.mid(index, count) * painter.combined Matrix();7196 QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform(); 7079 7197 \endcode 7080 7198 */ … … 7091 7209 \fn QPoint QPainter::xFormDev(const QPoint &point) const 7092 7210 \overload 7093 7094 Use combinedTransform() combined with QMatrix::inverted() instead. 7211 \obsolete 7212 7213 Use combinedTransform() combined with QTransform::inverted() instead. 7095 7214 7096 7215 \oldcode … … 7099 7218 \newcode 7100 7219 QPainter painter(this); 7101 QPoint transformed = point * painter.combined Matrix().inverted();7220 QPoint transformed = point * painter.combinedTransform().inverted(); 7102 7221 \endcode 7103 7222 */ … … 7118 7237 \fn QRect QPainter::xFormDev(const QRect &rectangle) const 7119 7238 \overload 7120 7121 Use combineMatrix() combined with QMatrix::inverted() instead. 7239 \obsolete 7240 7241 Use combinedTransform() combined with QTransform::inverted() instead. 7122 7242 7123 7243 \oldcode … … 7126 7246 \newcode 7127 7247 QPainter painter(this); 7128 QRect transformed = rectangle * painter.combinedMatrix().inverted(); 7248 QRegion region = QRegion(rectangle) * painter.combinedTransform().inverted(); 7249 QRect transformed = region.boundingRect(); 7129 7250 \endcode 7130 7251 */ … … 7146 7267 7147 7268 \fn QPoint QPainter::xFormDev(const QPolygon &polygon) const 7148 \o verload7149 7150 Use combined Matrix() combined with QMatrix::inverted() instead.7269 \obsolete 7270 7271 Use combinedTransform() combined with QTransform::inverted() instead. 7151 7272 7152 7273 \oldcode … … 7155 7276 \newcode 7156 7277 QPainter painter(this); 7157 QPolygon transformed = polygon * painter.combined Matrix().inverted();7278 QPolygon transformed = polygon * painter.combinedTransform().inverted(); 7158 7279 \endcode 7159 7280 */ … … 7174 7295 \fn QPolygon QPainter::xFormDev(const QPolygon &polygon, int index, int count) const 7175 7296 \overload 7176 7177 Use combinedMatrix() combined with QPolygon::mid() and QMatrix::inverted() instead. 7297 \obsolete 7298 7299 Use combinedTransform() combined with QPolygon::mid() and QTransform::inverted() instead. 7178 7300 7179 7301 \oldcode … … 7182 7304 \newcode 7183 7305 QPainter painter(this); 7184 QPolygon transformed = polygon.mid(index, count) * painter.combined Matrix().inverted();7306 QPolygon transformed = polygon.mid(index, count) * painter.combinedTransform().inverted(); 7185 7307 \endcode 7186 7308 */ … … 7377 7499 void qt_painter_removePaintDevice(QPaintDevice *dev) 7378 7500 { 7379 QMutexLocker locker(globalRedirectionsMutex()); 7380 if(QPaintDeviceRedirectionList *redirections = globalRedirections()) { 7501 QMutex *mutex = 0; 7502 QT_TRY { 7503 mutex = globalRedirectionsMutex(); 7504 } QT_CATCH(...) { 7505 // ignore the missing mutex, since we could be called from 7506 // a destructor, and destructors shall not throw 7507 } 7508 QMutexLocker locker(mutex); 7509 QPaintDeviceRedirectionList *redirections = 0; 7510 QT_TRY { 7511 redirections = globalRedirections(); 7512 } QT_CATCH(...) { 7513 // do nothing - code below is safe with redirections being 0. 7514 } 7515 if (redirections) { 7381 7516 for (int i = 0; i < redirections->size(); ) { 7382 7517 if(redirections->at(i) == dev || redirections->at(i).replacement == dev) … … 7428 7563 7429 7564 Qt::LayoutDirection layout_direction; 7430 if(option) 7565 if (tf & Qt::TextForceLeftToRight) 7566 layout_direction = Qt::LeftToRight; 7567 else if (tf & Qt::TextForceRightToLeft) 7568 layout_direction = Qt::RightToLeft; 7569 else if (option) 7431 7570 layout_direction = option->textDirection(); 7432 7571 else if (painter) … … 7445 7584 tf |= Qt::TextDontPrint; 7446 7585 7447 int maxUnderlines = 0;7586 uint maxUnderlines = 0; 7448 7587 int numUnderlines = 0; 7449 int underlinePositionStack[32]; 7450 int *underlinePositions = underlinePositionStack; 7588 QVarLengthArray<int, 32> underlinePositions(1); 7451 7589 7452 7590 QFontMetricsF fm(fnt); 7453 7454 7591 QString text = str; 7592 int offset = 0; 7593 start_lengthVariant: 7594 bool hasMoreLengthVariants = false; 7455 7595 // compatible behaviour to the old implementation. Replace 7456 7596 // tabs by spaces 7457 QChar *chr = text.data(); 7458 const QChar *end = chr + str.length(); 7459 bool has_tab = false; 7460 while (chr != end) { 7461 if (*chr == QLatin1Char('\r') || (singleline && *chr == QLatin1Char('\n'))) { 7462 *chr = QLatin1Char(' '); 7463 } else if (*chr == QLatin1Char('\n')) { 7464 *chr = QChar::LineSeparator; 7465 } else if (*chr == QLatin1Char('&')) { 7597 int old_offset = offset; 7598 for (; offset < text.length(); offset++) { 7599 QChar chr = text.at(offset); 7600 if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) { 7601 text[offset] = QLatin1Char(' '); 7602 } else if (chr == QLatin1Char('\n')) { 7603 text[offset] = QChar::LineSeparator; 7604 } else if (chr == QLatin1Char('&')) { 7466 7605 ++maxUnderlines; 7467 } else if (*chr == QLatin1Char('\t')) { 7468 has_tab = true; 7606 } else if (chr == QLatin1Char('\t')) { 7607 if (!expandtabs) { 7608 text[offset] = QLatin1Char(' '); 7609 } else if (!tabarraylen && !tabstops) { 7610 tabstops = qRound(fm.width(QLatin1Char('x'))*8); 7611 } 7612 } else if (chr == QChar(ushort(0x9c))) { 7613 // string with multiple length variants 7614 hasMoreLengthVariants = true; 7615 break; 7469 7616 } 7470 ++chr; 7471 } 7472 if (has_tab) { 7473 if (!expandtabs) { 7474 chr = text.data(); 7475 while (chr != end) { 7476 if (*chr == QLatin1Char('\t')) 7477 *chr = QLatin1Char(' '); 7478 ++chr; 7479 } 7480 } else if (!tabarraylen && !tabstops) { 7481 tabstops = qRound(fm.width(QLatin1Char('x'))*8); 7482 } 7483 } 7484 7485 if (hidemnmemonic || showmnemonic) { 7486 if (maxUnderlines > 32) 7487 underlinePositions = new int[maxUnderlines]; 7488 QChar *cout = text.data(); 7617 } 7618 7619 int length = offset - old_offset; 7620 if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) { 7621 underlinePositions.resize(maxUnderlines + 1); 7622 7623 QChar *cout = text.data() + old_offset; 7489 7624 QChar *cin = cout; 7490 int l = str.length();7625 int l = length; 7491 7626 while (l) { 7492 7627 if (*cin == QLatin1Char('&')) { 7493 7628 ++cin; 7629 --length; 7494 7630 --l; 7495 7631 if (!l) 7496 7632 break; 7497 7633 if (*cin != QLatin1Char('&') && !hidemnmemonic) 7498 underlinePositions[numUnderlines++] = cout - text. unicode();7634 underlinePositions[numUnderlines++] = cout - text.data() - old_offset; 7499 7635 } 7500 7636 *cout = *cin; … … 7503 7639 --l; 7504 7640 } 7505 int newlen = cout - text.unicode();7506 if (newlen != text.length())7507 text.resize(newlen);7508 7641 } 7509 7642 … … 7516 7649 qreal width = 0; 7517 7650 7518 QStackTextEngine engine(text, fnt); 7651 QString finalText = text.mid(old_offset, length); 7652 QStackTextEngine engine(finalText, fnt); 7519 7653 if (option) { 7520 7654 engine.option = *option; 7521 7655 } 7522 7523 7524 7656 7525 7657 engine.option.setTextDirection(layout_direction); … … 7536 7668 QTextLayout textLayout(&engine); 7537 7669 textLayout.setCacheEnabled(true); 7538 textLayout.engine()->underlinePositions = underlinePositions ;7539 7540 if ( text.isEmpty()) {7670 textLayout.engine()->underlinePositions = underlinePositions.data(); 7671 7672 if (finalText.isEmpty()) { 7541 7673 height = fm.height(); 7542 7674 width = 0; … … 7564 7696 height += l.height(); 7565 7697 width = qMax(width, l.naturalTextWidth()); 7566 if (! brect && height >= r.height())7698 if (!dontclip && !brect && height >= r.height()) 7567 7699 break; 7568 7700 } … … 7583 7715 const qreal scale = painter->transform().m22(); 7584 7716 if (scale != 0) 7585 yoff = qRound(yoff * scale) / scale;7717 yoff = -qRound(-yoff * scale) / scale; 7586 7718 } 7587 7719 } … … 7603 7735 } 7604 7736 QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height); 7737 7738 if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) { 7739 offset++; 7740 goto start_lengthVariant; 7741 } 7605 7742 if (brect) 7606 7743 *brect = bounds; … … 7629 7766 } 7630 7767 } 7631 7632 if (underlinePositions != underlinePositionStack)7633 delete [] underlinePositions;7634 7768 } 7635 7769 … … 7664 7798 clipOperation(s->clipOperation), 7665 7799 renderHints(s->renderHints), clipInfo(s->clipInfo), 7666 worldMatrix(s->worldMatrix), matrix(s->matrix), redirection _offset(s->redirection_offset),7800 worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix), 7667 7801 wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh), 7668 7802 vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh), … … 8086 8220 \row \o QPaintEngine::DirtyCompositionMode \o compositionMode() 8087 8221 \row \o QPaintEngine::DirtyFont \o font() 8088 \row \o QPaintEngine::DirtyTransform \o matrix()8222 \row \o QPaintEngine::DirtyTransform \o transform() 8089 8223 \row \o QPaintEngine::DirtyClipEnabled \o isClipEnabled() 8090 8224 \row \o QPaintEngine::DirtyPen \o pen() … … 8205 8339 /*! 8206 8340 \since 4.2 8341 \obsolete 8207 8342 8208 8343 Returns the matrix in the current paint engine 8209 8344 state. 8345 8346 \note It is advisable to use transform() instead of this function to 8347 preserve the properties of perspective transformations. 8210 8348 8211 8349 This variable should only be used when the state() returns a … … 8389 8527 the current matrix; otherwise it replaces the current matrix. 8390 8528 8391 This function has been added for compatibility with setMatrix(), 8392 but as with setMatrix() the preferred method of setting a 8393 transformation on the painter is through setWorldTransform(). 8394 8395 \sa transform() 8529 \sa transform() setWorldTransform() 8396 8530 */ 8397 8531 … … 8403 8537 /*! 8404 8538 Returns the world transformation matrix. 8539 8540 \sa worldTransform() 8405 8541 */ 8406 8542 … … 8513 8649 window/viewport and world transformation. 8514 8650 8515 \sa setWorld Matrix(), setWindow(), setViewport()8651 \sa setWorldTransform(), setWindow(), setViewport() 8516 8652 */ 8517 8653 … … 8531 8667 } 8532 8668 8669 /*! \fn Display *QPaintDevice::x11Display() const 8670 Use QX11Info::display() instead. 8671 8672 \oldcode 8673 Display *display = widget->x11Display(); 8674 \newcode 8675 Display *display = QX11Info::display(); 8676 \endcode 8677 8678 \sa QWidget::x11Info(), QX11Info::display() 8679 */ 8680 8681 /*! \fn int QPaintDevice::x11Screen() const 8682 Use QX11Info::screen() instead. 8683 8684 \oldcode 8685 int screen = widget->x11Screen(); 8686 \newcode 8687 int screen = widget->x11Info().screen(); 8688 \endcode 8689 8690 \sa QWidget::x11Info(), QPixmap::x11Info() 8691 */ 8692 8693 /*! \fn void *QPaintDevice::x11Visual() const 8694 Use QX11Info::visual() instead. 8695 8696 \oldcode 8697 void *visual = widget->x11Visual(); 8698 \newcode 8699 void *visual = widget->x11Info().visual(); 8700 \endcode 8701 8702 \sa QWidget::x11Info(), QPixmap::x11Info() 8703 */ 8704 8705 /*! \fn int QPaintDevice::x11Depth() const 8706 Use QX11Info::depth() instead. 8707 8708 \oldcode 8709 int depth = widget->x11Depth(); 8710 \newcode 8711 int depth = widget->x11Info().depth(); 8712 \endcode 8713 8714 \sa QWidget::x11Info(), QPixmap::x11Info() 8715 */ 8716 8717 /*! \fn int QPaintDevice::x11Cells() const 8718 Use QX11Info::cells() instead. 8719 8720 \oldcode 8721 int cells = widget->x11Cells(); 8722 \newcode 8723 int cells = widget->x11Info().cells(); 8724 \endcode 8725 8726 \sa QWidget::x11Info(), QPixmap::x11Info() 8727 */ 8728 8729 /*! \fn Qt::HANDLE QPaintDevice::x11Colormap() const 8730 Use QX11Info::colormap() instead. 8731 8732 \oldcode 8733 unsigned long screen = widget->x11Colormap(); 8734 \newcode 8735 unsigned long screen = widget->x11Info().colormap(); 8736 \endcode 8737 8738 \sa QWidget::x11Info(), QPixmap::x11Info() 8739 */ 8740 8741 /*! \fn bool QPaintDevice::x11DefaultColormap() const 8742 Use QX11Info::defaultColormap() instead. 8743 8744 \oldcode 8745 bool isDefault = widget->x11DefaultColormap(); 8746 \newcode 8747 bool isDefault = widget->x11Info().defaultColormap(); 8748 \endcode 8749 8750 \sa QWidget::x11Info(), QPixmap::x11Info() 8751 */ 8752 8753 /*! \fn bool QPaintDevice::x11DefaultVisual() const 8754 Use QX11Info::defaultVisual() instead. 8755 8756 \oldcode 8757 bool isDefault = widget->x11DefaultVisual(); 8758 \newcode 8759 bool isDefault = widget->x11Info().defaultVisual(); 8760 \endcode 8761 8762 \sa QWidget::x11Info(), QPixmap::x11Info() 8763 */ 8764 8765 /*! \fn void *QPaintDevice::x11AppVisual(int screen) 8766 Use QX11Info::visual() instead. 8767 8768 \oldcode 8769 void *visual = QPaintDevice::x11AppVisual(screen); 8770 \newcode 8771 void *visual = qApp->x11Info(screen).visual(); 8772 \endcode 8773 8774 \sa QWidget::x11Info(), QPixmap::x11Info() 8775 */ 8776 8777 /*! \fn Qt::HANDLE QPaintDevice::x11AppColormap(int screen) 8778 Use QX11Info::colormap() instead. 8779 8780 \oldcode 8781 unsigned long colormap = QPaintDevice::x11AppColormap(screen); 8782 \newcode 8783 unsigned long colormap = qApp->x11Info(screen).colormap(); 8784 \endcode 8785 8786 \sa QWidget::x11Info(), QPixmap::x11Info() 8787 */ 8788 8789 /*! \fn Display *QPaintDevice::x11AppDisplay() 8790 Use QX11Info::display() instead. 8791 8792 \oldcode 8793 Display *display = QPaintDevice::x11AppDisplay(); 8794 \newcode 8795 Display *display = qApp->x11Info().display(); 8796 \endcode 8797 8798 \sa QWidget::x11Info(), QPixmap::x11Info() 8799 */ 8800 8801 /*! \fn int QPaintDevice::x11AppScreen() 8802 Use QX11Info::screen() instead. 8803 8804 \oldcode 8805 int screen = QPaintDevice::x11AppScreen(); 8806 \newcode 8807 int screen = qApp->x11Info().screen(); 8808 \endcode 8809 8810 \sa QWidget::x11Info(), QPixmap::x11Info() 8811 */ 8812 8813 /*! \fn int QPaintDevice::x11AppDepth(int screen) 8814 Use QX11Info::depth() instead. 8815 8816 \oldcode 8817 int depth = QPaintDevice::x11AppDepth(screen); 8818 \newcode 8819 int depth = qApp->x11Info(screen).depth(); 8820 \endcode 8821 8822 \sa QWidget::x11Info(), QPixmap::x11Info() 8823 */ 8824 8825 /*! \fn int QPaintDevice::x11AppCells(int screen) 8826 Use QX11Info::cells() instead. 8827 8828 \oldcode 8829 int cells = QPaintDevice::x11AppCells(screen); 8830 \newcode 8831 int cells = qApp->x11Info(screen).cells(); 8832 \endcode 8833 8834 \sa QWidget::x11Info(), QPixmap::x11Info() 8835 */ 8836 8837 /*! \fn Qt::HANDLE QPaintDevice::x11AppRootWindow(int screen) 8838 Use QX11Info::appRootWindow() instead. 8839 8840 \oldcode 8841 unsigned long window = QPaintDevice::x11AppRootWindow(screen); 8842 \newcode 8843 unsigned long window = qApp->x11Info(screen).appRootWindow(); 8844 \endcode 8845 8846 \sa QWidget::x11Info(), QPixmap::x11Info() 8847 */ 8848 8849 /*! \fn bool QPaintDevice::x11AppDefaultColormap(int screen) 8850 Use QX11Info::defaultColormap() instead. 8851 8852 \oldcode 8853 bool isDefault = QPaintDevice::x11AppDefaultColormap(screen); 8854 \newcode 8855 bool isDefault = qApp->x11Info(screen).defaultColormap(); 8856 \endcode 8857 8858 \sa QWidget::x11Info(), QPixmap::x11Info() 8859 */ 8860 8861 /*! \fn bool QPaintDevice::x11AppDefaultVisual(int screen) 8862 Use QX11Info::defaultVisual() instead. 8863 8864 \oldcode 8865 bool isDefault = QPaintDevice::x11AppDefaultVisual(screen); 8866 \newcode 8867 bool isDefault = qApp->x11Info(screen).defaultVisual(); 8868 \endcode 8869 8870 \sa QWidget::x11Info(), QPixmap::x11Info() 8871 */ 8872 8873 /*! \fn void QPaintDevice::x11SetAppDpiX(int dpi, int screen) 8874 Use QX11Info::setAppDpiX() instead. 8875 */ 8876 8877 /*! \fn void QPaintDevice::x11SetAppDpiY(int dpi, int screen) 8878 Use QX11Info::setAppDpiY() instead. 8879 */ 8880 8881 /*! \fn int QPaintDevice::x11AppDpiX(int screen) 8882 Use QX11Info::appDpiX() instead. 8883 8884 \oldcode 8885 bool isDefault = QPaintDevice::x11AppDpiX(screen); 8886 \newcode 8887 bool isDefault = qApp->x11Info(screen).appDpiX(); 8888 \endcode 8889 8890 \sa QWidget::x11Info(), QPixmap::x11Info() 8891 */ 8892 8893 /*! \fn int QPaintDevice::x11AppDpiY(int screen) 8894 Use QX11Info::appDpiY() instead. 8895 8896 \oldcode 8897 bool isDefault = QPaintDevice::x11AppDpiY(screen); 8898 \newcode 8899 bool isDefault = qApp->x11Info(screen).appDpiY(); 8900 \endcode 8901 8902 \sa QWidget::x11Info(), QPixmap::x11Info() 8903 */ 8904 8905 /*! \fn HDC QPaintDevice::getDC() const 8906 \internal 8907 */ 8908 8909 /*! \fn void QPaintDevice::releaseDC(HDC) const 8910 \internal 8911 */ 8912 8913 /*! \fn QWSDisplay *QPaintDevice::qwsDisplay() 8914 \internal 8915 */ 8916 8533 8917 QT_END_NAMESPACE
Note:
See TracChangeset
for help on using the changeset viewer.