| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | 
| 4 | ** Contact: https://www.qt.io/licensing/ | 
| 5 | ** | 
| 6 | ** This file is part of the test suite of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ | 
| 9 | ** Commercial License Usage | 
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 11 | ** accordance with the commercial license agreement provided with the | 
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU | 
| 19 | ** General Public License version 3 as published by the Free Software | 
| 20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | 
| 21 | ** included in the packaging of this file. Please review the following | 
| 22 | ** information to ensure the GNU General Public License requirements will | 
| 23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. | 
| 24 | ** | 
| 25 | ** $QT_END_LICENSE$ | 
| 26 | ** | 
| 27 | ****************************************************************************/ | 
| 28 |  | 
| 29 |  | 
| 30 | #include <QtTest/QtTest> | 
| 31 | #include <qpainter.h> | 
| 32 | #ifndef QT_NO_WIDGETS | 
| 33 | #include <qdrawutil.h> | 
| 34 | #include <qwidget.h> | 
| 35 | #endif | 
| 36 | #include <qguiapplication.h> | 
| 37 | #include <qfontmetrics.h> | 
| 38 | #include <qbitmap.h> | 
| 39 | #include <qimage.h> | 
| 40 | #include <qthread.h> | 
| 41 | #include <limits.h> | 
| 42 | #include <math.h> | 
| 43 | #include <qpaintengine.h> | 
| 44 | #include <qpixmap.h> | 
| 45 | #include <qrandom.h> | 
| 46 |  | 
| 47 | #include <private/qdrawhelper_p.h> | 
| 48 | #include <qpainter.h> | 
| 49 | #include <qpainterpath.h> | 
| 50 | #include <qqueue.h> | 
| 51 | #include <qscreen.h> | 
| 52 |  | 
| 53 | #ifndef QT_NO_WIDGETS | 
| 54 | #include <qgraphicsview.h> | 
| 55 | #include <qgraphicsscene.h> | 
| 56 | #include <qgraphicsproxywidget.h> | 
| 57 | #endif | 
| 58 | #include <qfontdatabase.h> | 
| 59 |  | 
| 60 | Q_DECLARE_METATYPE(QGradientStops) | 
| 61 | Q_DECLARE_METATYPE(QPainterPath) | 
| 62 | Q_DECLARE_METATYPE(QImage::Format) | 
| 63 | Q_DECLARE_METATYPE(QPainter::CompositionMode) | 
| 64 |  | 
| 65 | class tst_QPainter : public QObject | 
| 66 | { | 
| 67 | Q_OBJECT | 
| 68 |  | 
| 69 | public: | 
| 70 |     tst_QPainter(); | 
| 71 |  | 
| 72 | private slots: | 
| 73 |     void cleanupTestCase(); | 
| 74 |     void getSetCheck(); | 
| 75 | #ifndef QT_NO_WIDGETS | 
| 76 |     void drawPixmap_comp_data(); | 
| 77 |     void drawPixmap_comp(); | 
| 78 | #endif | 
| 79 |     void saveAndRestore_data(); | 
| 80 |     void saveAndRestore(); | 
| 81 |  | 
| 82 | #ifndef QT_NO_WIDGETS | 
| 83 |     void drawBorderPixmap(); | 
| 84 | #endif | 
| 85 |     void drawPixmapFragments(); | 
| 86 |     void drawPixmapNegativeScale(); | 
| 87 |  | 
| 88 |     void drawLine_data(); | 
| 89 |     void drawLine(); | 
| 90 |     void drawLine_clipped(); | 
| 91 |     void drawLine_task121143(); | 
| 92 |     void drawLine_task216948(); | 
| 93 |  | 
| 94 |     void drawLine_task190634(); | 
| 95 |     void drawLine_task229459(); | 
| 96 |     void drawLine_task234891(); | 
| 97 |     void drawLineEndPoints(); | 
| 98 |  | 
| 99 |     void drawRect_data() { fillData(); } | 
| 100 |     void drawRect(); | 
| 101 |     void drawRect2(); | 
| 102 |  | 
| 103 |     void fillRect_data(); | 
| 104 |     void fillRect(); | 
| 105 |     void fillRect2_data(); | 
| 106 |     void fillRect2(); | 
| 107 |     void fillRect3_data() { fillRect2_data(); } | 
| 108 |     void fillRect3(); | 
| 109 |     void fillRect4_data() { fillRect2_data(); } | 
| 110 |     void fillRect4(); | 
| 111 |     void fillRectNonPremul_data(); | 
| 112 |     void fillRectNonPremul(); | 
| 113 |  | 
| 114 |     void fillRectRGB30_data(); | 
| 115 |     void fillRectRGB30(); | 
| 116 |  | 
| 117 |     void drawEllipse_data(); | 
| 118 |     void drawEllipse(); | 
| 119 |     void drawClippedEllipse_data(); | 
| 120 |     void drawClippedEllipse(); | 
| 121 |  | 
| 122 |     void drawPath_data(); | 
| 123 |     void drawPath(); | 
| 124 |     void drawPath2(); | 
| 125 |     void drawPath3(); | 
| 126 |  | 
| 127 | #if QT_DEPRECATED_SINCE(5, 13) | 
| 128 |     void drawRoundRect_data() { fillData(); } | 
| 129 |     void drawRoundRect(); | 
| 130 | #endif | 
| 131 |     void drawRoundedRect_data() { fillData(); } | 
| 132 |     void drawRoundedRect(); | 
| 133 |  | 
| 134 |     void qimageFormats_data(); | 
| 135 |     void qimageFormats(); | 
| 136 |     void textOnTransparentImage(); | 
| 137 |  | 
| 138 | #if !defined(QT_NO_WIDGETS) && QT_DEPRECATED_SINCE(5, 13) | 
| 139 |     void initFrom(); | 
| 140 | #endif | 
| 141 |  | 
| 142 |     void setWindow(); | 
| 143 |  | 
| 144 |     void combinedMatrix(); | 
| 145 |     void renderHints(); | 
| 146 |  | 
| 147 |     void disableEnableClipping(); | 
| 148 |     void setClipRect(); | 
| 149 |     void clipRect(); | 
| 150 |     void setEqualClipRegionAndPath_data(); | 
| 151 |     void setEqualClipRegionAndPath(); | 
| 152 |  | 
| 153 |     void clipRectSaveRestore(); | 
| 154 |     void clipStateSaveRestore(); | 
| 155 |  | 
| 156 |     void clippedFillPath_data(); | 
| 157 |     void clippedFillPath(); | 
| 158 |     void clippedLines_data(); | 
| 159 |     void clippedLines(); | 
| 160 |     void clippedPolygon_data(); | 
| 161 |     void clippedPolygon(); | 
| 162 |     void clippedText(); | 
| 163 |  | 
| 164 |     void clipBoundingRect(); | 
| 165 |     void transformedClip(); | 
| 166 |  | 
| 167 |     void setOpacity_data(); | 
| 168 |     void setOpacity(); | 
| 169 |  | 
| 170 |     void drawhelper_blend_untransformed_data(); | 
| 171 |     void drawhelper_blend_untransformed(); | 
| 172 |     void drawhelper_blend_tiled_untransformed_data(); | 
| 173 |     void drawhelper_blend_tiled_untransformed(); | 
| 174 |  | 
| 175 |     void porterDuff_warning(); | 
| 176 |  | 
| 177 |     void drawhelper_blend_color(); | 
| 178 |  | 
| 179 | #ifndef QT_NO_WIDGETS | 
| 180 |     void childWidgetViewport(); | 
| 181 | #endif | 
| 182 |  | 
| 183 |     void fillRect_objectBoundingModeGradient(); | 
| 184 |     void fillRect_stretchToDeviceMode(); | 
| 185 |     void monoImages(); | 
| 186 |  | 
| 187 |     void linearGradientSymmetry_data(); | 
| 188 |     void linearGradientSymmetry(); | 
| 189 |     void gradientInterpolation(); | 
| 190 |  | 
| 191 |     void gradientPixelFormat_data(); | 
| 192 |     void gradientPixelFormat(); | 
| 193 |  | 
| 194 | #if QT_CONFIG(raster_64bit) | 
| 195 |     void linearGradientRgb30_data(); | 
| 196 |     void linearGradientRgb30(); | 
| 197 |     void radialGradientRgb30_data(); | 
| 198 |     void radialGradientRgb30(); | 
| 199 | #endif | 
| 200 |  | 
| 201 |     void fpe_pixmapTransform(); | 
| 202 |     void fpe_zeroLengthLines(); | 
| 203 |     void fpe_divByZero(); | 
| 204 |  | 
| 205 |     void fpe_steepSlopes_data(); | 
| 206 |     void fpe_steepSlopes(); | 
| 207 |     void fpe_rasterizeLine_task232012(); | 
| 208 |  | 
| 209 |     void fpe_radialGradients(); | 
| 210 |  | 
| 211 |     void rasterizer_asserts(); | 
| 212 |     void rasterizer_negativeCoords(); | 
| 213 |  | 
| 214 |     void blendOverFlow_data(); | 
| 215 |     void blendOverFlow(); | 
| 216 |  | 
| 217 |     void largeImagePainting_data(); | 
| 218 |     void largeImagePainting(); | 
| 219 |  | 
| 220 |     void imageScaling_task206785(); | 
| 221 |  | 
| 222 |     void outlineFillConsistency(); | 
| 223 |  | 
| 224 |     void drawImage_task217400_data(); | 
| 225 |     void drawImage_task217400(); | 
| 226 |     void drawImage_1x1(); | 
| 227 |     void drawImage_task258776(); | 
| 228 |     void drawImage_QTBUG28324(); | 
| 229 |     void drawRect_task215378(); | 
| 230 |     void drawRect_task247505(); | 
| 231 |  | 
| 232 | #if defined(Q_OS_MAC) | 
| 233 |     void drawText_subPixelPositionsInRaster_qtbug5053(); | 
| 234 | #endif | 
| 235 |  | 
| 236 |     void drawImage_data(); | 
| 237 |     void drawImage(); | 
| 238 |  | 
| 239 |     void clippedImage(); | 
| 240 |  | 
| 241 |     void stateResetBetweenQPainters(); | 
| 242 |  | 
| 243 |     void imageCoordinateLimit(); | 
| 244 |     void imageBlending_data(); | 
| 245 |     void imageBlending(); | 
| 246 |     void imageBlending_clipped(); | 
| 247 |  | 
| 248 |     void paintOnNullPixmap(); | 
| 249 |     void checkCompositionMode(); | 
| 250 |  | 
| 251 |     void drawPolygon(); | 
| 252 |  | 
| 253 |     void inactivePainter(); | 
| 254 |  | 
| 255 |     void extendedBlendModes(); | 
| 256 |  | 
| 257 |     void zeroOpacity(); | 
| 258 |     void clippingBug(); | 
| 259 |     void emptyClip(); | 
| 260 |  | 
| 261 |     void taskQT4444_dontOverflowDashOffset(); | 
| 262 |  | 
| 263 |     void painterBegin(); | 
| 264 |     void setPenColorOnImage(); | 
| 265 |     void setPenColorOnPixmap(); | 
| 266 |  | 
| 267 | #ifndef QT_NO_WIDGETS | 
| 268 |     void QTBUG5939_attachPainterPrivate(); | 
| 269 | #endif | 
| 270 |  | 
| 271 |     void drawPointScaled(); | 
| 272 |  | 
| 273 |     void QTBUG14614_gradientCacheRaceCondition(); | 
| 274 |     void drawTextOpacity(); | 
| 275 |  | 
| 276 |     void QTBUG17053_zeroDashPattern(); | 
| 277 |  | 
| 278 |     void QTBUG38781_NoBrushAndQBitmap(); | 
| 279 |  | 
| 280 |     void drawTextOutsideGuiThread(); | 
| 281 |  | 
| 282 |     void drawTextWithComplexBrush(); | 
| 283 |     void QTBUG26013_squareCapStroke(); | 
| 284 |     void QTBUG25153_drawLine(); | 
| 285 |  | 
| 286 |     void cosmeticStrokerClipping_data(); | 
| 287 |     void cosmeticStrokerClipping(); | 
| 288 |  | 
| 289 |     void blendARGBonRGB_data(); | 
| 290 |     void blendARGBonRGB(); | 
| 291 |  | 
| 292 |     void RasterOp_NotDestination(); | 
| 293 |     void drawTextNoHinting(); | 
| 294 |  | 
| 295 |     void drawPolyline_data(); | 
| 296 |     void drawPolyline(); | 
| 297 |  | 
| 298 |     void QTBUG50153_drawImage_assert(); | 
| 299 |  | 
| 300 |     void rotateImage_data(); | 
| 301 |     void rotateImage(); | 
| 302 |  | 
| 303 |     void QTBUG56252(); | 
| 304 |  | 
| 305 |     void blendNullRGB32(); | 
| 306 |     void toRGB64(); | 
| 307 |  | 
| 308 |     void fillPolygon(); | 
| 309 |  | 
| 310 |     void drawImageAtPointF(); | 
| 311 |     void scaledDashes(); | 
| 312 |  | 
| 313 | private: | 
| 314 |     void fillData(); | 
| 315 |     void setPenColor(QPainter& p); | 
| 316 |     QColor baseColor( int k, int intensity=255 ); | 
| 317 |     QImage getResImage( const QString &dir, const QString &addition, const QString &extension ); | 
| 318 |     QBitmap getBitmap( const QString &dir, const QString &filename, bool mask ); | 
| 319 | }; | 
| 320 |  | 
| 321 | // Testing get/set functions | 
| 322 | void tst_QPainter::getSetCheck() | 
| 323 | { | 
| 324 |     QImage img(QSize(10, 10), QImage::Format_ARGB32_Premultiplied); | 
| 325 |     QPainter obj1; | 
| 326 |     obj1.begin(&img); | 
| 327 |     // CompositionMode QPainter::compositionMode() | 
| 328 |     // void QPainter::setCompositionMode(CompositionMode) | 
| 329 |     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceOver)); | 
| 330 |     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceOver), obj1.compositionMode()); | 
| 331 |     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOver)); | 
| 332 |     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOver), obj1.compositionMode()); | 
| 333 |     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Clear)); | 
| 334 |     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Clear), obj1.compositionMode()); | 
| 335 |     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Source)); | 
| 336 |     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Source), obj1.compositionMode()); | 
| 337 |     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Destination)); | 
| 338 |     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Destination), obj1.compositionMode()); | 
| 339 |     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceIn)); | 
| 340 |     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceIn), obj1.compositionMode()); | 
| 341 |     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationIn)); | 
| 342 |     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationIn), obj1.compositionMode()); | 
| 343 |     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceOut)); | 
| 344 |     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceOut), obj1.compositionMode()); | 
| 345 |     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOut)); | 
| 346 |     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOut), obj1.compositionMode()); | 
| 347 |     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceAtop)); | 
| 348 |     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceAtop), obj1.compositionMode()); | 
| 349 |     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationAtop)); | 
| 350 |     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationAtop), obj1.compositionMode()); | 
| 351 |     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Xor)); | 
| 352 |     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Xor), obj1.compositionMode()); | 
| 353 |  | 
| 354 |     // const QPen & QPainter::pen() | 
| 355 |     // void QPainter::setPen(const QPen &) | 
| 356 |     QPen var3(Qt::red); | 
| 357 |     obj1.setPen(var3); | 
| 358 |     QCOMPARE(var3, obj1.pen()); | 
| 359 |     obj1.setPen(QPen()); | 
| 360 |     QCOMPARE(QPen(), obj1.pen()); | 
| 361 |  | 
| 362 |     // const QBrush & QPainter::brush() | 
| 363 |     // void QPainter::setBrush(const QBrush &) | 
| 364 |     QBrush var4(Qt::red); | 
| 365 |     obj1.setBrush(var4); | 
| 366 |     QCOMPARE(var4, obj1.brush()); | 
| 367 |     obj1.setBrush(QBrush()); | 
| 368 |     QCOMPARE(QBrush(), obj1.brush()); | 
| 369 |  | 
| 370 |     // const QBrush & QPainter::background() | 
| 371 |     // void QPainter::setBackground(const QBrush &) | 
| 372 |     QBrush var5(Qt::yellow); | 
| 373 |     obj1.setBackground(var5); | 
| 374 |     QCOMPARE(var5, obj1.background()); | 
| 375 |     obj1.setBackground(QBrush()); | 
| 376 |     QCOMPARE(QBrush(), obj1.background()); | 
| 377 |  | 
| 378 |     // bool QPainter::matrixEnabled() | 
| 379 |     // void QPainter::setMatrixEnabled(bool) | 
| 380 |     obj1.setWorldMatrixEnabled(false); | 
| 381 |     QCOMPARE(false, obj1.worldMatrixEnabled()); | 
| 382 |     obj1.setWorldMatrixEnabled(true); | 
| 383 |     QCOMPARE(true, obj1.worldMatrixEnabled()); | 
| 384 |  | 
| 385 |     // bool QPainter::viewTransformEnabled() | 
| 386 |     // void QPainter::setViewTransformEnabled(bool) | 
| 387 |     obj1.setViewTransformEnabled(false); | 
| 388 |     QCOMPARE(false, obj1.viewTransformEnabled()); | 
| 389 |     obj1.setViewTransformEnabled(true); | 
| 390 |     QCOMPARE(true, obj1.viewTransformEnabled()); | 
| 391 | } | 
| 392 |  | 
| 393 |  | 
| 394 | tst_QPainter::tst_QPainter() | 
| 395 | { | 
| 396 |     // QtTestCase sets this to false, but this turns off alpha pixmaps on Unix. | 
| 397 |     QGuiApplication::setDesktopSettingsAware(true); | 
| 398 | } | 
| 399 |  | 
| 400 | void tst_QPainter::cleanupTestCase() | 
| 401 | { | 
| 402 |     QFile::remove(fileName: QLatin1String("dest.png" )); | 
| 403 |     QFile::remove(fileName: QLatin1String("expected.png" )); | 
| 404 |     QFile::remove(fileName: QLatin1String("foo.png" )); | 
| 405 | } | 
| 406 |  | 
| 407 | #ifndef QT_NO_WIDGETS | 
| 408 | void tst_QPainter::drawPixmap_comp_data() | 
| 409 | { | 
| 410 |     if (QGuiApplication::primaryScreen()->depth() < 24) | 
| 411 |         QSKIP("Test only works on 32 bit displays" ); | 
| 412 |  | 
| 413 |     QTest::addColumn<uint>(name: "dest" ); | 
| 414 |     QTest::addColumn<uint>(name: "source" ); | 
| 415 |  | 
| 416 |     QTest::newRow(dataTag: "0% on 0%, 1" )           << 0x00000000u<< 0x00000000u; | 
| 417 |     QTest::newRow(dataTag: "0% on 0%, 2" )           << 0x00007fffu << 0x00ff007fu; | 
| 418 |  | 
| 419 |     QTest::newRow(dataTag: "50% on a=0%" )           << 0x00000000u << 0x7fff0000u; | 
| 420 |     QTest::newRow(dataTag: "50% on a=50%" )          << 0x7f000000u << 0x7fff0000u; | 
| 421 |     QTest::newRow(dataTag: "50% on deadbeef" )      << 0xdeafbeefu <<  0x7fff0000u; | 
| 422 |     QTest::newRow(dataTag: "deadbeef on a=0%" )      << 0x00000000u << 0xdeadbeefu; | 
| 423 |     QTest::newRow(dataTag: "deadbeef on a=50%" )     << 0x7f000000u << 0xdeadbeefu; | 
| 424 |     QTest::newRow(dataTag: "50% blue on 50% red" )   << 0x7fff0000u << 0x7f0000ffu; | 
| 425 |     QTest::newRow(dataTag: "50% blue on 50% green" ) << 0x7f00ff00u << 0x7f0000ffu; | 
| 426 |     QTest::newRow(dataTag: "50% red on 50% green" )  << 0x7f00ff00u << 0x7fff0000u; | 
| 427 |     QTest::newRow(dataTag: "0% on 50%" )             << 0x7fff00ffu << 0x00ffffffu; | 
| 428 |     QTest::newRow(dataTag: "100% on deadbeef" )      << 0xdeafbeefu << 0xffabcdefu; | 
| 429 |     QTest::newRow(dataTag: "100% on a=0%" )           << 0x00000000u << 0xffabcdefu; | 
| 430 | } | 
| 431 |  | 
| 432 | QRgb qt_compose_alpha(QRgb source, QRgb dest) | 
| 433 | { | 
| 434 |     int r1 = qRed(rgb: dest), g1 = qGreen(rgb: dest), b1 = qBlue(rgb: dest), a1 = qAlpha(rgb: dest); | 
| 435 |     int r2 = qRed(rgb: source), g2 = qGreen(rgb: source), b2 = qBlue(rgb: source), a2 = qAlpha(rgb: source); | 
| 436 |  | 
| 437 |     int alpha = qMin(a: a2 + ((255 - a2) * a1 + 127) / 255, b: 255); | 
| 438 |     if (alpha == 0) | 
| 439 |         return qRgba(r: 0, g: 0, b: 0, a: 0); | 
| 440 |  | 
| 441 |     return qRgba( | 
| 442 |         r: qMin(a: (r2 * a2 + (255 - a2) * r1 * a1 / 255) / alpha, b: 255), | 
| 443 |         g: qMin(a: (g2 * a2 + (255 - a2) * g1 * a1 / 255) / alpha, b: 255), | 
| 444 |         b: qMin(a: (b2 * a2 + (255 - a2) * b1 * a1 / 255) / alpha, b: 255), | 
| 445 |         a: alpha); | 
| 446 | } | 
| 447 |  | 
| 448 | /* Tests that drawing masked pixmaps works | 
| 449 | */ | 
| 450 | void tst_QPainter::drawPixmap_comp() | 
| 451 | { | 
| 452 | #ifdef Q_OS_MAC | 
| 453 |     QSKIP("Mac has other ideas about alpha composition" ); | 
| 454 | #endif | 
| 455 |     QFETCH(uint, dest); | 
| 456 |     QFETCH(uint, source); | 
| 457 |  | 
| 458 |     QRgb expected = qt_compose_alpha(source, dest); | 
| 459 |  | 
| 460 |     QColor c1(qRed(rgb: dest), qGreen(rgb: dest), qBlue(rgb: dest), qAlpha(rgb: dest)); | 
| 461 |     QColor c2(qRed(rgb: source), qGreen(rgb: source), qBlue(rgb: source), qAlpha(rgb: source)); | 
| 462 |  | 
| 463 |     QPixmap destPm(10, 10), srcPm(10, 10); | 
| 464 |     destPm.fill(fillColor: c1); | 
| 465 |     srcPm.fill(fillColor: c2); | 
| 466 |  | 
| 467 |     QPainter p(&destPm); | 
| 468 |     p.drawPixmap(x: 0, y: 0, pm: srcPm); | 
| 469 |     p.end(); | 
| 470 |  | 
| 471 |     QImage result = destPm.toImage().convertToFormat(f: QImage::Format_ARGB32); | 
| 472 |     bool different = false; | 
| 473 |     for (int y=0; y<result.height(); ++y) | 
| 474 |         for (int x=0; x<result.width(); ++x) { | 
| 475 |             bool diff; | 
| 476 |             if (qAlpha(rgb: expected) == 0) { | 
| 477 |                 diff = qAlpha(rgb: result.pixel(x, y)) != 0; | 
| 478 |             } else { | 
| 479 |                 // Compensate for possible roundoff / platform fudge | 
| 480 |                 int off = 1; | 
| 481 |                 QRgb pix = result.pixel(x, y); | 
| 482 |                 diff = (qAbs(t: qRed(rgb: pix) - qRed(rgb: expected)) > off) | 
| 483 |                              || (qAbs(t: qGreen(rgb: pix) - qGreen(rgb: expected)) > off) | 
| 484 |                              || (qAbs(t: qBlue(rgb: pix) - qBlue(rgb: expected)) > off) | 
| 485 |                              || (qAbs(t: qAlpha(rgb: pix) - qAlpha(rgb: expected)) > off); | 
| 486 |             } | 
| 487 |             if (diff && !different) | 
| 488 |                 qDebug( msg: "Different at %d,%d pixel [%d,%d,%d,%d] expected [%d,%d,%d,%d]" , x, y, | 
| 489 |                         qRed(rgb: result.pixel(x, y)), qGreen(rgb: result.pixel(x, y)), | 
| 490 |                         qBlue(rgb: result.pixel(x, y)), qAlpha(rgb: result.pixel(x, y)), | 
| 491 |                         qRed(rgb: expected), qGreen(rgb: expected), qBlue(rgb: expected), qAlpha(rgb: expected)); | 
| 492 |             different |= diff; | 
| 493 |         } | 
| 494 |  | 
| 495 |     QVERIFY(!different); | 
| 496 | } | 
| 497 | #endif | 
| 498 |  | 
| 499 | void tst_QPainter::saveAndRestore_data() | 
| 500 | { | 
| 501 |     QTest::addColumn<QFont>(name: "font" ); | 
| 502 |     QTest::addColumn<QPen>(name: "pen" ); | 
| 503 |     QTest::addColumn<QBrush>(name: "brush" ); | 
| 504 |     QTest::addColumn<QColor>(name: "backgroundColor" ); | 
| 505 |     QTest::addColumn<int>(name: "backgroundMode" ); | 
| 506 |     QTest::addColumn<QPoint>(name: "brushOrigin" ); | 
| 507 |     QTest::addColumn<QRegion>(name: "clipRegion" ); | 
| 508 |     QTest::addColumn<QRect>(name: "window" ); | 
| 509 |     QTest::addColumn<QRect>(name: "viewport" ); | 
| 510 |  | 
| 511 |     QPixmap pixmap(1, 1); | 
| 512 |     QPainter p(&pixmap); | 
| 513 |     QFont font = p.font(); | 
| 514 |     QPen pen = p.pen(); | 
| 515 |     QBrush brush = p.brush(); | 
| 516 |     QColor backgroundColor = p.background().color(); | 
| 517 |     Qt::BGMode backgroundMode = p.backgroundMode(); | 
| 518 |     QPoint brushOrigin = p.brushOrigin(); | 
| 519 |     QRegion clipRegion = p.clipRegion(); | 
| 520 |     QRect window = p.window(); | 
| 521 |     QRect viewport = p.viewport(); | 
| 522 |  | 
| 523 |     QTest::newRow(dataTag: "Original" ) << font << pen << brush << backgroundColor << int(backgroundMode) | 
| 524 |             << brushOrigin << clipRegion << window << viewport; | 
| 525 |  | 
| 526 |     QFont font2 = font; | 
| 527 |     font2.setPointSize( 24 ); | 
| 528 |     QTest::newRow(dataTag: "Modified font.pointSize, brush, backgroundColor, backgroundMode" ) | 
| 529 |             << font2 << pen << QBrush(Qt::red) << QColor(Qt::blue) << int(Qt::TransparentMode) | 
| 530 |             << brushOrigin << clipRegion << window << viewport; | 
| 531 |  | 
| 532 |     font2 = font; | 
| 533 |     font2.setPixelSize( 20 ); | 
| 534 |     QTest::newRow(dataTag: "Modified font.pixelSize, brushOrigin, pos" ) | 
| 535 |             << font2 << pen << brush << backgroundColor << int(backgroundMode) | 
| 536 |             << QPoint( 50, 32 ) << clipRegion << window << viewport; | 
| 537 |  | 
| 538 |     QTest::newRow(dataTag: "Modified clipRegion, window, viewport" ) | 
| 539 |             << font << pen << brush << backgroundColor << int(backgroundMode) | 
| 540 |             << brushOrigin << clipRegion.subtracted(r: QRect(10,10,50,30)) | 
| 541 |             << QRect(-500, -500, 500, 500 ) << QRect( 0, 0, 50, 50 ); | 
| 542 | } | 
| 543 |  | 
| 544 | void tst_QPainter::saveAndRestore() | 
| 545 | { | 
| 546 |     QFETCH( QFont, font ); | 
| 547 |     QFETCH( QPen, pen ); | 
| 548 |     QFETCH( QBrush, brush ); | 
| 549 |     QFETCH( QColor, backgroundColor ); | 
| 550 |     QFETCH( int, backgroundMode ); | 
| 551 |     QFETCH( QPoint, brushOrigin ); | 
| 552 |     QFETCH( QRegion, clipRegion ); | 
| 553 |     QFETCH( QRect, window ); | 
| 554 |     QFETCH( QRect, viewport ); | 
| 555 |  | 
| 556 |     QPixmap pixmap(1, 1); | 
| 557 |     QPainter painter(&pixmap); | 
| 558 |  | 
| 559 |     QFont font_org = painter.font(); | 
| 560 |     QPen pen_org = painter.pen(); | 
| 561 |     QBrush brush_org = painter.brush(); | 
| 562 |     QColor backgroundColor_org = painter.background().color(); | 
| 563 |     Qt::BGMode backgroundMode_org = painter.backgroundMode(); | 
| 564 |     QPoint brushOrigin_org = painter.brushOrigin(); | 
| 565 |     QRegion clipRegion_org = painter.clipRegion(); | 
| 566 |     QRect window_org = painter.window(); | 
| 567 |     QRect viewport_org = painter.viewport(); | 
| 568 |  | 
| 569 |     painter.save(); | 
| 570 |     painter.setFont( font ); | 
| 571 |     painter.setPen( QPen(pen) ); | 
| 572 |     painter.setBrush( brush ); | 
| 573 |     painter.setBackground( backgroundColor ); | 
| 574 |     painter.setBackgroundMode( (Qt::BGMode)backgroundMode ); | 
| 575 |     painter.setBrushOrigin( brushOrigin ); | 
| 576 |     painter.setClipRegion( clipRegion ); | 
| 577 |     painter.setWindow( window ); | 
| 578 |     painter.setViewport( viewport ); | 
| 579 |     painter.restore(); | 
| 580 |  | 
| 581 |     QCOMPARE( painter.font(), font_org ); | 
| 582 |     QCOMPARE( painter.font().pointSize(), font_org.pointSize() ); | 
| 583 |     QCOMPARE( painter.font().pixelSize(), font_org.pixelSize() ); | 
| 584 |     QCOMPARE( painter.pen(), pen_org ); | 
| 585 |     QCOMPARE( painter.brush(), brush_org ); | 
| 586 |     QCOMPARE( painter.background().color(), backgroundColor_org ); | 
| 587 |     QCOMPARE( painter.backgroundMode(), backgroundMode_org ); | 
| 588 |     QCOMPARE( painter.brushOrigin(), brushOrigin_org ); | 
| 589 |     QCOMPARE( painter.clipRegion(), clipRegion_org ); | 
| 590 |     QCOMPARE( painter.window(), window_org ); | 
| 591 |     QCOMPARE( painter.viewport(), viewport_org ); | 
| 592 | } | 
| 593 |  | 
| 594 | /* | 
| 595 |    Helper functions | 
| 596 | */ | 
| 597 |  | 
| 598 | QColor tst_QPainter::baseColor( int k, int intensity ) | 
| 599 | { | 
| 600 |     int r = ( k & 1 ) * intensity; | 
| 601 |     int g = ( (k>>1) & 1 ) * intensity; | 
| 602 |     int b = ( (k>>2) & 1 ) * intensity; | 
| 603 |     return QColor( r, g, b ); | 
| 604 | } | 
| 605 |  | 
| 606 | QImage tst_QPainter::getResImage( const QString &dir, const QString &addition, const QString &extension ) | 
| 607 | { | 
| 608 |     QImage res; | 
| 609 |     QString resFilename  = dir + QLatin1String("/res_" ) + addition + QLatin1Char('.') + extension; | 
| 610 |     if ( !res.load( fileName: resFilename ) ) { | 
| 611 |         QWARN(QString("Could not load result data %s %1" ).arg(resFilename).toLatin1()); | 
| 612 |         return QImage(); | 
| 613 |     } | 
| 614 |     return res; | 
| 615 | } | 
| 616 |  | 
| 617 | QBitmap tst_QPainter::getBitmap( const QString &dir, const QString &filename, bool mask ) | 
| 618 | { | 
| 619 |     QBitmap bm; | 
| 620 |     QString bmFilename = dir + QLatin1Char('/') + filename + QLatin1String(".xbm" ); | 
| 621 |     if ( !bm.load( fileName: bmFilename ) ) { | 
| 622 |         QWARN(QString("Could not load bitmap '%1'" ).arg(bmFilename).toLatin1()); | 
| 623 |         return QBitmap(); | 
| 624 |     } | 
| 625 |     if ( mask ) { | 
| 626 |         QBitmap mask; | 
| 627 |         QString maskFilename = dir + QLatin1Char('/') + filename + QLatin1String("-mask.xbm" ); | 
| 628 |         if (!mask.load(fileName: maskFilename)) { | 
| 629 |             QWARN(QString("Could not load mask '%1'" ).arg(maskFilename).toLatin1()); | 
| 630 |             return QBitmap(); | 
| 631 |         } | 
| 632 |         bm.setMask( mask ); | 
| 633 |     } | 
| 634 |     return bm; | 
| 635 | } | 
| 636 |  | 
| 637 | static int getPaintedPixels(const QImage &image, const QColor &background) | 
| 638 | { | 
| 639 |     uint color = background.rgba(); | 
| 640 |  | 
| 641 |     int pixels = 0; | 
| 642 |  | 
| 643 |     for (int y = 0; y < image.height(); ++y) | 
| 644 |         for (int x = 0; x < image.width(); ++x) | 
| 645 |             if (image.pixel(x, y) != color) | 
| 646 |                 ++pixels; | 
| 647 |  | 
| 648 |     return pixels; | 
| 649 | } | 
| 650 |  | 
| 651 | static QRect getPaintedSize(const QImage &image, const QColor &background) | 
| 652 | { | 
| 653 |     // not the fastest but at least it works.. | 
| 654 |     int xmin = image.width() + 1; | 
| 655 |     int xmax = -1; | 
| 656 |     int ymin = image.height() +1; | 
| 657 |     int ymax = -1; | 
| 658 |  | 
| 659 |     uint color = background.rgba(); | 
| 660 |  | 
| 661 |     for ( int y = 0; y < image.height(); ++y ) { | 
| 662 |         for (int x = 0; x < image.width(); ++x) { | 
| 663 |             QRgb pixel = image.pixel( x, y ); | 
| 664 |             if (pixel != color && x < xmin) | 
| 665 |                 xmin = x; | 
| 666 |             if (pixel != color && x > xmax) | 
| 667 |                 xmax = x; | 
| 668 |             if (pixel != color && y < ymin) | 
| 669 |                 ymin = y; | 
| 670 |             if (pixel != color && y > ymax) | 
| 671 |                 ymax = y; | 
| 672 |         } | 
| 673 |     } | 
| 674 |  | 
| 675 |     return QRect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); | 
| 676 | } | 
| 677 |  | 
| 678 | static QRect getPaintedSize(const QPixmap &pm, const QColor &background) | 
| 679 | { | 
| 680 |     return getPaintedSize(image: pm.toImage(), background); | 
| 681 | } | 
| 682 |  | 
| 683 | #ifndef QT_NO_WIDGETS | 
| 684 |  | 
| 685 | #if QT_DEPRECATED_SINCE(5, 13) | 
| 686 | void tst_QPainter::initFrom() | 
| 687 | { | 
| 688 |     QWidget *widget = new QWidget(); | 
| 689 |     QPalette pal = widget->palette(); | 
| 690 |     pal.setColor(acr: QPalette::WindowText, acolor: QColor(255, 0, 0)); | 
| 691 |     pal.setBrush(acr: QPalette::Window, abrush: QColor(0, 255, 0)); | 
| 692 |     widget->setPalette(pal); | 
| 693 |     widget->show(); | 
| 694 |  | 
| 695 |     QFont font = widget->font(); | 
| 696 |     font.setPointSize(26); | 
| 697 |     font.setItalic(true); | 
| 698 |     widget->setFont(font); | 
| 699 |  | 
| 700 |     QPixmap pm(100, 100); | 
| 701 |     QPainter p(&pm); | 
| 702 |     p.initFrom(device: widget); | 
| 703 |  | 
| 704 |     QCOMPARE(p.font(), font); | 
| 705 |     QCOMPARE(p.pen().color(), pal.color(QPalette::WindowText)); | 
| 706 |     QCOMPARE(p.background(), pal.window()); | 
| 707 |  | 
| 708 |     delete widget; | 
| 709 | } | 
| 710 | #endif | 
| 711 |  | 
| 712 | void tst_QPainter::drawBorderPixmap() | 
| 713 | { | 
| 714 |     QPixmap src(79,79); | 
| 715 |     src.fill(fillColor: Qt::transparent); | 
| 716 |  | 
| 717 |     QImage pm(200,200,QImage::Format_RGB32); | 
| 718 |     QPainter p(&pm); | 
| 719 |     p.setTransform(transform: QTransform(-1,0,0,-1,173.5,153.5)); | 
| 720 |     qDrawBorderPixmap(painter: &p, targetRect: QRect(0,0,75,105), targetMargins: QMargins(39,39,39,39), pixmap: src, sourceRect: QRect(0,0,79,79), sourceMargins: QMargins(39,39,39,39), | 
| 721 |                        rules: QTileRules(Qt::StretchTile,Qt::StretchTile), hints: { }); | 
| 722 | } | 
| 723 | #endif | 
| 724 |  | 
| 725 | void tst_QPainter::drawPixmapFragments() | 
| 726 | { | 
| 727 |     QPixmap origPixmap(20, 20); | 
| 728 |     QPixmap resPixmap(20, 20); | 
| 729 |     QPainter::PixmapFragment fragments[4] = { {.x: 15, .y: 15,  .sourceLeft: 0,  .sourceTop: 0, .width: 10, .height: 10, .scaleX: 1, .scaleY: 1, .rotation: 0, .opacity: 1}, | 
| 730 |                                               { .x: 5, .y: 15, .sourceLeft: 10,  .sourceTop: 0, .width: 10, .height: 10, .scaleX: 1, .scaleY: 1, .rotation: 0, .opacity: 1}, | 
| 731 |                                               {.x: 15,  .y: 5,  .sourceLeft: 0, .sourceTop: 10, .width: 10, .height: 10, .scaleX: 1, .scaleY: 1, .rotation: 0, .opacity: 1}, | 
| 732 |                                               { .x: 5,  .y: 5, .sourceLeft: 10, .sourceTop: 10, .width: 10, .height: 10, .scaleX: 1, .scaleY: 1, .rotation: 0, .opacity: 1} }; | 
| 733 |     { | 
| 734 |         QPainter p(&origPixmap); | 
| 735 |         p.fillRect(x: 0, y: 0, w: 10, h: 10, c: Qt::red); | 
| 736 |         p.fillRect(x: 10, y: 0, w: 10, h: 10, c: Qt::green); | 
| 737 |         p.fillRect(x: 0, y: 10, w: 10, h: 10, c: Qt::blue); | 
| 738 |         p.fillRect(x: 10, y: 10, w: 10, h: 10, c: Qt::yellow); | 
| 739 |     } | 
| 740 |     { | 
| 741 |         QPainter p(&resPixmap); | 
| 742 |         p.drawPixmapFragments(fragments, fragmentCount: 4, pixmap: origPixmap); | 
| 743 |     } | 
| 744 |  | 
| 745 |     QImage origImage = origPixmap.toImage().convertToFormat(f: QImage::Format_ARGB32); | 
| 746 |     QImage resImage = resPixmap.toImage().convertToFormat(f: QImage::Format_ARGB32); | 
| 747 |  | 
| 748 |     QCOMPARE(resImage.size(), resPixmap.size()); | 
| 749 |     QVERIFY(resImage.pixel(5, 5) == origImage.pixel(15, 15)); | 
| 750 |     QVERIFY(resImage.pixel(5, 15) == origImage.pixel(15, 5)); | 
| 751 |     QVERIFY(resImage.pixel(15, 5) == origImage.pixel(5, 15)); | 
| 752 |     QVERIFY(resImage.pixel(15, 15) == origImage.pixel(5, 5)); | 
| 753 |  | 
| 754 |  | 
| 755 |     QPainter::PixmapFragment fragment = QPainter::PixmapFragment::create(pos: QPointF(20, 20), sourceRect: QRectF(30, 30, 2, 2)); | 
| 756 |     QCOMPARE(fragment.x, qreal(20)); | 
| 757 |     QCOMPARE(fragment.y, qreal(20)); | 
| 758 |     QCOMPARE(fragment.sourceLeft, qreal(30)); | 
| 759 |     QCOMPARE(fragment.sourceTop, qreal(30)); | 
| 760 |     QCOMPARE(fragment.width, qreal(2)); | 
| 761 |     QCOMPARE(fragment.height, qreal(2)); | 
| 762 |     QCOMPARE(fragment.scaleX, qreal(1)); | 
| 763 |     QCOMPARE(fragment.scaleY, qreal(1)); | 
| 764 |     QCOMPARE(fragment.rotation, qreal(0)); | 
| 765 |     QCOMPARE(fragment.opacity, qreal(1)); | 
| 766 | } | 
| 767 |  | 
| 768 | void tst_QPainter::drawPixmapNegativeScale() | 
| 769 | { | 
| 770 |     // basePixmap is a 16x16 opaque white square ... | 
| 771 |     QPixmap basePixmap(16, 16); | 
| 772 |     basePixmap.fill(fillColor: QColor(255, 255, 255, 255)); | 
| 773 |     // ... with an opaque black 8x16 left strip | 
| 774 |     QPainter p(&basePixmap); | 
| 775 |     p.setCompositionMode(QPainter::CompositionMode_Source); | 
| 776 |     p.fillRect(QRect(0, 0, 8, 16), color: QColor(0, 0, 0, 255)); | 
| 777 |     p.end(); | 
| 778 |  | 
| 779 |     // verify one pixel value for each strip | 
| 780 |     QImage baseImage = basePixmap.toImage().convertToFormat(f: QImage::Format_ARGB32); | 
| 781 |     QVERIFY(baseImage.pixel(4, 8) == qRgba(0, 0, 0, 255)); | 
| 782 |     QVERIFY(baseImage.pixel(12, 8) == qRgba(255, 255, 255, 255)); | 
| 783 |  | 
| 784 |     // resultPixmap is a 16x16 square | 
| 785 |     QPixmap resultPixmap(16, 16); | 
| 786 |  | 
| 787 |     // draw basePixmap over resultPixmap using x=-1.0 y=-1.0 | 
| 788 |     // scaling factors (i.e. 180° rotation) | 
| 789 |     QPainter p2(&resultPixmap); | 
| 790 |     p2.setCompositionMode(QPainter::CompositionMode_Source); | 
| 791 |     p2.scale(sx: qreal(-1.0), sy: qreal(-1.0)); | 
| 792 |     p2.translate(dx: -resultPixmap.width(), dy: -resultPixmap.height()); | 
| 793 |     p2.drawPixmap(r: resultPixmap.rect(), pm: basePixmap); | 
| 794 |     p2.end(); | 
| 795 |  | 
| 796 |     // check result | 
| 797 |     QImage resultImage = resultPixmap.toImage().convertToFormat(f: QImage::Format_ARGB32); | 
| 798 |     QVERIFY(resultImage.pixel(4, 8) == qRgba(255, 255, 255, 255)); // left strip is now white | 
| 799 |     QVERIFY(resultImage.pixel(12, 8) == qRgba(0, 0, 0, 255)); // and right strip is now black | 
| 800 | } | 
| 801 |  | 
| 802 | void tst_QPainter::drawLine_data() | 
| 803 | { | 
| 804 |     QTest::addColumn<QLine>(name: "line" ); | 
| 805 |  | 
| 806 |     QTest::newRow(dataTag: "0-45" ) << QLine(0, 20, 100, 0); | 
| 807 |     QTest::newRow(dataTag: "45-90" ) << QLine(0, 100, 20, 0); | 
| 808 |     QTest::newRow(dataTag: "90-135" ) << QLine(20, 100, 0, 0); | 
| 809 |     QTest::newRow(dataTag: "135-180" ) << QLine(100, 20, 0, 0); | 
| 810 |     QTest::newRow(dataTag: "180-225" ) << QLine(100, 0, 0, 20); | 
| 811 |     QTest::newRow(dataTag: "225-270" ) << QLine(20, 0, 0, 100); | 
| 812 |     QTest::newRow(dataTag: "270-315" ) << QLine(0, 0, 20, 100); | 
| 813 |     QTest::newRow(dataTag: "315-360" ) << QLine(0, 0, 100, 20); | 
| 814 | } | 
| 815 |  | 
| 816 | void tst_QPainter::drawLine() | 
| 817 | { | 
| 818 |     const int offset = 5; | 
| 819 |     const int epsilon = 1; // allow for one pixel difference | 
| 820 |  | 
| 821 |     QFETCH(QLine, line); | 
| 822 |  | 
| 823 |     QPixmap pixmapUnclipped(qMin(a: line.x1(), b: line.x2()) | 
| 824 |                             + 2*offset + qAbs(t: line.dx()), | 
| 825 |                             qMin(a: line.y1(), b: line.y2()) | 
| 826 |                             + 2*offset + qAbs(t: line.dy())); | 
| 827 |  | 
| 828 |     { // unclipped | 
| 829 |         pixmapUnclipped.fill(fillColor: Qt::white); | 
| 830 |         QPainter p(&pixmapUnclipped); | 
| 831 |         p.setRenderHint(hint: QPainter::Qt4CompatiblePainting); | 
| 832 |         p.translate(dx: offset, dy: offset); | 
| 833 |         p.setPen(QPen(Qt::black)); | 
| 834 |         p.drawLine(line); | 
| 835 |         p.end(); | 
| 836 |  | 
| 837 |         const QRect painted = getPaintedSize(pm: pixmapUnclipped, background: Qt::white); | 
| 838 |  | 
| 839 |         QLine l = line; | 
| 840 |         l.translate(adx: offset, ady: offset); | 
| 841 |         QVERIFY(qAbs(painted.width() - qAbs(l.dx())) <= epsilon); | 
| 842 |         QVERIFY(qAbs(painted.height() - qAbs(l.dy())) <= epsilon); | 
| 843 |         QVERIFY(qAbs(painted.top() - qMin(l.y1(), l.y2())) <= epsilon); | 
| 844 |         QVERIFY(qAbs(painted.left() - qMin(l.x1(), l.x2())) <= epsilon); | 
| 845 |         QVERIFY(qAbs(painted.bottom() - qMax(l.y1(), l.y2())) <= epsilon); | 
| 846 |         QVERIFY(qAbs(painted.right() - qMax(l.x1(), l.x2())) <= epsilon); | 
| 847 |     } | 
| 848 |  | 
| 849 |     QPixmap pixmapClipped(qMin(a: line.x1(), b: line.x2()) | 
| 850 |                           + 2*offset + qAbs(t: line.dx()), | 
| 851 |                           qMin(a: line.y1(), b: line.y2()) | 
| 852 |                           + 2*offset + qAbs(t: line.dy())); | 
| 853 |     { // clipped | 
| 854 |         const QRect clip = QRect(line.p1(), line.p2()).normalized(); | 
| 855 |  | 
| 856 |         pixmapClipped.fill(fillColor: Qt::white); | 
| 857 |         QPainter p(&pixmapClipped); | 
| 858 |         p.setRenderHint(hint: QPainter::Qt4CompatiblePainting); | 
| 859 |         p.translate(dx: offset, dy: offset); | 
| 860 |         p.setClipRect(clip); | 
| 861 |         p.setPen(QPen(Qt::black)); | 
| 862 |         p.drawLine(line); | 
| 863 |         p.end(); | 
| 864 |     } | 
| 865 |  | 
| 866 |     const QImage unclipped = pixmapUnclipped.toImage(); | 
| 867 |     const QImage clipped = pixmapClipped.toImage(); | 
| 868 |     QCOMPARE(unclipped, clipped); | 
| 869 | } | 
| 870 |  | 
| 871 | void tst_QPainter::drawLine_clipped() | 
| 872 | { | 
| 873 |     QImage image(16, 1, QImage::Format_ARGB32_Premultiplied); | 
| 874 |     image.fill(pixel: 0x0); | 
| 875 |  | 
| 876 |     QPainter p(&image); | 
| 877 |     p.setPen(QPen(Qt::black, 10)); | 
| 878 |  | 
| 879 |     // this should fill the whole image | 
| 880 |     p.drawLine(x1: -1, y1: -1, x2: 17, y2: 1); | 
| 881 |     p.end(); | 
| 882 |  | 
| 883 |     for (int x = 0; x < 16; ++x) | 
| 884 |         QCOMPARE(image.pixel(x, 0), 0xff000000); | 
| 885 | } | 
| 886 |  | 
| 887 | void tst_QPainter::drawLine_task121143() | 
| 888 | { | 
| 889 |     QPen pen(Qt::black); | 
| 890 |  | 
| 891 |     QImage image(5, 5, QImage::Format_ARGB32_Premultiplied); | 
| 892 |     image.fill(pixel: 0xffffffff); | 
| 893 |     QPainter p(&image); | 
| 894 |     p.setPen(pen); | 
| 895 |     p.setRenderHint(hint: QPainter::Qt4CompatiblePainting); | 
| 896 |     p.drawLine(line: QLine(0, 0+4, 0+4, 0)); | 
| 897 |     p.end(); | 
| 898 |  | 
| 899 |     QImage expected(5, 5, QImage::Format_ARGB32_Premultiplied); | 
| 900 |     expected.fill(pixel: 0xffffffff); | 
| 901 |     for (int x = 0; x < 5; ++x) | 
| 902 |         expected.setPixel(x, y: 5-x-1, index_or_rgb: pen.color().rgb()); | 
| 903 |  | 
| 904 |     QCOMPARE(image, expected); | 
| 905 | } | 
| 906 |  | 
| 907 | void tst_QPainter::drawLine_task190634() | 
| 908 | { | 
| 909 |     QPen pen(Qt::black, 3); | 
| 910 |  | 
| 911 |     QImage image(32, 32, QImage::Format_ARGB32_Premultiplied); | 
| 912 |     QPainter p(&image); | 
| 913 |     p.fillRect(x: 0, y: 0, w: image.width(), h: image.height(), c: Qt::white); | 
| 914 |  | 
| 915 |     p.setPen(pen); | 
| 916 |     p.drawLine(l: QLineF(2, -1.6, 10, -1.6)); | 
| 917 |     p.end(); | 
| 918 |  | 
| 919 |     const uint *data = reinterpret_cast<uint *>(image.bits()); | 
| 920 |  | 
| 921 |     for (int i = 0; i < image.width() * image.height(); ++i) | 
| 922 |         QCOMPARE(data[i], 0xffffffff); | 
| 923 |  | 
| 924 |     p.begin(&image); | 
| 925 |     p.fillRect(x: 0, y: 0, w: image.width(), h: image.height(), c: Qt::white); | 
| 926 |  | 
| 927 |     p.setPen(pen); | 
| 928 |     p.drawLine(l: QLineF(-1.6, 2, -1.6, 10)); | 
| 929 |     p.end(); | 
| 930 |  | 
| 931 |     data = reinterpret_cast<uint *>(image.bits()); | 
| 932 |  | 
| 933 |     for (int i = 0; i < image.width() * image.height(); ++i) | 
| 934 |         QCOMPARE(data[i], 0xffffffff); | 
| 935 |  | 
| 936 |     p.begin(&image); | 
| 937 |     p.fillRect(x: 0, y: 0, w: image.width(), h: image.height(), c: Qt::white); | 
| 938 |  | 
| 939 |     p.setPen(pen); | 
| 940 |     p.drawLine( p1: QPoint(2,-2), p2: QPoint(3,-5) ); | 
| 941 |     p.end(); | 
| 942 |  | 
| 943 |     data = reinterpret_cast<uint *>(image.bits()); | 
| 944 |  | 
| 945 |     for (int i = 0; i < image.width() * image.height(); ++i) | 
| 946 |         QCOMPARE(data[i], 0xffffffff); | 
| 947 | } | 
| 948 |  | 
| 949 | void tst_QPainter::drawLine_task229459() | 
| 950 | { | 
| 951 |     QImage image(32, 32, QImage::Format_ARGB32_Premultiplied); | 
| 952 |     image.fill(pixel: 0x0); | 
| 953 |     QPen pen(Qt::black, 64); | 
| 954 |  | 
| 955 |     QPainter p(&image); | 
| 956 |     p.setPen(pen); | 
| 957 |     p.drawLine(x1: -8, y1: -8, x2: 10000000, y2: 10000000); | 
| 958 |     p.end(); | 
| 959 |  | 
| 960 |     QImage expected = image; | 
| 961 |     expected.fill(pixel: 0xff000000); | 
| 962 |  | 
| 963 |     QCOMPARE(image, expected); | 
| 964 | } | 
| 965 |  | 
| 966 | void tst_QPainter::drawLine_task234891() | 
| 967 | { | 
| 968 |     QImage img(100, 1000, QImage::Format_ARGB32_Premultiplied); | 
| 969 |     img.fill(pixel: 0x0); | 
| 970 |     QImage expected = img; | 
| 971 |  | 
| 972 |     QPainter p(&img); | 
| 973 |     p.setPen(QPen(QBrush(QColor(255,0,0)), 6)); | 
| 974 |     p.drawLine(p1: QPointF(25000,100),p2: QPointF(30000,105)); | 
| 975 |  | 
| 976 |     p.setPen(QPen(QBrush(QColor(0,255,0)), 6)); | 
| 977 |     p.drawLine(p1: QPointF(30000,150),p2: QPointF(35000,155)); | 
| 978 |  | 
| 979 |     p.setPen(QPen(QBrush(QColor(0,0,255)), 6)); | 
| 980 |     p.drawLine(p1: QPointF(65000,200),p2: QPointF(66000,205)); | 
| 981 |  | 
| 982 |     QCOMPARE(expected, img); | 
| 983 | } | 
| 984 |  | 
| 985 | void tst_QPainter::drawLine_task216948() | 
| 986 | { | 
| 987 |     QImage img(1, 10, QImage::Format_ARGB32_Premultiplied); | 
| 988 |     img.fill(pixel: 0x0); | 
| 989 |  | 
| 990 |     QPainter p(&img); | 
| 991 |     QLine line(10, 0, 10, 10); | 
| 992 |     p.translate(dx: -10, dy: 0); | 
| 993 |     p.drawLine(line); | 
| 994 |     p.end(); | 
| 995 |  | 
| 996 |     for (int i = 0; i < img.height(); ++i) | 
| 997 |         QCOMPARE(img.pixel(0, i), QColor(Qt::black).rgba()); | 
| 998 | } | 
| 999 |  | 
| 1000 | void tst_QPainter::drawLineEndPoints() | 
| 1001 | { | 
| 1002 |     QImage img(256, 256, QImage::Format_ARGB32_Premultiplied); | 
| 1003 |     img.fill(pixel: 0x0); | 
| 1004 |  | 
| 1005 |     QPainter p; | 
| 1006 |     for (int x = 0; x < img.width(); ++x) { | 
| 1007 |         QRgb color = qRgb(r: x, g: 0, b: 0); | 
| 1008 |         p.begin(&img); | 
| 1009 |         p.setPen(QPen(color)); | 
| 1010 |         p.drawLine(x1: x, y1: 0, x2: 255 - x, y2: 255); | 
| 1011 |         p.end(); | 
| 1012 |         QCOMPARE(img.pixel(x, 0), color); | 
| 1013 |         QCOMPARE(img.pixel(255 - x, 255), color); | 
| 1014 |     } | 
| 1015 |     for (int y = 0; y < img.height(); ++y) { | 
| 1016 |         QRgb color = qRgb(r: 0, g: y, b: 0); | 
| 1017 |         p.begin(&img); | 
| 1018 |         p.setPen(QPen(color)); | 
| 1019 |         p.drawLine(x1: 0, y1: y, x2: 255, y2: 255 - y); | 
| 1020 |         p.end(); | 
| 1021 |         QCOMPARE(img.pixel(0, y), color); | 
| 1022 |         QCOMPARE(img.pixel(255, 255 - y), color); | 
| 1023 |     } | 
| 1024 |     for (int x = 0; x < img.width(); ++x) { | 
| 1025 |         QRgb color = qRgb(r: x, g: 0, b: x); | 
| 1026 |         p.begin(&img); | 
| 1027 |         p.setPen(QPen(color)); | 
| 1028 |         p.drawLine(x1: x, y1: 255, x2: 255 - x, y2: 0); | 
| 1029 |         p.end(); | 
| 1030 |         QCOMPARE(img.pixel(x, 255), color); | 
| 1031 |         QCOMPARE(img.pixel(255 - x, 0), color); | 
| 1032 |     } | 
| 1033 |     for (int y = 0; y < img.height(); ++y) { | 
| 1034 |         QRgb color = qRgb(r: 0, g: y, b: y); | 
| 1035 |         p.begin(&img); | 
| 1036 |         p.setPen(QPen(color)); | 
| 1037 |         p.drawLine(x1: 255, y1: y, x2: 0, y2: 255 - y); | 
| 1038 |         p.end(); | 
| 1039 |         QCOMPARE(img.pixel(255, y), color); | 
| 1040 |         QCOMPARE(img.pixel(0, 255 - y), color); | 
| 1041 |     } | 
| 1042 | } | 
| 1043 |  | 
| 1044 | void tst_QPainter::drawRect() | 
| 1045 | { | 
| 1046 |     QFETCH(QRect, rect); | 
| 1047 |     QFETCH(bool, usePen); | 
| 1048 |  | 
| 1049 |     QPixmap pixmap(rect.x() + rect.width() + 10, | 
| 1050 |                    rect.y() + rect.height() + 10); | 
| 1051 |     { | 
| 1052 |         pixmap.fill(fillColor: Qt::white); | 
| 1053 |         QPainter p(&pixmap); | 
| 1054 |         p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen)); | 
| 1055 |         p.setBrush(Qt::black); | 
| 1056 |         p.drawRect(r: rect); | 
| 1057 |         p.end(); | 
| 1058 |  | 
| 1059 |         int increment = usePen ? 1 : 0; | 
| 1060 |  | 
| 1061 |         const QRect painted = getPaintedSize(pm: pixmap, background: Qt::white); | 
| 1062 |         QCOMPARE(painted.width(), rect.width() + increment); | 
| 1063 |         QCOMPARE(painted.height(), rect.height() + increment); | 
| 1064 |     } | 
| 1065 | } | 
| 1066 |  | 
| 1067 | void tst_QPainter::drawRect2() | 
| 1068 | { | 
| 1069 |     QImage image(64, 64, QImage::Format_ARGB32_Premultiplied); | 
| 1070 |     { | 
| 1071 |         image.fill(pixel: 0xffffffff); | 
| 1072 |  | 
| 1073 |         QTransform transform(0.368567, 0, 0, 0, 0.368567, 0, 0.0289, 0.0289, 1); | 
| 1074 |  | 
| 1075 |         QPainter p(&image); | 
| 1076 |         p.setRenderHint(hint: QPainter::Qt4CompatiblePainting); | 
| 1077 |         p.setTransform(transform); | 
| 1078 |         p.setBrush(Qt::red); | 
| 1079 |         p.setPen(Qt::NoPen); | 
| 1080 |         p.drawRect(r: QRect(14, 14, 39, 39)); | 
| 1081 |         p.end(); | 
| 1082 |  | 
| 1083 |         QRect fill = getPaintedSize(image, background: Qt::white); | 
| 1084 |         image.fill(pixel: 0xffffffff); | 
| 1085 |  | 
| 1086 |         p.begin(&image); | 
| 1087 |         p.setRenderHint(hint: QPainter::Qt4CompatiblePainting); | 
| 1088 |         p.setTransform(transform); | 
| 1089 |         p.drawRect(r: QRect(14, 14, 39, 39)); | 
| 1090 |         p.end(); | 
| 1091 |  | 
| 1092 |         QRect stroke = getPaintedSize(image, background: Qt::white); | 
| 1093 |         QCOMPARE(stroke.adjusted(1, 1, 0, 0), fill.adjusted(0, 0, 1, 1)); | 
| 1094 |     } | 
| 1095 | } | 
| 1096 |  | 
| 1097 | void tst_QPainter::fillRect_data() | 
| 1098 | { | 
| 1099 |     QTest::addColumn<QImage::Format>(name: "format" ); | 
| 1100 |  | 
| 1101 |     QTest::newRow(dataTag: "argb32pm" ) << QImage::Format_ARGB32_Premultiplied; | 
| 1102 |     QTest::newRow(dataTag: "rgba8888pm" ) << QImage::Format_RGBA8888_Premultiplied; | 
| 1103 |     QTest::newRow(dataTag: "rgba64pm" ) << QImage::Format_RGBA64_Premultiplied; | 
| 1104 | } | 
| 1105 |  | 
| 1106 | void tst_QPainter::fillRect() | 
| 1107 | { | 
| 1108 |     QFETCH(QImage::Format, format); | 
| 1109 |  | 
| 1110 |     QImage image(100, 100, format); | 
| 1111 |     image.fill(pixel: QColor(0, 0, 0, 0).rgba()); | 
| 1112 |  | 
| 1113 |     QPainter p(&image); | 
| 1114 |  | 
| 1115 |     p.fillRect(x: 0, y: 0, w: 100, h: 100, b: QColor(255, 0, 0, 127)); | 
| 1116 |  | 
| 1117 | //    pixmap.save("bla1.png", "PNG"); | 
| 1118 |     QCOMPARE(getPaintedSize(image, QColor(0, 0, 0, 0)), | 
| 1119 |              QRect(0, 0, 100, 100)); | 
| 1120 |     QCOMPARE(getPaintedSize(image, QColor(127, 0, 0, 127)).isValid(), | 
| 1121 |              QRect().isValid()); | 
| 1122 |  | 
| 1123 |     p.setCompositionMode(QPainter::CompositionMode_SourceIn); | 
| 1124 |     p.fillRect(x: 50, y: 0, w: 50, h: 100, b: QColor(0, 0, 255, 255)); | 
| 1125 |  | 
| 1126 |     QCOMPARE(getPaintedSize(image, QColor(127, 0, 0, 127)), | 
| 1127 |              QRect(50, 0, 50, 100)); | 
| 1128 |     QCOMPARE(getPaintedSize(image, QColor(0, 0, 127, 127)), | 
| 1129 |              QRect(0, 0, 50, 100)); | 
| 1130 | } | 
| 1131 |  | 
| 1132 | void tst_QPainter::fillRect2_data() | 
| 1133 | { | 
| 1134 |     QTest::addColumn<QImage::Format>(name: "format" ); | 
| 1135 |  | 
| 1136 |     QTest::newRow(dataTag: "argb32" ) << QImage::Format_ARGB32; | 
| 1137 |     QTest::newRow(dataTag: "argb32pm" ) << QImage::Format_ARGB32_Premultiplied; | 
| 1138 |     QTest::newRow(dataTag: "rgba8888" ) << QImage::Format_RGBA8888; | 
| 1139 |     QTest::newRow(dataTag: "rgba8888pm" ) << QImage::Format_RGBA8888_Premultiplied; | 
| 1140 |     QTest::newRow(dataTag: "a2rgb30pm" ) << QImage::Format_A2RGB30_Premultiplied; | 
| 1141 |     QTest::newRow(dataTag: "a2bgr30pm" ) << QImage::Format_A2BGR30_Premultiplied; | 
| 1142 | } | 
| 1143 |  | 
| 1144 | void tst_QPainter::fillRect2() | 
| 1145 | { | 
| 1146 |     QFETCH(QImage::Format, format); | 
| 1147 |  | 
| 1148 |     QRgb background = 0x0; | 
| 1149 |  | 
| 1150 |     QImage img(1, 20, format); | 
| 1151 |     img.fill(pixel: background); | 
| 1152 |  | 
| 1153 |     QPainter p(&img); | 
| 1154 |  | 
| 1155 |     QRectF rect(0, 1, 1.2, 18); | 
| 1156 |     p.fillRect(r: rect, c: Qt::yellow); | 
| 1157 |  | 
| 1158 |     p.end(); | 
| 1159 |  | 
| 1160 |     QCOMPARE(img.pixel(0, 0), background); | 
| 1161 |     QCOMPARE(img.pixel(0, img.height() - 1), background); | 
| 1162 |  | 
| 1163 |     QCOMPARE(img.pixel(0, 1), img.pixel(0, 2)); | 
| 1164 |     QCOMPARE(img.pixel(0, img.height() - 2), img.pixel(0, img.height() - 3)); | 
| 1165 |     QCOMPARE(img.pixel(0, 1), QColor(Qt::yellow).rgba()); | 
| 1166 | } | 
| 1167 |  | 
| 1168 | void tst_QPainter::fillRect3() | 
| 1169 | { | 
| 1170 |     QFETCH(QImage::Format, format); | 
| 1171 |  | 
| 1172 |     QImage img(1, 1, format); | 
| 1173 |     img.fill(pixel: QColor(Qt::black).rgba()); | 
| 1174 |  | 
| 1175 |     QPainter p(&img); | 
| 1176 |     p.setCompositionMode(QPainter::CompositionMode_Source); | 
| 1177 |     p.fillRect(r: img.rect(), c: Qt::transparent); | 
| 1178 |     p.end(); | 
| 1179 |  | 
| 1180 |     QCOMPARE(img.pixel(0, 0), 0U); | 
| 1181 | } | 
| 1182 |  | 
| 1183 | void tst_QPainter::fillRect4() | 
| 1184 | { | 
| 1185 |     QFETCH(QImage::Format, format); | 
| 1186 |  | 
| 1187 |     QImage image(100, 1, format); | 
| 1188 |     image.fill(pixel: 0x0); | 
| 1189 |  | 
| 1190 |     QImage expected = image; | 
| 1191 |     expected.fill(pixel: 0xffffffff); | 
| 1192 |  | 
| 1193 |     QPainter p(&image); | 
| 1194 |     p.scale(sx: 1.1, sy: 1); | 
| 1195 |     p.setPen(Qt::NoPen); | 
| 1196 |  | 
| 1197 |     for (int i = 0; i < 33; ++i) | 
| 1198 |         p.fillRect(r: QRectF(3 * i, 0, 3, 1), c: Qt::white); | 
| 1199 |  | 
| 1200 |     p.end(); | 
| 1201 |  | 
| 1202 |     QCOMPARE(image, expected); | 
| 1203 | } | 
| 1204 |  | 
| 1205 | void tst_QPainter::fillRectNonPremul_data() | 
| 1206 | { | 
| 1207 |     QTest::addColumn<QImage::Format>(name: "format" ); | 
| 1208 |     QTest::addColumn<uint>(name: "color" ); | 
| 1209 |  | 
| 1210 |     QTest::newRow(dataTag: "argb32 7f1f3f7f" ) << QImage::Format_ARGB32 << qRgba(r: 31, g: 63, b: 127, a: 127); | 
| 1211 |     QTest::newRow(dataTag: "rgba8888 7f1f3f7f" ) << QImage::Format_RGBA8888 << qRgba(r: 31, g: 63, b: 127, a: 127); | 
| 1212 |  | 
| 1213 |     QTest::newRow(dataTag: "argb32 3f1f3f7f" ) << QImage::Format_ARGB32 << qRgba(r: 31, g: 63, b: 127, a: 63); | 
| 1214 |     QTest::newRow(dataTag: "rgba8888 3f1f3f7f" ) << QImage::Format_RGBA8888 << qRgba(r: 31, g: 63, b: 127, a: 63); | 
| 1215 |  | 
| 1216 |     QTest::newRow(dataTag: "argb32 070375f4" ) << QImage::Format_ARGB32 << qRgba(r: 3, g: 117, b: 244, a: 7); | 
| 1217 |     QTest::newRow(dataTag: "rgba8888 070375f4" ) << QImage::Format_RGBA8888 << qRgba(r: 3, g: 117, b: 244, a: 7); | 
| 1218 |  | 
| 1219 |     QTest::newRow(dataTag: "argb32 0301fe0c" ) << QImage::Format_ARGB32 << qRgba(r: 1, g: 254, b: 12, a: 3); | 
| 1220 |     QTest::newRow(dataTag: "rgba8888 0301fe0c" ) << QImage::Format_RGBA8888 << qRgba(r: 1, g: 254, b: 12, a: 3); | 
| 1221 |  | 
| 1222 |     QTest::newRow(dataTag: "argb32 01804010" ) << QImage::Format_ARGB32 << qRgba(r: 128, g: 64, b: 32, a: 1); | 
| 1223 |     QTest::newRow(dataTag: "rgba8888 01804010" ) << QImage::Format_RGBA8888 << qRgba(r: 128, g: 64, b: 32, a: 1); | 
| 1224 | } | 
| 1225 |  | 
| 1226 | void tst_QPainter::fillRectNonPremul() | 
| 1227 | { | 
| 1228 |     QFETCH(QImage::Format, format); | 
| 1229 |     QFETCH(uint, color); | 
| 1230 |  | 
| 1231 |     QImage image(1, 1, format); | 
| 1232 |     QRectF rect(0, 0, 1, 1); | 
| 1233 |  | 
| 1234 |     // Fill with CompositionMode_SourceOver tests blend_color | 
| 1235 |     image.fill(color: Qt::transparent); | 
| 1236 |     QPainter painter(&image); | 
| 1237 |     painter.fillRect(rect, color: QColor::fromRgba(rgba: color)); | 
| 1238 |     painter.end(); | 
| 1239 |  | 
| 1240 |     // Fill with CompositionMode_Source tests rectfill. | 
| 1241 |     painter.begin(&image); | 
| 1242 |     painter.setCompositionMode(QPainter::CompositionMode_Source); | 
| 1243 |     painter.fillRect(rect, color: QColor::fromRgba(rgba: color)); | 
| 1244 |     painter.end(); | 
| 1245 |  | 
| 1246 |     QRgb p = image.pixel(x: 0, y: 0); | 
| 1247 |     QCOMPARE(qAlpha(p), qAlpha(color)); | 
| 1248 |     QVERIFY(qAbs(qRed(p)-qRed(color)) <= 1); | 
| 1249 |     QVERIFY(qAbs(qGreen(p)-qGreen(color)) <= 1); | 
| 1250 |     QVERIFY(qAbs(qBlue(p)-qBlue(color)) <= 1); | 
| 1251 | } | 
| 1252 |  | 
| 1253 | void tst_QPainter::fillRectRGB30_data() | 
| 1254 | { | 
| 1255 |     QTest::addColumn<uint>(name: "color" ); | 
| 1256 |  | 
| 1257 |     QTest::newRow(dataTag: "17|43|259" ) << (0xc0000000 | (17 << 20) | (43 << 10) | 259); | 
| 1258 |     QTest::newRow(dataTag: "2|33|444" ) << (0xc0000000 | (2 << 20) | (33 << 10) | 444); | 
| 1259 |     QTest::newRow(dataTag: "1000|1000|1000" ) << (0xc0000000 | (1000 << 20) | (1000 << 10) | 1000); | 
| 1260 | } | 
| 1261 |  | 
| 1262 | void tst_QPainter::fillRectRGB30() | 
| 1263 | { | 
| 1264 |     QFETCH(uint, color); | 
| 1265 |     QRectF rect(0, 0, 1, 1); | 
| 1266 |  | 
| 1267 |     // Fill with CompositionMode_SourceOver tests blend_color | 
| 1268 |     QImage image1(1, 1, QImage::Format_A2BGR30_Premultiplied); | 
| 1269 |     image1.fill(color: Qt::transparent); | 
| 1270 |     QPainter painter(&image1); | 
| 1271 |     painter.fillRect(rect, color: QColor::fromRgba64(rgba: qConvertA2rgb30ToRgb64<PixelOrderBGR>(rgb: color))); | 
| 1272 |     painter.end(); | 
| 1273 |  | 
| 1274 |     uint pixel1 = ((const uint*)(image1.bits()))[0]; | 
| 1275 |     QCOMPARE(pixel1, color); | 
| 1276 |  | 
| 1277 |     // Fill with CompositionMode_Source tests rectfill. | 
| 1278 |     QImage image2(1, 1, QImage::Format_RGB30); | 
| 1279 |     painter.begin(&image2); | 
| 1280 |     painter.setCompositionMode(QPainter::CompositionMode_Source); | 
| 1281 |     painter.fillRect(rect, color: QColor::fromRgba64(rgba: qConvertA2rgb30ToRgb64<PixelOrderRGB>(rgb: color))); | 
| 1282 |     painter.end(); | 
| 1283 |  | 
| 1284 |     uint pixel2 = ((const uint*)(image2.bits()))[0]; | 
| 1285 |     QCOMPARE(pixel2, color); | 
| 1286 | } | 
| 1287 |  | 
| 1288 | void tst_QPainter::drawPath_data() | 
| 1289 | { | 
| 1290 |     QTest::addColumn<QPainterPath>(name: "path" ); | 
| 1291 |     QTest::addColumn<QRect>(name: "expectedBounds" ); | 
| 1292 |     QTest::addColumn<int>(name: "expectedPixels" ); | 
| 1293 |  | 
| 1294 |     { | 
| 1295 |         QPainterPath p; | 
| 1296 |         p.addRect(x: 2, y: 2, w: 10, h: 10); | 
| 1297 |         QTest::newRow(dataTag: "int-aligned rect" ) << p << QRect(2, 2, 10, 10) << 10 * 10; | 
| 1298 |     } | 
| 1299 |  | 
| 1300 |     { | 
| 1301 |         QPainterPath p; | 
| 1302 |         p.addRect(x: 2.25, y: 2.25, w: 10, h: 10); | 
| 1303 |         QTest::newRow(dataTag: "non-aligned rect" ) << p << QRect(3, 3, 10, 10) << 10 * 10; | 
| 1304 |     } | 
| 1305 |  | 
| 1306 |     { | 
| 1307 |         QPainterPath p; | 
| 1308 |         p.addRect(x: 2.25, y: 2.25, w: 10.5, h: 10.5); | 
| 1309 |         QTest::newRow(dataTag: "non-aligned rect 2" ) << p << QRect(3, 3, 10, 10) << 10 * 10; | 
| 1310 |     } | 
| 1311 |  | 
| 1312 |     { | 
| 1313 |         QPainterPath p; | 
| 1314 |         p.addRect(x: 2.5, y: 2.5, w: 10, h: 10); | 
| 1315 |         QTest::newRow(dataTag: "non-aligned rect 3" ) << p << QRect(3, 3, 10, 10) << 10 * 10; | 
| 1316 |     } | 
| 1317 |  | 
| 1318 |     { | 
| 1319 |         QPainterPath p; | 
| 1320 |         p.addRect(x: 2, y: 2, w: 10, h: 10); | 
| 1321 |         p.addRect(x: 4, y: 4, w: 6, h: 6); | 
| 1322 |         QTest::newRow(dataTag: "rect-in-rect" ) << p << QRect(2, 2, 10, 10) << 10 * 10 - 6 * 6; | 
| 1323 |     } | 
| 1324 |  | 
| 1325 |     { | 
| 1326 |         QPainterPath p; | 
| 1327 |         p.addRect(x: 2, y: 2, w: 10, h: 10); | 
| 1328 |         p.addRect(x: 4, y: 4, w: 6, h: 6); | 
| 1329 |         p.addRect(x: 6, y: 6, w: 2, h: 2); | 
| 1330 |         QTest::newRow(dataTag: "rect-in-rect-in-rect" ) << p << QRect(2, 2, 10, 10) << 10 * 10 - 6 * 6 + 2 * 2; | 
| 1331 |     } | 
| 1332 | } | 
| 1333 |  | 
| 1334 | void tst_QPainter::drawPath() | 
| 1335 | { | 
| 1336 |     QFETCH(QPainterPath, path); | 
| 1337 |     QFETCH(QRect, expectedBounds); | 
| 1338 |     QFETCH(int, expectedPixels); | 
| 1339 |  | 
| 1340 |     const int offset = 2; | 
| 1341 |  | 
| 1342 |     QImage image(expectedBounds.width() + 2 * offset, expectedBounds.height() + 2 * offset, | 
| 1343 |                  QImage::Format_ARGB32_Premultiplied); | 
| 1344 |     image.fill(pixel: QColor(Qt::white).rgb()); | 
| 1345 |  | 
| 1346 |     QPainter p(&image); | 
| 1347 |     p.setRenderHint(hint: QPainter::Qt4CompatiblePainting); | 
| 1348 |     p.setPen(Qt::NoPen); | 
| 1349 |     p.setBrush(Qt::black); | 
| 1350 |     p.translate(dx: offset - expectedBounds.left(), dy: offset - expectedBounds.top()); | 
| 1351 |     p.drawPath(path); | 
| 1352 |     p.end(); | 
| 1353 |  | 
| 1354 |     const QRect paintedBounds = getPaintedSize(image, background: Qt::white); | 
| 1355 |  | 
| 1356 |     QCOMPARE(paintedBounds.x(), offset); | 
| 1357 |     QCOMPARE(paintedBounds.y(), offset); | 
| 1358 |     QCOMPARE(paintedBounds.width(), expectedBounds.width()); | 
| 1359 |     QCOMPARE(paintedBounds.height(), expectedBounds.height()); | 
| 1360 |  | 
| 1361 |     if (expectedPixels != -1) { | 
| 1362 |         int paintedPixels = getPaintedPixels(image, background: Qt::white); | 
| 1363 |         QCOMPARE(paintedPixels, expectedPixels); | 
| 1364 |     } | 
| 1365 | } | 
| 1366 |  | 
| 1367 | void tst_QPainter::drawPath2() | 
| 1368 | { | 
| 1369 |     const int w = 50; | 
| 1370 |  | 
| 1371 |     for (int h = 5; h < 200; ++h) { | 
| 1372 |         QPainterPath p1, p2; | 
| 1373 |         p1.lineTo(x: w, y: 0); | 
| 1374 |         p1.lineTo(x: w, y: h); | 
| 1375 |  | 
| 1376 |         p2.lineTo(x: w, y: h); | 
| 1377 |         p2.lineTo(x: 0, y: h); | 
| 1378 |  | 
| 1379 |         const int offset = 2; | 
| 1380 |  | 
| 1381 |         QImage image(w + 2 * offset, h + 2 * offset, | 
| 1382 |                      QImage::Format_ARGB32_Premultiplied); | 
| 1383 |         image.fill(pixel: QColor(Qt::white).rgb()); | 
| 1384 |  | 
| 1385 |         QPainter p(&image); | 
| 1386 |         p.setPen(Qt::NoPen); | 
| 1387 |         p.setBrush(Qt::black); | 
| 1388 |         p.translate(dx: offset, dy: offset); | 
| 1389 |         p.drawPath(path: p1); | 
| 1390 |         p.end(); | 
| 1391 |  | 
| 1392 |         const int p1Pixels = getPaintedPixels(image, background: Qt::white); | 
| 1393 |  | 
| 1394 |         image.fill(pixel: QColor(Qt::white).rgb()); | 
| 1395 |         p.begin(&image); | 
| 1396 |         p.setPen(Qt::NoPen); | 
| 1397 |         p.setBrush(Qt::black); | 
| 1398 |         p.translate(dx: offset, dy: offset); | 
| 1399 |         p.drawPath(path: p2); | 
| 1400 |         p.end(); | 
| 1401 |  | 
| 1402 |         const int p2Pixels = getPaintedPixels(image, background: Qt::white); | 
| 1403 |  | 
| 1404 |         QCOMPARE(p1Pixels + p2Pixels, w * h); | 
| 1405 |     } | 
| 1406 | } | 
| 1407 |  | 
| 1408 | void tst_QPainter::drawPath3() | 
| 1409 | { | 
| 1410 |     QImage imgA(100, 100, QImage::Format_RGB32); | 
| 1411 |     imgA.fill(pixel: 0xffffff); | 
| 1412 |     QImage imgB = imgA; | 
| 1413 |  | 
| 1414 |     QPainterPath path; | 
| 1415 |     for (int y = 0; y < imgA.height(); ++y) { | 
| 1416 |         for (int x = 0; x < imgA.width(); ++x) { | 
| 1417 |             if ((x + y) & 1) { | 
| 1418 |                 imgA.setPixel(x, y, index_or_rgb: 0); | 
| 1419 |                 path.addRect(x, y, w: 1, h: 1); | 
| 1420 |             } | 
| 1421 |         } | 
| 1422 |     } | 
| 1423 |  | 
| 1424 |     QPainter p(&imgB); | 
| 1425 |     p.setPen(Qt::NoPen); | 
| 1426 |     p.setBrush(Qt::black); | 
| 1427 |  | 
| 1428 |     p.drawPath(path); | 
| 1429 |     p.end(); | 
| 1430 |  | 
| 1431 |     QCOMPARE(imgA, imgB); | 
| 1432 |  | 
| 1433 |     imgA.invertPixels(); | 
| 1434 |     imgB.fill(pixel: 0xffffff); | 
| 1435 |  | 
| 1436 |     p.begin(&imgB); | 
| 1437 |     p.setPen(Qt::NoPen); | 
| 1438 |     p.setBrush(Qt::black); | 
| 1439 |  | 
| 1440 |     QRectF rect(0, 0, imgA.width(), imgA.height()); | 
| 1441 |     path.addRect(rect: rect.adjusted(xp1: -10, yp1: -10, xp2: 10, yp2: 10)); | 
| 1442 |     p.drawPath(path); | 
| 1443 |     p.end(); | 
| 1444 |  | 
| 1445 |     QCOMPARE(imgA, imgB); | 
| 1446 |  | 
| 1447 |     path.setFillRule(Qt::WindingFill); | 
| 1448 |     imgB.fill(pixel: 0xffffff); | 
| 1449 |  | 
| 1450 |     p.begin(&imgB); | 
| 1451 |     p.setPen(Qt::NoPen); | 
| 1452 |     p.setBrush(Qt::black); | 
| 1453 |     QRect clip = rect.adjusted(xp1: 10, yp1: 10, xp2: -10, yp2: -10).toRect(); | 
| 1454 |     p.setClipRect(clip); | 
| 1455 |     p.drawPath(path); | 
| 1456 |     p.end(); | 
| 1457 |  | 
| 1458 |     QCOMPARE(getPaintedPixels(imgB, Qt::white), clip.width() * clip.height()); | 
| 1459 | } | 
| 1460 |  | 
| 1461 | void tst_QPainter::drawEllipse_data() | 
| 1462 | { | 
| 1463 |     QTest::addColumn<QSize>(name: "size" ); | 
| 1464 |     QTest::addColumn<bool>(name: "usePen" ); | 
| 1465 |  | 
| 1466 |     // The current drawEllipse algorithm (drawEllipse_midpoint_i in | 
| 1467 |     // qpaintengine_raster.cpp) draws ellipses that are too wide if the | 
| 1468 |     // ratio between width and hight is too large/small (task 114874). Those | 
| 1469 |     // ratios are therefore currently avoided. | 
| 1470 |     for (int w = 10; w < 128; w += 7) { | 
| 1471 |         const QByteArray wB = QByteArray::number(w); | 
| 1472 |         for (int h = w/2; h < qMin(a: 2*w, b: 128); h += 13) { | 
| 1473 |             const QByteArray sB = wB + 'x' + QByteArray::number(h); | 
| 1474 |             QTest::newRow(dataTag: (sB + " with pen" ).constData()) << QSize(w, h) << true; | 
| 1475 |             QTest::newRow(dataTag: (sB + " no pen" ).constData()) << QSize(w, h) << false; | 
| 1476 |         } | 
| 1477 |     } | 
| 1478 | } | 
| 1479 |  | 
| 1480 | void tst_QPainter::drawEllipse() | 
| 1481 | { | 
| 1482 |     QFETCH(QSize, size); | 
| 1483 |     QFETCH(bool, usePen); | 
| 1484 |  | 
| 1485 |     const int offset = 10; | 
| 1486 |     QRect rect(QPoint(offset, offset), size); | 
| 1487 |  | 
| 1488 |     QImage image(size.width() + 2 * offset, size.height() + 2 * offset, | 
| 1489 |                  QImage::Format_ARGB32_Premultiplied); | 
| 1490 |     image.fill(pixel: QColor(Qt::white).rgb()); | 
| 1491 |  | 
| 1492 |     QPainter p(&image); | 
| 1493 |     p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen)); | 
| 1494 |     p.setBrush(Qt::black); | 
| 1495 |     p.drawEllipse(r: rect); | 
| 1496 |     p.end(); | 
| 1497 |  | 
| 1498 |     QPixmap pixmap = QPixmap::fromImage(image); | 
| 1499 |  | 
| 1500 |     const QRect painted = getPaintedSize(pm: pixmap, background: Qt::white); | 
| 1501 |  | 
| 1502 |     QCOMPARE(painted.x(), rect.x()); | 
| 1503 |     QCOMPARE(painted.y(), rect.y() + (usePen ? 0 : 1)); | 
| 1504 |     QCOMPARE(painted.width(), size.width() + (usePen ? 1 : 0)); | 
| 1505 |     QCOMPARE(painted.height(), size.height() + (usePen ? 1 : -1)); | 
| 1506 | } | 
| 1507 |  | 
| 1508 | void tst_QPainter::drawClippedEllipse_data() | 
| 1509 | { | 
| 1510 |     QTest::addColumn<QRect>(name: "rect" ); | 
| 1511 |  | 
| 1512 |     for (int w = 20; w < 128; w += 7) { | 
| 1513 |         const QByteArray wB = QByteArray::number(w); | 
| 1514 |         for (int h = w/2; h < qMin(a: 2*w, b: 128); h += 13) { | 
| 1515 |             const QByteArray sB = wB + 'x' + QByteArray::number(h); | 
| 1516 |             QTest::newRow(dataTag: (sB + " top" ).constData()) << QRect(0, -h/2, w, h); | 
| 1517 |             QTest::newRow(dataTag: (sB + " topright" ).constData()) << QRect(w/2, -h/2, w, h); | 
| 1518 |             QTest::newRow(dataTag: (sB + " right" ).constData()) << QRect(w/2, 0, w, h); | 
| 1519 |             QTest::newRow(dataTag: (sB + " bottomright" ).constData()) << QRect(w/2, h/2, w, h); | 
| 1520 |             QTest::newRow(dataTag: (sB + " bottom" ).constData()) << QRect(0, h/2, w, h); | 
| 1521 |             QTest::newRow(dataTag: (sB + " bottomleft" ).constData()) << QRect(-w/2, h/2, w, h); | 
| 1522 |             QTest::newRow(dataTag: (sB + " left" ).constData()) << QRect(-w/2, 0, w, h); | 
| 1523 |             QTest::newRow(dataTag: (sB + " topleft" ).constData()) << QRect(-w/2, -h/2, w, h); | 
| 1524 |         } | 
| 1525 |     } | 
| 1526 | } | 
| 1527 |  | 
| 1528 | void tst_QPainter::drawClippedEllipse() | 
| 1529 | { | 
| 1530 |     QFETCH(QRect, rect); | 
| 1531 |     if (sizeof(qreal) != sizeof(double)) | 
| 1532 |         QSKIP("Test only works for qreal==double" ); | 
| 1533 |     QImage image(rect.width() + 1, rect.height() + 1, | 
| 1534 |                  QImage::Format_ARGB32_Premultiplied); | 
| 1535 |     QRect expected = QRect(rect.x(), rect.y(), rect.width()+1, rect.height()+1) | 
| 1536 |                      & QRect(0, 0, image.width(), image.height()); | 
| 1537 |  | 
| 1538 |  | 
| 1539 |     image.fill(pixel: QColor(Qt::white).rgb()); | 
| 1540 |     QPainter p(&image); | 
| 1541 |     p.drawEllipse(r: rect); | 
| 1542 |     p.end(); | 
| 1543 |  | 
| 1544 |     QPixmap pixmap = QPixmap::fromImage(image); | 
| 1545 |     const QRect painted = getPaintedSize(pm: pixmap, background: Qt::white); | 
| 1546 |  | 
| 1547 |     QCOMPARE(painted.x(), expected.x()); | 
| 1548 |     QCOMPARE(painted.y(), expected.y()); | 
| 1549 |     QCOMPARE(painted.width(), expected.width()); | 
| 1550 |     QCOMPARE(painted.height(), expected.height()); | 
| 1551 |  | 
| 1552 | } | 
| 1553 |  | 
| 1554 | #if QT_DEPRECATED_SINCE(5, 13) | 
| 1555 | void tst_QPainter::drawRoundRect() | 
| 1556 | { | 
| 1557 |     QFETCH(QRect, rect); | 
| 1558 |     QFETCH(bool, usePen); | 
| 1559 |  | 
| 1560 | #ifdef Q_OS_MAC | 
| 1561 |     if (QTest::currentDataTag() == QByteArray("rect(6, 12, 3, 14) with pen" ) || | 
| 1562 |         QTest::currentDataTag() == QByteArray("rect(6, 17, 3, 25) with pen" ) || | 
| 1563 |         QTest::currentDataTag() == QByteArray("rect(10, 6, 10, 3) with pen" ) || | 
| 1564 |         QTest::currentDataTag() == QByteArray("rect(10, 12, 10, 14) with pen" ) || | 
| 1565 |         QTest::currentDataTag() == QByteArray("rect(13, 45, 17, 80) with pen" ) || | 
| 1566 |         QTest::currentDataTag() == QByteArray("rect(13, 50, 17, 91) with pen" ) || | 
| 1567 |         QTest::currentDataTag() == QByteArray("rect(17, 6, 24, 3) with pen" ) || | 
| 1568 |         QTest::currentDataTag() == QByteArray("rect(24, 12, 38, 14) with pen" )) | 
| 1569 |         QSKIP("The Mac paint engine is off-by-one on certain rect sizes" ); | 
| 1570 | #endif | 
| 1571 |     QPixmap pixmap(rect.x() + rect.width() + 10, | 
| 1572 |                    rect.y() + rect.height() + 10); | 
| 1573 |     { | 
| 1574 |         pixmap.fill(fillColor: Qt::white); | 
| 1575 |         QPainter p(&pixmap); | 
| 1576 |         p.setRenderHint(hint: QPainter::Qt4CompatiblePainting); | 
| 1577 |         p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen)); | 
| 1578 |         p.setBrush(Qt::black); | 
| 1579 |         p.drawRoundRect(r: rect); | 
| 1580 |         p.end(); | 
| 1581 |  | 
| 1582 |         int increment = usePen ? 1 : 0; | 
| 1583 |  | 
| 1584 |         const QRect painted = getPaintedSize(pm: pixmap, background: Qt::white); | 
| 1585 |         QCOMPARE(painted.width(), rect.width() + increment); | 
| 1586 |         QCOMPARE(painted.height(), rect.height() + increment); | 
| 1587 |     } | 
| 1588 | } | 
| 1589 | #endif | 
| 1590 |  | 
| 1591 | void tst_QPainter::drawRoundedRect() | 
| 1592 | { | 
| 1593 |     QFETCH(QRect, rect); | 
| 1594 |     QFETCH(bool, usePen); | 
| 1595 |  | 
| 1596 | #ifdef Q_OS_DARWIN | 
| 1597 |     if (QTest::currentDataTag() == QByteArray("rect(6, 12, 3, 14) with pen" ) || | 
| 1598 |         QTest::currentDataTag() == QByteArray("rect(6, 17, 3, 25) with pen" ) || | 
| 1599 |         QTest::currentDataTag() == QByteArray("rect(10, 6, 10, 3) with pen" ) || | 
| 1600 |         QTest::currentDataTag() == QByteArray("rect(10, 12, 10, 14) with pen" ) || | 
| 1601 |         QTest::currentDataTag() == QByteArray("rect(13, 45, 17, 80) with pen" ) || | 
| 1602 |         QTest::currentDataTag() == QByteArray("rect(13, 50, 17, 91) with pen" ) || | 
| 1603 |         QTest::currentDataTag() == QByteArray("rect(17, 6, 24, 3) with pen" ) || | 
| 1604 |         QTest::currentDataTag() == QByteArray("rect(24, 12, 38, 14) with pen" )) | 
| 1605 |         QSKIP("The Mac paint engine is off-by-one on certain rect sizes" ); | 
| 1606 | #endif | 
| 1607 |     QPixmap pixmap(rect.x() + rect.width() + 10, | 
| 1608 |                    rect.y() + rect.height() + 10); | 
| 1609 |     { | 
| 1610 |         pixmap.fill(fillColor: Qt::white); | 
| 1611 |         QPainter p(&pixmap); | 
| 1612 |         p.setRenderHint(hint: QPainter::Qt4CompatiblePainting); | 
| 1613 |         p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen)); | 
| 1614 |         p.setBrush(Qt::black); | 
| 1615 |         p.drawRoundedRect(rect, xRadius: 25, yRadius: 25, mode: Qt::RelativeSize); | 
| 1616 |         p.end(); | 
| 1617 |  | 
| 1618 |         int increment = usePen ? 1 : 0; | 
| 1619 |  | 
| 1620 |         const QRect painted = getPaintedSize(pm: pixmap, background: Qt::white); | 
| 1621 |         QCOMPARE(painted.width(), rect.width() + increment); | 
| 1622 |         QCOMPARE(painted.height(), rect.height() + increment); | 
| 1623 |     } | 
| 1624 | } | 
| 1625 |  | 
| 1626 | void tst_QPainter::qimageFormats_data() | 
| 1627 | { | 
| 1628 |     QTest::addColumn<QImage::Format>(name: "format" ); | 
| 1629 |     QTest::newRow(dataTag: "QImage::Format_RGB32" ) << QImage::Format_RGB32; | 
| 1630 |     QTest::newRow(dataTag: "QImage::Format_ARGB32" ) << QImage::Format_ARGB32; | 
| 1631 |     QTest::newRow(dataTag: "QImage::Format_ARGB32_Premultiplied" ) << QImage::Format_ARGB32_Premultiplied; | 
| 1632 |     QTest::newRow(dataTag: "QImage::Format_RGB16" ) << QImage::Format_RGB16; | 
| 1633 |     QTest::newRow(dataTag: "Qimage::Format_ARGB8565_Premultiplied" ) << QImage::Format_ARGB8565_Premultiplied; | 
| 1634 |     QTest::newRow(dataTag: "Qimage::Format_RGB666" ) << QImage::Format_RGB666; | 
| 1635 |     QTest::newRow(dataTag: "Qimage::Format_RGB555" ) << QImage::Format_RGB555; | 
| 1636 |     QTest::newRow(dataTag: "Qimage::Format_ARGB8555_Premultiplied" ) << QImage::Format_ARGB8555_Premultiplied; | 
| 1637 |     QTest::newRow(dataTag: "Qimage::Format_RGB888" ) << QImage::Format_RGB888; | 
| 1638 |     QTest::newRow(dataTag: "Qimage::Format_BGR888" ) << QImage::Format_BGR888; | 
| 1639 |     QTest::newRow(dataTag: "Qimage::Format_A2RGB30_Premultiplied" ) << QImage::Format_A2RGB30_Premultiplied; | 
| 1640 |     QTest::newRow(dataTag: "Qimage::Format_RGB30" ) << QImage::Format_RGB30; | 
| 1641 | } | 
| 1642 |  | 
| 1643 | /* | 
| 1644 |     Tests that QPainter can paint on various QImage formats. | 
| 1645 | */ | 
| 1646 | void tst_QPainter::qimageFormats() | 
| 1647 | { | 
| 1648 |     QFETCH(QImage::Format, format); | 
| 1649 |  | 
| 1650 |     const QSize size(100, 100); | 
| 1651 |     QImage image(size, format); | 
| 1652 |     image.fill(pixel: 0); | 
| 1653 |  | 
| 1654 |     const QColor testColor(Qt::red); | 
| 1655 |     QPainter p(&image); | 
| 1656 |     QVERIFY(p.isActive()); | 
| 1657 |     p.setBrush(QBrush(testColor)); | 
| 1658 |     p.drawRect(r: QRect(QPoint(0,0), size)); | 
| 1659 |     QCOMPARE(image.pixel(50, 50), testColor.rgb()); | 
| 1660 | } | 
| 1661 |  | 
| 1662 | void tst_QPainter::fillData() | 
| 1663 | { | 
| 1664 |     QTest::addColumn<QRect>(name: "rect" ); | 
| 1665 |     QTest::addColumn<bool>(name: "usePen" ); | 
| 1666 |  | 
| 1667 |     for (int w = 3; w < 50; w += 7) { | 
| 1668 |         const QByteArray wB = QByteArray::number(w); | 
| 1669 |         for (int h = 3; h < 50; h += 11) { | 
| 1670 |             int x = w/2 + 5; | 
| 1671 |             int y = h/2 + 5; | 
| 1672 |             const QByteArray rB = "rect("  + QByteArray::number(x) + ", "  + QByteArray::number(y) | 
| 1673 |                 + ", "  + QByteArray::number(w) + ", "  + QByteArray::number(h) + ')'; | 
| 1674 |             QTest::newRow(dataTag: (rB + " with pen" ).constData()) << QRect(x, y, w, h) << true; | 
| 1675 |             QTest::newRow(dataTag: (rB + " no pen" ).constData()) << QRect(x, y, w, h) << false; | 
| 1676 |         } | 
| 1677 |     } | 
| 1678 | } | 
| 1679 |  | 
| 1680 | /* | 
| 1681 |     Test that drawline works properly after setWindow has been called. | 
| 1682 | */ | 
| 1683 | void tst_QPainter::setWindow() | 
| 1684 | { | 
| 1685 |     QPixmap pixmap(600, 600); | 
| 1686 |     pixmap.fill(fillColor: QColor(Qt::white)); | 
| 1687 |  | 
| 1688 |     QPainter painter(&pixmap); | 
| 1689 |     painter.setRenderHint(hint: QPainter::Qt4CompatiblePainting); | 
| 1690 |     painter.setWindow(x: 0, y: 0, w: 3, h: 3); | 
| 1691 |     painter.drawLine(x1: 1, y1: 1, x2: 2, y2: 2); | 
| 1692 |  | 
| 1693 |     const QRect painted = getPaintedSize(pm: pixmap, background: Qt::white); | 
| 1694 |     QVERIFY(195 < painted.y() && painted.y() < 205); // correct value is around 200 | 
| 1695 |     QVERIFY(195 < painted.height() && painted.height() < 205); // correct value is around 200 | 
| 1696 | } | 
| 1697 |  | 
| 1698 | void tst_QPainter::combinedMatrix() | 
| 1699 | { | 
| 1700 |     QPixmap pm(64, 64); | 
| 1701 |  | 
| 1702 |     QPainter p(&pm); | 
| 1703 |     p.setWindow(x: 0, y: 0, w: 1, h: 1); | 
| 1704 |     p.setViewport(x: 32, y: 0, w: 32, h: 32); | 
| 1705 |  | 
| 1706 |     p.translate(dx: 0.5, dy: 0.5); | 
| 1707 |  | 
| 1708 |     QTransform ct = p.combinedTransform(); | 
| 1709 | #if QT_DEPRECATED_SINCE(5, 13) | 
| 1710 | QT_WARNING_PUSH | 
| 1711 | QT_WARNING_DISABLE_DEPRECATED | 
| 1712 |     QMatrix cm = p.combinedMatrix(); | 
| 1713 |     QCOMPARE(cm, ct.toAffine()); | 
| 1714 | QT_WARNING_POP | 
| 1715 | #endif | 
| 1716 |  | 
| 1717 |     QPointF pt = QPointF(0, 0) * ct.toAffine(); | 
| 1718 |  | 
| 1719 |     QCOMPARE(pt.x(), 48.0); | 
| 1720 |     QCOMPARE(pt.y(), 16.0); | 
| 1721 | } | 
| 1722 |  | 
| 1723 | void tst_QPainter::textOnTransparentImage() | 
| 1724 | { | 
| 1725 |     bool foundPixel = false; | 
| 1726 |     QImage image(10, 10, QImage::Format_ARGB32_Premultiplied); | 
| 1727 |     image.fill(pixel: qRgba(r: 0, g: 0, b: 0, a: 0)); // transparent | 
| 1728 |     { | 
| 1729 |         QPainter painter(&image); | 
| 1730 |         painter.setPen(QColor(255, 255, 255)); | 
| 1731 |         painter.drawText(x: 0, y: 10, s: "W" ); | 
| 1732 |     } | 
| 1733 |     for (int x = 0; x < image.width(); ++x) | 
| 1734 |         for (int y = 0; y < image.height(); ++y) | 
| 1735 |             if (image.pixel(x, y) != 0) | 
| 1736 |                 foundPixel = true; | 
| 1737 |     QVERIFY(foundPixel); | 
| 1738 | } | 
| 1739 |  | 
| 1740 | void tst_QPainter::renderHints() | 
| 1741 | { | 
| 1742 |     QImage img(1, 1, QImage::Format_RGB32); | 
| 1743 |  | 
| 1744 |     QPainter p(&img); | 
| 1745 |  | 
| 1746 |     // Turn off all... | 
| 1747 |     p.setRenderHints(hints: QPainter::RenderHints(0xffffffff), on: false); | 
| 1748 |     QCOMPARE(p.renderHints(), QPainter::RenderHints{}); | 
| 1749 |  | 
| 1750 |     // Single set/get | 
| 1751 |     p.setRenderHint(hint: QPainter::Antialiasing); | 
| 1752 |     QVERIFY(p.renderHints() & QPainter::Antialiasing); | 
| 1753 |  | 
| 1754 |     p.setRenderHint(hint: QPainter::Antialiasing, on: false); | 
| 1755 |     QVERIFY(!(p.renderHints() & QPainter::Antialiasing)); | 
| 1756 |  | 
| 1757 |     // Multi set/get | 
| 1758 |     p.setRenderHints(hints: QPainter::Antialiasing | QPainter::SmoothPixmapTransform); | 
| 1759 |     QVERIFY(p.renderHints() & (QPainter::Antialiasing | QPainter::SmoothPixmapTransform)); | 
| 1760 |  | 
| 1761 |     p.setRenderHints(hints: QPainter::Antialiasing | QPainter::SmoothPixmapTransform, on: false); | 
| 1762 |     QVERIFY(!(p.renderHints() & (QPainter::Antialiasing | QPainter::SmoothPixmapTransform))); | 
| 1763 | } | 
| 1764 |  | 
| 1765 | int countPixels(const QImage &img, const QRgb &color) | 
| 1766 | { | 
| 1767 |     int count = 0; | 
| 1768 |     for (int y = 0; y < img.height(); ++y) { | 
| 1769 |         for (int x = 0; x < img.width(); ++x) { | 
| 1770 |             count += ((img.pixel(x, y) & 0xffffff) == color); | 
| 1771 |         } | 
| 1772 |     } | 
| 1773 |     return count; | 
| 1774 | } | 
| 1775 |  | 
| 1776 | template <typename T> | 
| 1777 | void testClipping(QImage &img) | 
| 1778 | { | 
| 1779 |     QPainterPath a, b; | 
| 1780 |     a.addRect(rect: QRect(2, 2, 4, 4)); | 
| 1781 |     b.addRect(rect: QRect(4, 4, 4, 4)); | 
| 1782 |     QPainter p(&img); | 
| 1783 |  | 
| 1784 |     p.end(); | 
| 1785 |     img.fill(pixel: 0x0); | 
| 1786 |     p.begin(&img); | 
| 1787 |     p.setClipPath(path: a); | 
| 1788 |     p.setClipPath(path: b, op: Qt::IntersectClip); | 
| 1789 |  | 
| 1790 |     p.setClipping(false); | 
| 1791 |     p.setPen(Qt::NoPen); | 
| 1792 |     p.setBrush(QColor(0xff0000)); | 
| 1793 |     p.drawRect(T(0, 0, 10, 10)); | 
| 1794 |  | 
| 1795 |     p.setClipping(true); | 
| 1796 |     p.setBrush(QColor(0x00ff00)); | 
| 1797 |     p.drawRect(T(0, 0, 10, 10)); | 
| 1798 |  | 
| 1799 |     QCOMPARE(countPixels(img, 0xff0000), 96); | 
| 1800 |     QCOMPARE(countPixels(img, 0x00ff00), 4); | 
| 1801 | } | 
| 1802 |  | 
| 1803 | void tst_QPainter::disableEnableClipping() | 
| 1804 | { | 
| 1805 |     QImage img(10, 10, QImage::Format_RGB32); | 
| 1806 |  | 
| 1807 |     testClipping<QRectF>(img); | 
| 1808 |     testClipping<QRect>(img); | 
| 1809 | } | 
| 1810 |  | 
| 1811 | void tst_QPainter::setClipRect() | 
| 1812 | { | 
| 1813 |     QImage img(10, 10, QImage::Format_RGB32); | 
| 1814 |     // simple test to let valgrind check for buffer overflow | 
| 1815 |     { | 
| 1816 |         QPainter p(&img); | 
| 1817 |         p.setClipRect(x: -10, y: -10, w: 100, h: 100); | 
| 1818 |         p.fillRect(x: -10, y: -10, w: 100, h: 100, b: QBrush(QColor(Qt::red))); | 
| 1819 |     } | 
| 1820 |  | 
| 1821 |     // rects with negative width/height | 
| 1822 |     { | 
| 1823 |         QPainter p(&img); | 
| 1824 |         p.setClipRect(QRect(10, 10, -10, 10)); | 
| 1825 |         QVERIFY(p.clipRegion().isEmpty()); | 
| 1826 |         p.setClipRect(QRect(10, 10, 10, -10)); | 
| 1827 |         QVERIFY(p.clipRegion().isEmpty()); | 
| 1828 |         p.setClipRect(QRectF(10.5, 10.5, -10.5, 10.5)); | 
| 1829 |         QVERIFY(p.clipRegion().isEmpty()); | 
| 1830 |         p.setClipRect(QRectF(10.5, 10.5, 10.5, -10.5)); | 
| 1831 |         QVERIFY(p.clipRegion().isEmpty()); | 
| 1832 |     } | 
| 1833 | } | 
| 1834 |  | 
| 1835 | /* | 
| 1836 |     Verify that the clipping works correctly. | 
| 1837 |     The red outline should be covered by the blue rect on top and left, | 
| 1838 |     while it should be clipped on the right and bottom and thus the red outline be visible | 
| 1839 |  | 
| 1840 |     See: QTBUG-83229 | 
| 1841 | */ | 
| 1842 | void tst_QPainter::clipRect() | 
| 1843 | { | 
| 1844 |     int width = 654; | 
| 1845 |     int height = 480; | 
| 1846 |     QRect rect(0, 0, width, height); | 
| 1847 |  | 
| 1848 |     QImage image(width, height, QImage::Format_ARGB32); | 
| 1849 |     QPainter p(&image); | 
| 1850 |     qreal halfWidth = width / 2.0; | 
| 1851 |     qreal halfHeight = height / 2.0; | 
| 1852 |  | 
| 1853 |     QRectF clipRect = QRectF(halfWidth - halfWidth / 2.0, halfHeight - halfHeight / 2.0, | 
| 1854 |                              halfWidth / 2.0, halfHeight / 2.0); | 
| 1855 |  | 
| 1856 |     p.fillRect(r: rect, c: Qt::white); | 
| 1857 |     p.setPen(Qt::red); | 
| 1858 |     p.drawRect(rect: clipRect); | 
| 1859 |  | 
| 1860 |     p.setClipRect(clipRect, op: Qt::ReplaceClip); | 
| 1861 |     p.fillRect(r: rect, c: Qt::blue); | 
| 1862 |  | 
| 1863 |     p.end(); | 
| 1864 |  | 
| 1865 |     QCOMPARE(image.pixelColor(clipRect.left() + 1, clipRect.top()), QColor(Qt::blue)); | 
| 1866 |     QCOMPARE(image.pixelColor(clipRect.left(), clipRect.top() + 1), QColor(Qt::blue)); | 
| 1867 |     QCOMPARE(image.pixelColor(clipRect.left() + 1, clipRect.bottom()), QColor(Qt::red)); | 
| 1868 |     QCOMPARE(image.pixelColor(clipRect.right(), clipRect.top() + 1), QColor(Qt::red)); | 
| 1869 | } | 
| 1870 |  | 
| 1871 | /* | 
| 1872 |     This tests the two different clipping approaches in QRasterPaintEngine, | 
| 1873 |     one when using a QRegion and one when using a QPainterPath. They should | 
| 1874 |     give equal results. | 
| 1875 | */ | 
| 1876 | void tst_QPainter::setEqualClipRegionAndPath_data() | 
| 1877 | { | 
| 1878 |     QTest::addColumn<QSize>(name: "deviceSize" ); | 
| 1879 |     QTest::addColumn<QRegion>(name: "region" ); | 
| 1880 |  | 
| 1881 |     QTest::newRow(dataTag: "empty" ) << QSize(100, 100) << QRegion(); | 
| 1882 |     QTest::newRow(dataTag: "simple rect" ) << QSize(100, 100) | 
| 1883 |                                  << QRegion(QRect(5, 5, 10, 10)); | 
| 1884 |  | 
| 1885 |     QVector<QRect> rects; | 
| 1886 |     QRegion region; | 
| 1887 |  | 
| 1888 |     rects << QRect(5, 5, 10, 10) << QRect(20, 20, 10, 10); | 
| 1889 |     region.setRects(rect: rects.constData(), num: rects.size()); | 
| 1890 |     QTest::newRow(dataTag: "two rects" ) << QSize(100, 100) << region; | 
| 1891 |  | 
| 1892 |     rects.clear(); | 
| 1893 |     rects << QRect(5, 5, 10, 10) << QRect(20, 5, 10, 10); | 
| 1894 |     region.setRects(rect: rects.constData(), num: rects.size()); | 
| 1895 |     QTest::newRow(dataTag: "two x-adjacent rects" ) << QSize(100, 100) << region; | 
| 1896 |  | 
| 1897 |     rects.clear(); | 
| 1898 |     rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100); | 
| 1899 |     region.setRects(rect: rects.constData(), num: rects.size()); | 
| 1900 |     QTest::newRow(dataTag: "two x-adjacent rects 2" ) << QSize(100, 100) << region; | 
| 1901 |  | 
| 1902 |     rects.clear(); | 
| 1903 |     rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100); | 
| 1904 |     region.setRects(rect: rects.constData(), num: rects.size()); | 
| 1905 |     QTest::newRow(dataTag: "two x-adjacent rects 3" ) << QSize(50, 50) << region; | 
| 1906 |  | 
| 1907 |     rects.clear(); | 
| 1908 |     rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100); | 
| 1909 |     region.setRects(rect: rects.constData(), num: rects.size()); | 
| 1910 |     QTest::newRow(dataTag: "two x-adjacent rects 4" ) << QSize(101, 101) << region; | 
| 1911 |  | 
| 1912 |     region = QRegion(QRect(0, 0, 200, 200), QRegion::Ellipse); | 
| 1913 |  | 
| 1914 |     QTest::newRow(dataTag: "ellipse" ) << QSize(190, 200) << region; | 
| 1915 |  | 
| 1916 |     region ^= QRect(50, 50, 50, 50); | 
| 1917 |     QTest::newRow(dataTag: "ellipse 2" ) << QSize(200, 200) << region; | 
| 1918 | } | 
| 1919 |  | 
| 1920 | void tst_QPainter::setEqualClipRegionAndPath() | 
| 1921 | { | 
| 1922 |     QFETCH(QSize, deviceSize); | 
| 1923 |     QFETCH(QRegion, region); | 
| 1924 |  | 
| 1925 |     QPainterPath path; | 
| 1926 |     path.addRegion(region); | 
| 1927 |  | 
| 1928 |     QImage img1(deviceSize.width(), deviceSize.height(), | 
| 1929 |                 QImage::Format_ARGB32); | 
| 1930 |     QImage img2(deviceSize.width(), deviceSize.height(), | 
| 1931 |                 QImage::Format_ARGB32); | 
| 1932 |     img1.fill(pixel: 0x12345678); | 
| 1933 |     img2.fill(pixel: 0x12345678); | 
| 1934 |  | 
| 1935 |     { | 
| 1936 |         QPainter p(&img1); | 
| 1937 |         p.setClipRegion(region); | 
| 1938 |         p.fillRect(x: 0, y: 0, w: img1.width(), h: img1.height(), b: QColor(Qt::red)); | 
| 1939 |     } | 
| 1940 |     { | 
| 1941 |         QPainter p(&img2); | 
| 1942 |         p.setClipPath(path); | 
| 1943 |         p.fillRect(x: 0, y: 0, w: img2.width(), h: img2.height(), b: QColor(Qt::red)); | 
| 1944 |     } | 
| 1945 |  | 
| 1946 |     QCOMPARE(img1, img2); | 
| 1947 |  | 
| 1948 |     // rotated | 
| 1949 |     img1.fill(pixel: 0x12345678); | 
| 1950 |     img2.fill(pixel: 0x12345678); | 
| 1951 |  | 
| 1952 |     { | 
| 1953 |         QPainter p(&img1); | 
| 1954 |         p.rotate(a: 25); | 
| 1955 |         p.setClipRegion(region); | 
| 1956 |         p.fillRect(x: 0, y: 0, w: img1.width(), h: img1.height(), b: QColor(Qt::red)); | 
| 1957 |     } | 
| 1958 |     { | 
| 1959 |         QPainter p(&img2); | 
| 1960 |         p.rotate(a: 25); | 
| 1961 |         p.setClipPath(path); | 
| 1962 |         p.fillRect(x: 0, y: 0, w: img2.width(), h: img2.height(), b: QColor(Qt::red)); | 
| 1963 |     } | 
| 1964 |  | 
| 1965 |     QCOMPARE(img1, img2); | 
| 1966 |  | 
| 1967 |     img1.fill(pixel: 0x12345678); | 
| 1968 |     img2.fill(pixel: 0x12345678); | 
| 1969 |  | 
| 1970 |     // simple intersectclip | 
| 1971 |     img1.fill(pixel: 0x12345678); | 
| 1972 |     img2.fill(pixel: 0x12345678); | 
| 1973 |     { | 
| 1974 |         QPainter p(&img1); | 
| 1975 |         p.setClipRegion(region); | 
| 1976 |         p.setClipRegion(region, op: Qt::IntersectClip); | 
| 1977 |         p.fillRect(x: 0, y: 0, w: img1.width(), h: img1.height(), b: QColor(Qt::red)); | 
| 1978 |     } | 
| 1979 |     { | 
| 1980 |         QPainter p(&img2); | 
| 1981 |         p.setClipPath(path); | 
| 1982 |         p.setClipPath(path, op: Qt::IntersectClip); | 
| 1983 |         p.fillRect(x: 0, y: 0, w: img2.width(), h: img2.height(), b: QColor(Qt::red)); | 
| 1984 |     } | 
| 1985 |     QCOMPARE(img1, img2); | 
| 1986 |  | 
| 1987 |     img1.fill(pixel: 0x12345678); | 
| 1988 |     img2.fill(pixel: 0x12345678); | 
| 1989 |     { | 
| 1990 |         QPainter p(&img1); | 
| 1991 |         p.setClipPath(path); | 
| 1992 |         p.setClipRegion(region, op: Qt::IntersectClip); | 
| 1993 |         p.fillRect(x: 0, y: 0, w: img1.width(), h: img1.height(), b: QColor(Qt::red)); | 
| 1994 |     } | 
| 1995 |     { | 
| 1996 |         QPainter p(&img2); | 
| 1997 |         p.setClipRegion(region); | 
| 1998 |         p.setClipPath(path, op: Qt::IntersectClip); | 
| 1999 |         p.fillRect(x: 0, y: 0, w: img2.width(), h: img2.height(), b: QColor(Qt::red)); | 
| 2000 |     } | 
| 2001 |     QCOMPARE(img1, img2); | 
| 2002 |  | 
| 2003 | } | 
| 2004 |  | 
| 2005 | void tst_QPainter::clippedFillPath_data() | 
| 2006 | { | 
| 2007 |     QTest::addColumn<QSize>(name: "imageSize" ); | 
| 2008 |     QTest::addColumn<QPainterPath>(name: "path" ); | 
| 2009 |     QTest::addColumn<QRect>(name: "clipRect" ); | 
| 2010 |     QTest::addColumn<QBrush>(name: "brush" ); | 
| 2011 |     QTest::addColumn<QPen>(name: "pen" ); | 
| 2012 |  | 
| 2013 |     QLinearGradient gradient(QPoint(0, 0), QPoint(100, 100)); | 
| 2014 |     gradient.setColorAt(pos: 0, color: Qt::red); | 
| 2015 |     gradient.setColorAt(pos: 1, color: Qt::blue); | 
| 2016 |  | 
| 2017 |  | 
| 2018 |     QPen pen2(QColor(223, 223, 0, 223)); | 
| 2019 |     pen2.setWidth(2); | 
| 2020 |  | 
| 2021 |     QPainterPath path; | 
| 2022 |     path.addRect(rect: QRect(15, 15, 50, 50)); | 
| 2023 |     QTest::newRow(dataTag: "simple rect 0" ) << QSize(100, 100) << path | 
| 2024 |                                    << QRect(15, 15, 49, 49) | 
| 2025 |                                    << QBrush(Qt::NoBrush) | 
| 2026 |                                    << QPen(Qt::black); | 
| 2027 |     QTest::newRow(dataTag: "simple rect 1" ) << QSize(100, 100) << path | 
| 2028 |                                    << QRect(15, 15, 50, 50) | 
| 2029 |                                    << QBrush(Qt::NoBrush) | 
| 2030 |                                    << QPen(Qt::black); | 
| 2031 |     QTest::newRow(dataTag: "simple rect 2" ) << QSize(100, 100) << path | 
| 2032 |                                    << QRect(15, 15, 51, 51) | 
| 2033 |                                    << QBrush(Qt::NoBrush) | 
| 2034 |                                    << QPen(Qt::black); | 
| 2035 |     QTest::newRow(dataTag: "simple rect 3" ) << QSize(100, 100) << path | 
| 2036 |                                    << QRect(15, 15, 51, 51) | 
| 2037 |                                    << QBrush(QColor(Qt::blue)) | 
| 2038 |                                    << QPen(Qt::NoPen); | 
| 2039 |     QTest::newRow(dataTag: "simple rect 4" ) << QSize(100, 100) << path | 
| 2040 |                                    << QRect(15, 15, 51, 51) | 
| 2041 |                                    << QBrush(gradient) | 
| 2042 |                                    << pen2; | 
| 2043 |  | 
| 2044 |     path = QPainterPath(); | 
| 2045 |     path.addEllipse(rect: QRect(15, 15, 50, 50)); | 
| 2046 |     QTest::newRow(dataTag: "ellipse 0" ) << QSize(100, 100) << path | 
| 2047 |                                << QRect(15, 15, 49, 49) | 
| 2048 |                                << QBrush(Qt::NoBrush) | 
| 2049 |                                << QPen(Qt::black); | 
| 2050 |     QTest::newRow(dataTag: "ellipse 1" ) << QSize(100, 100) << path | 
| 2051 |                                << QRect(15, 15, 50, 50) | 
| 2052 |                                << QBrush(Qt::NoBrush) | 
| 2053 |                                << QPen(Qt::black); | 
| 2054 |     QTest::newRow(dataTag: "ellipse 2" ) << QSize(100, 100) << path | 
| 2055 |                                << QRect(15, 15, 51, 51) | 
| 2056 |                                << QBrush(Qt::NoBrush) | 
| 2057 |                                << QPen(Qt::black); | 
| 2058 |     QTest::newRow(dataTag: "ellipse 3" ) << QSize(100, 100) << path | 
| 2059 |                                << QRect(15, 15, 51, 51) | 
| 2060 |                                << QBrush(QColor(Qt::blue)) | 
| 2061 |                                << QPen(Qt::NoPen); | 
| 2062 |     QTest::newRow(dataTag: "ellipse 4" ) << QSize(100, 100) << path | 
| 2063 |                                << QRect(15, 15, 51, 51) | 
| 2064 |                                << QBrush(gradient) | 
| 2065 |                                << pen2; | 
| 2066 |  | 
| 2067 |     path = QPainterPath(); | 
| 2068 |     path.addRoundedRect(rect: QRect(15, 15, 50, 50), xRadius: 20, yRadius: Qt::RelativeSize); | 
| 2069 |     QTest::newRow(dataTag: "round rect 0" ) << QSize(100, 100) << path | 
| 2070 |                                   << QRect(15, 15, 49, 49) | 
| 2071 |                                   << QBrush(Qt::NoBrush) | 
| 2072 |                                   << QPen(Qt::black); | 
| 2073 |     QTest::newRow(dataTag: "round rect 1" ) << QSize(100, 100) << path | 
| 2074 |                                   << QRect(15, 15, 50, 50) | 
| 2075 |                                   << QBrush(Qt::NoBrush) | 
| 2076 |                                   << QPen(Qt::black); | 
| 2077 |     QTest::newRow(dataTag: "round rect 2" ) << QSize(100, 100) << path | 
| 2078 |                                   << QRect(15, 15, 51, 51) | 
| 2079 |                                   << QBrush(Qt::NoBrush) | 
| 2080 |                                   << QPen(Qt::black); | 
| 2081 |     QTest::newRow(dataTag: "round rect 3" ) << QSize(100, 100) << path | 
| 2082 |                                   << QRect(15, 15, 51, 51) | 
| 2083 |                                   << QBrush(QColor(Qt::blue)) | 
| 2084 |                                   << QPen(Qt::NoPen); | 
| 2085 |     QTest::newRow(dataTag: "round rect 4" ) << QSize(100, 100) << path | 
| 2086 |                                   << QRect(15, 15, 51, 51) | 
| 2087 |                                   << QBrush(gradient) | 
| 2088 |                                   << pen2; | 
| 2089 |  | 
| 2090 |     path = QPainterPath(); | 
| 2091 |     path.moveTo(x: 15, y: 50); | 
| 2092 |     path.cubicTo(ctrlPt1x: 40, ctrlPt1y: 50, ctrlPt2x: 40, ctrlPt2y: 15, endPtx: 65, endPty: 50); | 
| 2093 |     path.lineTo(x: 15, y: 50); | 
| 2094 |     QTest::newRow(dataTag: "cubic 0" ) << QSize(100, 100) << path | 
| 2095 |                              << QRect(15, 15, 49, 49) | 
| 2096 |                              << QBrush(Qt::NoBrush) | 
| 2097 |                              << QPen(Qt::black); | 
| 2098 |     QTest::newRow(dataTag: "cubic 1" ) << QSize(100, 100) << path | 
| 2099 |                              << QRect(15, 15, 50, 50) | 
| 2100 |                              << QBrush(Qt::NoBrush) | 
| 2101 |                              << QPen(Qt::black); | 
| 2102 |     QTest::newRow(dataTag: "cubic 2" ) << QSize(100, 100) << path | 
| 2103 |                              << QRect(15, 15, 51, 51) | 
| 2104 |                              << QBrush(Qt::NoBrush) | 
| 2105 |                              << QPen(Qt::black); | 
| 2106 |     QTest::newRow(dataTag: "cubic 3" ) << QSize(100, 100) << path | 
| 2107 |                              << QRect(15, 15, 51, 51) | 
| 2108 |                              << QBrush(QColor(Qt::blue)) | 
| 2109 |                              << QPen(Qt::NoPen); | 
| 2110 |     QTest::newRow(dataTag: "cubic 4" ) << QSize(100, 100) << path | 
| 2111 |                              << QRect(15, 15, 51, 51) | 
| 2112 |                              << QBrush(gradient) | 
| 2113 |                              << pen2; | 
| 2114 | } | 
| 2115 |  | 
| 2116 | void tst_QPainter::clippedFillPath() | 
| 2117 | { | 
| 2118 |     QFETCH(QSize, imageSize); | 
| 2119 |     QFETCH(QPainterPath, path); | 
| 2120 |     QFETCH(QRect, clipRect); | 
| 2121 |     QPainterPath clipPath; | 
| 2122 |     clipPath.addRect(rect: clipRect); | 
| 2123 |     QFETCH(QBrush, brush); | 
| 2124 |     QFETCH(QPen, pen); | 
| 2125 |  | 
| 2126 |     const int width = imageSize.width(); | 
| 2127 |     const int height = imageSize.height(); | 
| 2128 |  | 
| 2129 |     QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied); | 
| 2130 |     clippedRect.fill(pixel: 0x12345678); | 
| 2131 |     { | 
| 2132 |         QPainter painter(&clippedRect); | 
| 2133 |         painter.setPen(pen); | 
| 2134 |         painter.setBrush(brush); | 
| 2135 |         painter.setClipRect(clipRect); | 
| 2136 |         painter.drawPath(path); | 
| 2137 |     } | 
| 2138 |  | 
| 2139 |     QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied); | 
| 2140 |     clippedPath.fill(pixel: 0x12345678); | 
| 2141 |     { | 
| 2142 |         QPainter painter(&clippedPath); | 
| 2143 |         painter.setPen(pen); | 
| 2144 |         painter.setBrush(brush); | 
| 2145 |         painter.setClipPath(path: clipPath); | 
| 2146 |         painter.drawPath(path); | 
| 2147 |     } | 
| 2148 |  | 
| 2149 |     QCOMPARE(clippedRect, clippedPath); | 
| 2150 |  | 
| 2151 |     // repeat with antialiasing | 
| 2152 |  | 
| 2153 |     clippedRect.fill(pixel: 0x12345678); | 
| 2154 |     { | 
| 2155 |         QPainter painter(&clippedRect); | 
| 2156 |         painter.setRenderHint(hint: QPainter::Antialiasing); | 
| 2157 |         painter.setPen(pen); | 
| 2158 |         painter.setBrush(brush); | 
| 2159 |         painter.setClipRect(clipRect); | 
| 2160 |         painter.drawPath(path); | 
| 2161 |     } | 
| 2162 |  | 
| 2163 |     clippedPath.fill(pixel: 0x12345678); | 
| 2164 |     { | 
| 2165 |         QPainter painter(&clippedPath); | 
| 2166 |         painter.setRenderHint(hint: QPainter::Antialiasing); | 
| 2167 |         painter.setPen(pen); | 
| 2168 |         painter.setBrush(brush); | 
| 2169 |         painter.setClipPath(path: clipPath); | 
| 2170 |         painter.drawPath(path); | 
| 2171 |     } | 
| 2172 |  | 
| 2173 |     QCOMPARE(clippedRect, clippedPath); | 
| 2174 | } | 
| 2175 |  | 
| 2176 | void tst_QPainter::clippedLines_data() | 
| 2177 | { | 
| 2178 |     QTest::addColumn<QSize>(name: "imageSize" ); | 
| 2179 |     QTest::addColumn<QLineF>(name: "line" ); | 
| 2180 |     QTest::addColumn<QRect>(name: "clipRect" ); | 
| 2181 |     QTest::addColumn<QPen>(name: "pen" ); | 
| 2182 |  | 
| 2183 |     QPen pen2(QColor(223, 223, 0, 223)); | 
| 2184 |     pen2.setWidth(2); | 
| 2185 |  | 
| 2186 |     QVector<QLineF> lines; | 
| 2187 |     lines << QLineF(15, 15, 65, 65) | 
| 2188 |           << QLineF(14, 14, 66, 66) | 
| 2189 |           << QLineF(16, 16, 64, 64) | 
| 2190 |           << QLineF(65, 65, 15, 15) | 
| 2191 |           << QLineF(66, 66, 14, 14) | 
| 2192 |           << QLineF(64, 64, 14, 14) | 
| 2193 |           << QLineF(15, 50, 15, 64) | 
| 2194 |           << QLineF(15, 50, 15, 65) | 
| 2195 |           << QLineF(15, 50, 15, 66) | 
| 2196 |           << QLineF(15, 50, 64, 50) | 
| 2197 |           << QLineF(15, 50, 65, 50) | 
| 2198 |           << QLineF(15, 50, 66, 50); | 
| 2199 |  | 
| 2200 |     foreach (QLineF line, lines) { | 
| 2201 |         const QByteArray desc = "line ("  + QByteArray::number(line.x1()) | 
| 2202 |             + ", "  + QByteArray::number(line.y1()) + ", "  | 
| 2203 |             + QByteArray::number(line.x2()) + ", "  + QByteArray::number(line.y2()) | 
| 2204 |             + ") " ; | 
| 2205 |         QTest::newRow(dataTag: (desc + '0').constData()) << QSize(100, 100) << line | 
| 2206 |                                    << QRect(15, 15, 49, 49) | 
| 2207 |                                    << QPen(Qt::black); | 
| 2208 |         QTest::newRow(dataTag: (desc + '1').constData()) << QSize(100, 100) << line | 
| 2209 |                                    << QRect(15, 15, 50, 50) | 
| 2210 |                                    << QPen(Qt::black); | 
| 2211 |         QTest::newRow(dataTag: (desc + '2').constData()) << QSize(100, 100) << line | 
| 2212 |                                    << QRect(15, 15, 51, 51) | 
| 2213 |                                    << QPen(Qt::black); | 
| 2214 |         QTest::newRow(dataTag: (desc + '3').constData()) << QSize(100, 100) << line | 
| 2215 |                                    << QRect(15, 15, 51, 51) | 
| 2216 |                                    << QPen(Qt::NoPen); | 
| 2217 |         QTest::newRow(dataTag: (desc + '4').constData()) << QSize(100, 100) << line | 
| 2218 |                                    << QRect(15, 15, 51, 51) | 
| 2219 |                                    << pen2; | 
| 2220 |     } | 
| 2221 | } | 
| 2222 |  | 
| 2223 | void tst_QPainter::clippedLines() | 
| 2224 | { | 
| 2225 |     QFETCH(QSize, imageSize); | 
| 2226 |     QFETCH(QLineF, line); | 
| 2227 |     QFETCH(QRect, clipRect); | 
| 2228 |     QPainterPath clipPath; | 
| 2229 |     clipPath.addRect(rect: clipRect); | 
| 2230 |     QFETCH(QPen, pen); | 
| 2231 |  | 
| 2232 |     const int width = imageSize.width(); | 
| 2233 |     const int height = imageSize.height(); | 
| 2234 |  | 
| 2235 |     QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied); | 
| 2236 |     clippedRect.fill(pixel: 0x12345678); | 
| 2237 |     { | 
| 2238 |         QPainter painter(&clippedRect); | 
| 2239 |         painter.setPen(pen); | 
| 2240 |         painter.setClipRect(clipRect); | 
| 2241 |         painter.drawLine(l: line); | 
| 2242 |         painter.drawLine(line: line.toLine()); | 
| 2243 |     } | 
| 2244 |  | 
| 2245 |     QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied); | 
| 2246 |     clippedPath.fill(pixel: 0x12345678); | 
| 2247 |     { | 
| 2248 |         QPainter painter(&clippedPath); | 
| 2249 |         painter.setPen(pen); | 
| 2250 |         painter.setClipPath(path: clipPath); | 
| 2251 |         painter.drawLine(l: line); | 
| 2252 |         painter.drawLine(line: line.toLine()); | 
| 2253 |     } | 
| 2254 |  | 
| 2255 |     QCOMPARE(clippedRect, clippedPath); | 
| 2256 |  | 
| 2257 |     // repeat with antialiasing | 
| 2258 |     clippedRect.fill(pixel: 0x12345678); | 
| 2259 |     { | 
| 2260 |         QPainter painter(&clippedRect); | 
| 2261 |         painter.setRenderHint(hint: QPainter::Antialiasing); | 
| 2262 |         painter.setPen(pen); | 
| 2263 |         painter.setClipRect(clipRect); | 
| 2264 |         painter.drawLine(l: line); | 
| 2265 |         painter.drawLine(line: line.toLine()); | 
| 2266 |     } | 
| 2267 |  | 
| 2268 |     clippedPath.fill(pixel: 0x12345678); | 
| 2269 |     { | 
| 2270 |         QPainter painter(&clippedPath); | 
| 2271 |         painter.setRenderHint(hint: QPainter::Antialiasing); | 
| 2272 |         painter.setPen(pen); | 
| 2273 |         painter.setClipPath(path: clipPath); | 
| 2274 |         painter.drawLine(l: line); | 
| 2275 |         painter.drawLine(line: line.toLine()); | 
| 2276 |     } | 
| 2277 |  | 
| 2278 |     QCOMPARE(clippedRect, clippedPath); | 
| 2279 | } | 
| 2280 |  | 
| 2281 | void tst_QPainter::clippedPolygon_data() | 
| 2282 | { | 
| 2283 |     clippedFillPath_data(); | 
| 2284 | }; | 
| 2285 |  | 
| 2286 | void tst_QPainter::clippedPolygon() | 
| 2287 | { | 
| 2288 |     QFETCH(QSize, imageSize); | 
| 2289 |     QFETCH(QPainterPath, path); | 
| 2290 |     QPolygonF polygon = path.toFillPolygon(matrix: QTransform()); | 
| 2291 |     QFETCH(QRect, clipRect); | 
| 2292 |     QPainterPath clipPath; | 
| 2293 |     clipPath.addRect(rect: clipRect); | 
| 2294 |     QFETCH(QPen, pen); | 
| 2295 |     QFETCH(QBrush, brush); | 
| 2296 |  | 
| 2297 |     const int width = imageSize.width(); | 
| 2298 |     const int height = imageSize.height(); | 
| 2299 |  | 
| 2300 |     QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied); | 
| 2301 |     clippedRect.fill(pixel: 0x12345678); | 
| 2302 |     { | 
| 2303 |         QPainter painter(&clippedRect); | 
| 2304 |         painter.setPen(pen); | 
| 2305 |         painter.setBrush(brush); | 
| 2306 |         painter.setClipRect(clipRect); | 
| 2307 |         painter.drawPolygon(polygon); | 
| 2308 |         painter.drawPolygon(polygon: polygon.toPolygon()); | 
| 2309 |     } | 
| 2310 |  | 
| 2311 |     QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied); | 
| 2312 |     clippedPath.fill(pixel: 0x12345678); | 
| 2313 |     { | 
| 2314 |         QPainter painter(&clippedPath); | 
| 2315 |         painter.setPen(pen); | 
| 2316 |         painter.setBrush(brush); | 
| 2317 |         painter.setClipRect(clipRect); | 
| 2318 |         painter.drawPolygon(polygon); | 
| 2319 |         painter.drawPolygon(polygon: polygon.toPolygon()); | 
| 2320 |     } | 
| 2321 |  | 
| 2322 |     QCOMPARE(clippedRect, clippedPath); | 
| 2323 |  | 
| 2324 |     // repeat with antialiasing | 
| 2325 |  | 
| 2326 |     clippedRect.fill(pixel: 0x12345678); | 
| 2327 |     { | 
| 2328 |         QPainter painter(&clippedRect); | 
| 2329 |         painter.setRenderHint(hint: QPainter::Antialiasing); | 
| 2330 |         painter.setPen(pen); | 
| 2331 |         painter.setBrush(brush); | 
| 2332 |         painter.setClipRect(clipRect); | 
| 2333 |         painter.drawPolygon(polygon); | 
| 2334 |         painter.drawPolygon(polygon: polygon.toPolygon()); | 
| 2335 |     } | 
| 2336 |  | 
| 2337 |     clippedPath.fill(pixel: 0x12345678); | 
| 2338 |     { | 
| 2339 |         QPainter painter(&clippedPath); | 
| 2340 |         painter.setRenderHint(hint: QPainter::Antialiasing); | 
| 2341 |         painter.setPen(pen); | 
| 2342 |         painter.setBrush(brush); | 
| 2343 |         painter.setClipRect(clipRect); | 
| 2344 |         painter.drawPolygon(polygon); | 
| 2345 |         painter.drawPolygon(polygon: polygon.toPolygon()); | 
| 2346 |     } | 
| 2347 |  | 
| 2348 |     QCOMPARE(clippedRect, clippedPath); | 
| 2349 | } | 
| 2350 |  | 
| 2351 | // this just draws some text that should be clipped in the raster | 
| 2352 | // paint engine. | 
| 2353 | void tst_QPainter::clippedText() | 
| 2354 | { | 
| 2355 |     for (char ch = 'A'; ch < 'Z'; ++ch) { | 
| 2356 |         //qDebug() << ch; | 
| 2357 |         QFont f; | 
| 2358 |         f.setPixelSize(24); | 
| 2359 |         QFontMetrics metrics(f); | 
| 2360 |         QRect textRect = metrics.boundingRect(QChar(ch)); | 
| 2361 |  | 
| 2362 |         if (textRect.width() <= 8) | 
| 2363 |             continue; | 
| 2364 |         if (textRect.height() <= 8) | 
| 2365 |             continue; | 
| 2366 |  | 
| 2367 |         QRect imageRect = textRect.adjusted(xp1: 4, yp1: 4, xp2: -4, yp2: -4); | 
| 2368 |  | 
| 2369 |         QImage image(imageRect.size(), QImage::Format_ARGB32_Premultiplied); | 
| 2370 |  | 
| 2371 |         image.fill(pixel: qRgba(r: 255, g: 255, b: 255, a: 255)); | 
| 2372 |         { | 
| 2373 |             QPainter painter(&image); | 
| 2374 |             painter.setFont(f); | 
| 2375 |             painter.setPen(Qt::black); | 
| 2376 |  | 
| 2377 |             painter.drawText(x: 0, y: 0, s: QChar(ch)); | 
| 2378 |         } | 
| 2379 |  | 
| 2380 |         image.fill(pixel: qRgba(r: 255, g: 255, b: 255, a: 255)); | 
| 2381 |         { | 
| 2382 |             QPainter painter(&image); | 
| 2383 |             painter.setFont(f); | 
| 2384 |             painter.setPen(Qt::black); | 
| 2385 |  | 
| 2386 |             painter.drawText(p: -imageRect.topLeft(), s: QChar(ch)); | 
| 2387 |         } | 
| 2388 |  | 
| 2389 |         bool foundPixel = false; | 
| 2390 |         for (int x = 0; x < image.width(); ++x) | 
| 2391 |             for (int y = 0; y < image.height(); ++y) | 
| 2392 |                 if (image.pixel(x, y) != 0) | 
| 2393 |                     foundPixel = true; | 
| 2394 |         // can't QVERIFY(foundPixel) as sometimes all pixels are clipped | 
| 2395 |         // away. For example for 'O' | 
| 2396 |         // just call /some/ function to prevent the compiler from optimizing | 
| 2397 |         // foundPixel away | 
| 2398 |         QString::number(foundPixel); | 
| 2399 |  | 
| 2400 |         //image.save(QString("debug") + ch + ".xpm"); | 
| 2401 |     } | 
| 2402 |  | 
| 2403 |     QVERIFY(true); // reached, don't trigger any valgrind errors | 
| 2404 | } | 
| 2405 |  | 
| 2406 | void tst_QPainter::setOpacity_data() | 
| 2407 | { | 
| 2408 |     QTest::addColumn<QImage::Format>(name: "destFormat" ); | 
| 2409 |     QTest::addColumn<QImage::Format>(name: "srcFormat" ); | 
| 2410 |  | 
| 2411 |     QTest::newRow(dataTag: "ARGB32P on ARGB32P" ) << QImage::Format_ARGB32_Premultiplied | 
| 2412 |                                         << QImage::Format_ARGB32_Premultiplied; | 
| 2413 |  | 
| 2414 |     QTest::newRow(dataTag: "ARGB32 on ARGB32" ) << QImage::Format_ARGB32 | 
| 2415 |                                       << QImage::Format_ARGB32; | 
| 2416 |  | 
| 2417 |     QTest::newRow(dataTag: "RGB32 on RGB32" ) << QImage::Format_RGB32 | 
| 2418 |                                     << QImage::Format_RGB32; | 
| 2419 |  | 
| 2420 |     QTest::newRow(dataTag: "RGB16 on RGB16" ) << QImage::Format_RGB16 | 
| 2421 |                                     << QImage::Format_RGB16; | 
| 2422 |  | 
| 2423 |     QTest::newRow(dataTag: "ARGB8565_Premultiplied on ARGB8565_Premultiplied" ) << QImage::Format_ARGB8565_Premultiplied | 
| 2424 |                                                                       << QImage::Format_ARGB8565_Premultiplied; | 
| 2425 |  | 
| 2426 |     QTest::newRow(dataTag: "RGB555 on RGB555" ) << QImage::Format_RGB555 | 
| 2427 |                                       << QImage::Format_RGB555; | 
| 2428 |  | 
| 2429 |     QTest::newRow(dataTag: "RGB666 on RGB666" ) << QImage::Format_RGB666 | 
| 2430 |                                       << QImage::Format_RGB666; | 
| 2431 |  | 
| 2432 |     QTest::newRow(dataTag: "ARGB8555_Premultiplied on ARGB8555_Premultiplied" ) << QImage::Format_ARGB8555_Premultiplied | 
| 2433 |                                                                       << QImage::Format_ARGB8555_Premultiplied; | 
| 2434 |  | 
| 2435 |     QTest::newRow(dataTag: "RGB888 on RGB888" ) << QImage::Format_RGB888 | 
| 2436 |                                       << QImage::Format_RGB888; | 
| 2437 |  | 
| 2438 |     QTest::newRow(dataTag: "RGB32 on RGB16" ) << QImage::Format_RGB16 | 
| 2439 |                                     << QImage::Format_RGB32; | 
| 2440 |  | 
| 2441 |     QTest::newRow(dataTag: "RGB32 on ARGB8565_Premultiplied" ) << QImage::Format_ARGB8565_Premultiplied | 
| 2442 |                                                      << QImage::Format_RGB32; | 
| 2443 |  | 
| 2444 |     QTest::newRow(dataTag: "RGB32 on RGB666" ) << QImage::Format_RGB666 | 
| 2445 |                                      << QImage::Format_RGB32; | 
| 2446 |  | 
| 2447 |     QTest::newRow(dataTag: "RGB32 on RGB555" ) << QImage::Format_RGB555 | 
| 2448 |                                      << QImage::Format_RGB32; | 
| 2449 |  | 
| 2450 |     QTest::newRow(dataTag: "RGB32 on ARGB8555_Premultiplied" ) << QImage::Format_ARGB8555_Premultiplied | 
| 2451 |                                                      << QImage::Format_RGB32; | 
| 2452 |  | 
| 2453 |     QTest::newRow(dataTag: "RGB32 on RGB888" ) << QImage::Format_RGB888 | 
| 2454 |                                      << QImage::Format_RGB32; | 
| 2455 |  | 
| 2456 |     QTest::newRow(dataTag: "RGB16 on RGB32" ) << QImage::Format_RGB32 | 
| 2457 |                                     << QImage::Format_RGB16; | 
| 2458 |  | 
| 2459 |     QTest::newRow(dataTag: "ARGB8565_Premultiplied on RGB32" ) << QImage::Format_RGB32 | 
| 2460 |                                                      << QImage::Format_ARGB8565_Premultiplied; | 
| 2461 |  | 
| 2462 |     QTest::newRow(dataTag: "RGB666 on RGB32" ) << QImage::Format_RGB32 | 
| 2463 |                                      << QImage::Format_RGB666; | 
| 2464 |  | 
| 2465 |     QTest::newRow(dataTag: "RGB555 on RGB32" ) << QImage::Format_RGB32 | 
| 2466 |                                      << QImage::Format_RGB555; | 
| 2467 |  | 
| 2468 |     QTest::newRow(dataTag: "ARGB8555_Premultiplied on RGB32" ) << QImage::Format_RGB32 | 
| 2469 |                                                      << QImage::Format_ARGB8555_Premultiplied; | 
| 2470 |  | 
| 2471 |     QTest::newRow(dataTag: "RGB888 on RGB32" ) << QImage::Format_RGB32 | 
| 2472 |                                      << QImage::Format_RGB888; | 
| 2473 |  | 
| 2474 |     QTest::newRow(dataTag: "RGB555 on RGB888" ) << QImage::Format_RGB888 | 
| 2475 |                                       << QImage::Format_RGB555; | 
| 2476 |  | 
| 2477 |     QTest::newRow(dataTag: "RGB666 on RGB888" ) << QImage::Format_RGB888 | 
| 2478 |                                       << QImage::Format_RGB666; | 
| 2479 |  | 
| 2480 |     QTest::newRow(dataTag: "RGB444 on RGB444" ) << QImage::Format_RGB444 | 
| 2481 |                                       << QImage::Format_RGB444; | 
| 2482 |  | 
| 2483 |     QTest::newRow(dataTag: "RGBA8888P on RGBA8888P" ) << QImage::Format_RGBA8888_Premultiplied | 
| 2484 |                                             << QImage::Format_RGBA8888_Premultiplied; | 
| 2485 |  | 
| 2486 |     QTest::newRow(dataTag: "RGBA8888 on RGBA8888" ) << QImage::Format_RGBA8888 | 
| 2487 |                                           << QImage::Format_RGBA8888; | 
| 2488 |  | 
| 2489 |     QTest::newRow(dataTag: "RGBx8888 on RGBx8888" ) << QImage::Format_RGBX8888 | 
| 2490 |                                           << QImage::Format_RGBX8888; | 
| 2491 |  | 
| 2492 |     QTest::newRow(dataTag: "RGBA8888P on ARGB32P" ) << QImage::Format_ARGB32_Premultiplied | 
| 2493 |                                           << QImage::Format_RGBA8888_Premultiplied; | 
| 2494 |  | 
| 2495 |     QTest::newRow(dataTag: "RGBx8888 on ARGB32P" ) << QImage::Format_ARGB32_Premultiplied | 
| 2496 |                                          << QImage::Format_RGBX8888; | 
| 2497 |  | 
| 2498 |     QTest::newRow(dataTag: "ARGB32P on RGBA8888P" ) << QImage::Format_RGBA8888_Premultiplied | 
| 2499 |                                           << QImage::Format_ARGB32_Premultiplied; | 
| 2500 |  | 
| 2501 |     QTest::newRow(dataTag: "RGB32 on RGBx8888" ) << QImage::Format_RGBX8888 | 
| 2502 |                                        << QImage::Format_RGB32; | 
| 2503 |  | 
| 2504 |     QTest::newRow(dataTag: "RGB30 on RGB32" ) << QImage::Format_RGB32 | 
| 2505 |                                     << QImage::Format_BGR30; | 
| 2506 |  | 
| 2507 |     QTest::newRow(dataTag: "BGR30 on ARGB32P" ) << QImage::Format_ARGB32_Premultiplied | 
| 2508 |                                       << QImage::Format_BGR30; | 
| 2509 |  | 
| 2510 |     QTest::newRow(dataTag: "A2RGB30P on ARGB32P" ) << QImage::Format_ARGB32_Premultiplied | 
| 2511 |                                          << QImage::Format_A2BGR30_Premultiplied; | 
| 2512 |  | 
| 2513 |     QTest::newRow(dataTag: "A2RGB30P on A2RGB30P" ) << QImage::Format_A2RGB30_Premultiplied | 
| 2514 |                                           << QImage::Format_A2RGB30_Premultiplied; | 
| 2515 |  | 
| 2516 |     QTest::newRow(dataTag: "ARGB32P on A2RGB30P" ) << QImage::Format_A2RGB30_Premultiplied | 
| 2517 |                                          << QImage::Format_ARGB32_Premultiplied; | 
| 2518 |  | 
| 2519 |     QTest::newRow(dataTag: "RGB32 on A2BGR30P" ) << QImage::Format_A2BGR30_Premultiplied | 
| 2520 |                                        << QImage::Format_RGB32; | 
| 2521 |  | 
| 2522 |     QTest::newRow(dataTag: "RGB30 on A2BGR30P" ) << QImage::Format_A2BGR30_Premultiplied | 
| 2523 |                                        << QImage::Format_RGB30; | 
| 2524 |  | 
| 2525 |     QTest::newRow(dataTag: "A2RGB30P on A2BGR30P" ) << QImage::Format_A2BGR30_Premultiplied | 
| 2526 |                                           << QImage::Format_A2RGB30_Premultiplied; | 
| 2527 |  | 
| 2528 |     QTest::newRow(dataTag: "ARGB32P on BGR30" ) << QImage::Format_BGR30 | 
| 2529 |                                       << QImage::Format_ARGB32_Premultiplied; | 
| 2530 |  | 
| 2531 |     QTest::newRow(dataTag: "ARGB32P on RGB30" ) << QImage::Format_RGB30 | 
| 2532 |                                       << QImage::Format_ARGB32_Premultiplied; | 
| 2533 |  | 
| 2534 |     QTest::newRow(dataTag: "A2RGB30P on RGB30" ) << QImage::Format_RGB30 | 
| 2535 |                                        << QImage::Format_A2RGB30_Premultiplied; | 
| 2536 |  | 
| 2537 |     QTest::newRow(dataTag: "RGBA64P on RGBA64P" ) << QImage::Format_RGBA64_Premultiplied | 
| 2538 |                                         << QImage::Format_RGBA64_Premultiplied; | 
| 2539 |  | 
| 2540 |     QTest::newRow(dataTag: "RGBA64 on RGBA64" ) << QImage::Format_RGBA64 | 
| 2541 |                                       << QImage::Format_RGBA64; | 
| 2542 |  | 
| 2543 |     QTest::newRow(dataTag: "RGBx64 on RGBx64" ) << QImage::Format_RGBX64 | 
| 2544 |                                       << QImage::Format_RGBX64; | 
| 2545 |  | 
| 2546 |     QTest::newRow(dataTag: "RGBA64P on ARGB32P" ) << QImage::Format_ARGB32_Premultiplied | 
| 2547 |                                         << QImage::Format_RGBA64_Premultiplied; | 
| 2548 |  | 
| 2549 |     QTest::newRow(dataTag: "RGBx64 on ARGB32P" ) << QImage::Format_ARGB32_Premultiplied | 
| 2550 |                                        << QImage::Format_RGBX64; | 
| 2551 |  | 
| 2552 |     QTest::newRow(dataTag: "ARGB32P on RGBA64P" ) << QImage::Format_RGBA64_Premultiplied | 
| 2553 |                                         << QImage::Format_ARGB32_Premultiplied; | 
| 2554 |  | 
| 2555 | } | 
| 2556 |  | 
| 2557 | void tst_QPainter::setOpacity() | 
| 2558 | { | 
| 2559 |     QFETCH(QImage::Format, destFormat); | 
| 2560 |     QFETCH(QImage::Format, srcFormat); | 
| 2561 |  | 
| 2562 |     const QSize imageSize(12, 12); | 
| 2563 |     const QRect imageRect(QPoint(0, 0), imageSize); | 
| 2564 |     QColor destColor = Qt::black; | 
| 2565 |     QColor srcColor = Qt::white; | 
| 2566 |  | 
| 2567 |     QImage dest(imageSize, destFormat); | 
| 2568 |     QImage src(imageSize, srcFormat); | 
| 2569 |  | 
| 2570 |     QPainter p; | 
| 2571 |     p.begin(&dest); | 
| 2572 |     p.fillRect(imageRect, color: destColor); | 
| 2573 |     p.end(); | 
| 2574 |  | 
| 2575 |     p.begin(&src); | 
| 2576 |     p.fillRect(imageRect, color: srcColor); | 
| 2577 |     p.end(); | 
| 2578 |  | 
| 2579 |     p.begin(&dest); | 
| 2580 |     p.setOpacity(0.5); | 
| 2581 |     p.drawImage(targetRect: imageRect, image: src, sourceRect: imageRect); | 
| 2582 |     p.end(); | 
| 2583 |  | 
| 2584 |     QImage actual = dest.convertToFormat(f: QImage::Format_RGB32); | 
| 2585 |  | 
| 2586 |     for (int y = 0; y < actual.height(); ++y) { | 
| 2587 |         QRgb *p = (QRgb *)actual.scanLine(y); | 
| 2588 |         for (int x = 0; x < actual.width(); ++x) { | 
| 2589 |             QVERIFY(qAbs(qRed(p[x]) - 127) <= 0xf); | 
| 2590 |             QVERIFY(qAbs(qGreen(p[x]) - 127) <= 0xf); | 
| 2591 |             QVERIFY(qAbs(qBlue(p[x]) - 127) <= 0xf); | 
| 2592 |         } | 
| 2593 |     } | 
| 2594 | } | 
| 2595 |  | 
| 2596 | void tst_QPainter::drawhelper_blend_untransformed_data() | 
| 2597 | { | 
| 2598 |     setOpacity_data(); | 
| 2599 | } | 
| 2600 |  | 
| 2601 | void tst_QPainter::drawhelper_blend_untransformed() | 
| 2602 | { | 
| 2603 |     QFETCH(QImage::Format, destFormat); | 
| 2604 |     QFETCH(QImage::Format, srcFormat); | 
| 2605 |  | 
| 2606 |     const int size = 128; | 
| 2607 |     const QSize imageSize(size, size); | 
| 2608 |     const QRect paintRect(1, 0, size - 2, size); // needs alignment and tailing | 
| 2609 |  | 
| 2610 |     QColor destColor(127, 127, 127); | 
| 2611 |     QColor srcColor(Qt::white); | 
| 2612 |  | 
| 2613 |     QImage dest(imageSize, destFormat); | 
| 2614 |     QImage src(imageSize, srcFormat); | 
| 2615 |  | 
| 2616 |     QPainter p; | 
| 2617 |     p.begin(&src); | 
| 2618 |     p.fillRect(paintRect, color: srcColor); | 
| 2619 |     p.end(); | 
| 2620 |  | 
| 2621 |     QList<qreal> opacities = (QList<qreal>() << 0.0 << 0.1  << 0.01 << 0.4 | 
| 2622 |                               << 0.5 << 0.6 << 0.9 << 1.0); | 
| 2623 |     foreach (qreal opacity, opacities) { | 
| 2624 |         p.begin(&dest); | 
| 2625 |         p.fillRect(paintRect, color: destColor); | 
| 2626 |  | 
| 2627 |         p.setOpacity(opacity); | 
| 2628 |         p.drawImage(targetRect: paintRect, image: src, sourceRect: paintRect); | 
| 2629 |         p.end(); | 
| 2630 |  | 
| 2631 |         // sanity check: make sure all pixels are equal | 
| 2632 |         QImage expected(size - 2, size, destFormat); | 
| 2633 |         p.begin(&expected); | 
| 2634 |         p.fillRect(x: 0, y: 0, w: expected.width(), h: expected.height(), | 
| 2635 |                    b: dest.pixelColor(x: 1, y: 0)); | 
| 2636 |         p.end(); | 
| 2637 |  | 
| 2638 |         const QImage subDest(dest.bits() + dest.depth() / 8, | 
| 2639 |                              dest.width() - 2, dest.height(), | 
| 2640 |                              dest.bytesPerLine(), dest.format()); | 
| 2641 |  | 
| 2642 |         if (dest.format() == QImage::Format_ARGB8565_Premultiplied || | 
| 2643 |             dest.format() == QImage::Format_ARGB8555_Premultiplied) { | 
| 2644 |             // Test skipped due to rounding errors... | 
| 2645 |             continue; | 
| 2646 |         } | 
| 2647 |         QCOMPARE(subDest, expected); | 
| 2648 |     } | 
| 2649 | } | 
| 2650 |  | 
| 2651 | void tst_QPainter::drawhelper_blend_tiled_untransformed_data() | 
| 2652 | { | 
| 2653 |     setOpacity_data(); | 
| 2654 | } | 
| 2655 |  | 
| 2656 | void tst_QPainter::drawhelper_blend_tiled_untransformed() | 
| 2657 | { | 
| 2658 |     QFETCH(QImage::Format, destFormat); | 
| 2659 |     QFETCH(QImage::Format, srcFormat); | 
| 2660 |  | 
| 2661 |     const int size = 128; | 
| 2662 |     const QSize imageSize(size, size); | 
| 2663 |     const QRect paintRect(1, 0, size - 2, size); // needs alignment and tailing | 
| 2664 |  | 
| 2665 |     QColor destColor(127, 127, 127); | 
| 2666 |     QColor srcColor(Qt::white); | 
| 2667 |  | 
| 2668 |     QImage dest(imageSize, destFormat); | 
| 2669 |     QImage src(imageSize / 2, srcFormat); | 
| 2670 |  | 
| 2671 |     QPainter p; | 
| 2672 |     p.begin(&src); | 
| 2673 |     p.fillRect(QRect(QPoint(0, 0), imageSize/ 2), color: srcColor); | 
| 2674 |     p.end(); | 
| 2675 |  | 
| 2676 |     const QBrush brush(src); | 
| 2677 |  | 
| 2678 |     QList<qreal> opacities = (QList<qreal>() << 0.0 << 0.1  << 0.01 << 0.4 | 
| 2679 |                               << 0.5 << 0.6 << 0.9 << 1.0); | 
| 2680 |     foreach (qreal opacity, opacities) { | 
| 2681 |         p.begin(&dest); | 
| 2682 |         p.fillRect(paintRect, color: destColor); | 
| 2683 |  | 
| 2684 |         p.setOpacity(opacity); | 
| 2685 |         p.fillRect(paintRect, brush); | 
| 2686 |         p.end(); | 
| 2687 |  | 
| 2688 |         // sanity check: make sure all pixels are equal | 
| 2689 |         QImage expected(size - 2, size, destFormat); | 
| 2690 |         p.begin(&expected); | 
| 2691 |         p.fillRect(x: 0, y: 0, w: expected.width(), h: expected.height(), | 
| 2692 |                    b: dest.pixelColor(x: 1, y: 0)); | 
| 2693 |         p.end(); | 
| 2694 |  | 
| 2695 |         const QImage subDest(dest.bits() + dest.depth() / 8, | 
| 2696 |                              dest.width() - 2, dest.height(), | 
| 2697 |                              dest.bytesPerLine(), dest.format()); | 
| 2698 |  | 
| 2699 |         if (dest.format() == QImage::Format_ARGB8565_Premultiplied || | 
| 2700 |             dest.format() == QImage::Format_ARGB8555_Premultiplied) { | 
| 2701 |             // Skipping test due to rounding errors. Test needs rewrite | 
| 2702 |             continue; | 
| 2703 |         } | 
| 2704 |         QCOMPARE(subDest, expected); | 
| 2705 |     } | 
| 2706 | } | 
| 2707 |  | 
| 2708 | static QPaintEngine::PaintEngineFeatures no_porter_duff() | 
| 2709 | { | 
| 2710 |     QPaintEngine::PaintEngineFeatures features = QPaintEngine::AllFeatures; | 
| 2711 |     return features & ~QPaintEngine::PorterDuff; | 
| 2712 | } | 
| 2713 |  | 
| 2714 | class DummyPaintEngine : public QPaintEngine, public QPaintDevice | 
| 2715 | { | 
| 2716 | public: | 
| 2717 |     DummyPaintEngine() : QPaintEngine(no_porter_duff()) {} | 
| 2718 |     virtual bool begin(QPaintDevice *) { return true; } | 
| 2719 |     virtual bool end() { return true; } | 
| 2720 |  | 
| 2721 |     virtual void updateState(const QPaintEngineState &) {} | 
| 2722 |     virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {} | 
| 2723 |  | 
| 2724 |     virtual Type type() const { return User; } | 
| 2725 |  | 
| 2726 |     virtual QPaintEngine *paintEngine() const { return (QPaintEngine *)this; } | 
| 2727 |  | 
| 2728 |     virtual int metric(PaintDeviceMetric metric) const { Q_UNUSED(metric); return 0; }; | 
| 2729 | }; | 
| 2730 |  | 
| 2731 | static bool success; | 
| 2732 |  | 
| 2733 | void porterDuff_warningChecker(QtMsgType type, const QMessageLogContext &, const QString &msg) | 
| 2734 | { | 
| 2735 |     if (type == QtWarningMsg && msg == QLatin1String("QPainter::setCompositionMode: PorterDuff modes not supported on device" )) | 
| 2736 |         success = false; | 
| 2737 | } | 
| 2738 |  | 
| 2739 | void tst_QPainter::porterDuff_warning() | 
| 2740 | { | 
| 2741 |     QtMessageHandler old = qInstallMessageHandler(porterDuff_warningChecker); | 
| 2742 |     DummyPaintEngine dummy; | 
| 2743 |     QPainter p(&dummy); | 
| 2744 |  | 
| 2745 |     success = true; | 
| 2746 |     p.setCompositionMode(QPainter::CompositionMode_Source); | 
| 2747 |     QVERIFY(success); | 
| 2748 |  | 
| 2749 |     success = true; | 
| 2750 |     p.setCompositionMode(QPainter::CompositionMode_SourceOver); | 
| 2751 |     QVERIFY(success); | 
| 2752 |  | 
| 2753 |     success = true; | 
| 2754 |     p.setCompositionMode(QPainter::CompositionMode_DestinationOver); | 
| 2755 |     QVERIFY(!success); | 
| 2756 |  | 
| 2757 |     QVERIFY(qInstallMessageHandler(old) == porterDuff_warningChecker); | 
| 2758 | } | 
| 2759 |  | 
| 2760 | void tst_QPainter::drawhelper_blend_color() | 
| 2761 | { | 
| 2762 |     QImage dest(32, 32, QImage::Format_ARGB8555_Premultiplied); | 
| 2763 |     dest.fill(pixel: 0xff000000); | 
| 2764 |  | 
| 2765 |     { | 
| 2766 |         QPainter p(&dest); | 
| 2767 |         p.fillRect(x: 0, y: 0, w: dest.width(), h: dest.height(), b: QColor(255, 0, 0, 127)); | 
| 2768 |     } | 
| 2769 |  | 
| 2770 |     QImage expected(32, 32, QImage::Format_ARGB8555_Premultiplied); | 
| 2771 |     expected.fill(pixel: 0xff3c007f); | 
| 2772 |  | 
| 2773 |     QCOMPARE(dest.pixel(1, 1), expected.pixel(1, 1)); | 
| 2774 |     QCOMPARE(dest, expected); | 
| 2775 | } | 
| 2776 |  | 
| 2777 | #ifndef QT_NO_WIDGETS | 
| 2778 | class ViewportTestWidget : public QWidget | 
| 2779 | { | 
| 2780 | public: | 
| 2781 |     ViewportTestWidget(QWidget *parent = 0) : QWidget(parent), hasPainted(false) {} | 
| 2782 |     QSize sizeHint() const { | 
| 2783 |         return QSize(100, 100); | 
| 2784 |     } | 
| 2785 |  | 
| 2786 |     QRect viewport; | 
| 2787 |     bool hasPainted; | 
| 2788 |  | 
| 2789 | protected: | 
| 2790 |     void paintEvent(QPaintEvent *) { | 
| 2791 |         hasPainted = true; | 
| 2792 |         QPainter p(this); | 
| 2793 |         viewport = p.viewport(); | 
| 2794 |     } | 
| 2795 | }; | 
| 2796 |  | 
| 2797 | void tst_QPainter::childWidgetViewport() | 
| 2798 | { | 
| 2799 |     QWidget parent; | 
| 2800 |     parent.setAutoFillBackground(true); | 
| 2801 |     parent.resize(w: 200, h: 200); | 
| 2802 |     ViewportTestWidget child(&parent); | 
| 2803 |     child.setAutoFillBackground(true); | 
| 2804 |     parent.show(); | 
| 2805 |     parent.update(); | 
| 2806 |     qApp->processEvents(); | 
| 2807 |  | 
| 2808 |     if (child.hasPainted) { | 
| 2809 |         QCOMPARE(child.viewport, QRect(QPoint(0, 0), child.sizeHint())); | 
| 2810 |     } else { | 
| 2811 |         qWarning(msg: "Failed to ensure that paintEvent has been run. Could not run test." ); | 
| 2812 |     } | 
| 2813 | } | 
| 2814 | #endif | 
| 2815 |  | 
| 2816 | void tst_QPainter::fillRect_objectBoundingModeGradient() | 
| 2817 | { | 
| 2818 |     QImage a(10, 10, QImage::Format_ARGB32_Premultiplied); | 
| 2819 |     a.fill(pixel: 0x0); | 
| 2820 |     QImage b = a; | 
| 2821 |  | 
| 2822 |     QLinearGradient g(QPoint(0, 0), QPoint(0, 1)); | 
| 2823 |     g.setColorAt(pos: 0, color: Qt::red); | 
| 2824 |     g.setColorAt(pos: 1, color: Qt::blue); | 
| 2825 |     g.setCoordinateMode(QGradient::ObjectBoundingMode); | 
| 2826 |  | 
| 2827 |     QPainter p(&a); | 
| 2828 |     p.fillRect(QRect(0, 0, a.width(), a.height()), g); | 
| 2829 |     p.end(); | 
| 2830 |  | 
| 2831 |     QPainterPath path; | 
| 2832 |     path.addRect(x: 0, y: 0, w: a.width(), h: a.height()); | 
| 2833 |  | 
| 2834 |     p.begin(&b); | 
| 2835 |     p.fillPath(path, brush: g); | 
| 2836 |     p.end(); | 
| 2837 |  | 
| 2838 |     QCOMPARE(a, b); | 
| 2839 | } | 
| 2840 |  | 
| 2841 | void tst_QPainter::fillRect_stretchToDeviceMode() | 
| 2842 | { | 
| 2843 |     QImage img(64, 64, QImage::Format_ARGB32_Premultiplied); | 
| 2844 |  | 
| 2845 |     QLinearGradient g(QPoint(0, 0), QPoint(0, 1)); | 
| 2846 |     g.setCoordinateMode(QGradient::StretchToDeviceMode); | 
| 2847 |  | 
| 2848 |     QPainter p(&img); | 
| 2849 |     p.fillRect(img.rect(), g); | 
| 2850 |     p.end(); | 
| 2851 |  | 
| 2852 |     for (int i = 1; i < img.height(); ++i) | 
| 2853 |         QVERIFY(img.pixel(0, i) != img.pixel(0, i-1)); | 
| 2854 | } | 
| 2855 |  | 
| 2856 | void tst_QPainter::monoImages() | 
| 2857 | { | 
| 2858 |     Qt::GlobalColor colorPairs[][2] = { | 
| 2859 |         { Qt::white, Qt::black }, | 
| 2860 |         { Qt::color0, Qt::color1 }, | 
| 2861 |         { Qt::red, Qt::blue } | 
| 2862 |     }; | 
| 2863 |  | 
| 2864 |     const int numColorPairs = sizeof(colorPairs) / sizeof(QRgb[2]); | 
| 2865 |  | 
| 2866 |     QImage transparent(2, 2, QImage::Format_ARGB32_Premultiplied); | 
| 2867 |     transparent.fill(pixel: 0x0); | 
| 2868 |  | 
| 2869 |     for (int i = 1; i < QImage::NImageFormats; ++i) { | 
| 2870 |         for (int j = 0; j < numColorPairs; ++j) { | 
| 2871 |             const QImage::Format format = QImage::Format(i); | 
| 2872 |             if (format == QImage::Format_Indexed8) | 
| 2873 |                 continue; | 
| 2874 |  | 
| 2875 |             QImage img(2, 2, format); | 
| 2876 |  | 
| 2877 |             if (img.colorCount() > 0) { | 
| 2878 |                 img.setColor(i: 0, c: QColor(colorPairs[j][0]).rgba()); | 
| 2879 |                 img.setColor(i: 1, c: QColor(colorPairs[j][1]).rgba()); | 
| 2880 |             } | 
| 2881 |  | 
| 2882 |             img.fill(pixel: 0x0); | 
| 2883 |             QPainter p(&img); | 
| 2884 |             p.fillRect(x: 0, y: 0, w: 2, h: 2, c: colorPairs[j][0]); | 
| 2885 |             p.fillRect(x: 0, y: 0, w: 1, h: 1, c: colorPairs[j][1]); | 
| 2886 |             p.fillRect(x: 1, y: 1, w: 1, h: 1, c: colorPairs[j][1]); | 
| 2887 |             p.end(); | 
| 2888 |  | 
| 2889 |             QImage original = img; | 
| 2890 |  | 
| 2891 |             p.begin(&img); | 
| 2892 |             p.drawImage(x: 0, y: 0, image: transparent); | 
| 2893 |             p.end(); | 
| 2894 |  | 
| 2895 |             // drawing a transparent image on top of another image | 
| 2896 |             // should not change the image | 
| 2897 |             QCOMPARE(original, img); | 
| 2898 |  | 
| 2899 |             if (img.colorCount() == 0) | 
| 2900 |                 continue; | 
| 2901 |  | 
| 2902 |             for (int k = 0; k < 2; ++k) { | 
| 2903 |                 QPainter p(&img); | 
| 2904 |                 p.fillRect(x: 0, y: 0, w: 2, h: 2, c: colorPairs[j][k]); | 
| 2905 |                 p.end(); | 
| 2906 |  | 
| 2907 |                 QImage argb32p(2, 2, QImage::Format_ARGB32_Premultiplied); | 
| 2908 |                 p.begin(&argb32p); | 
| 2909 |                 p.fillRect(x: 0, y: 0, w: 2, h: 2, c: colorPairs[j][k]); | 
| 2910 |                 p.end(); | 
| 2911 |  | 
| 2912 |                 QCOMPARE(argb32p, img.convertToFormat(argb32p.format())); | 
| 2913 |  | 
| 2914 |                 // drawing argb32p image on mono image | 
| 2915 |                 p.begin(&img); | 
| 2916 |                 p.drawImage(x: 0, y: 0, image: argb32p); | 
| 2917 |                 p.end(); | 
| 2918 |  | 
| 2919 |                 QCOMPARE(argb32p, img.convertToFormat(argb32p.format())); | 
| 2920 |  | 
| 2921 |                 // drawing mono image on argb32p image | 
| 2922 |                 p.begin(&argb32p); | 
| 2923 |                 p.drawImage(x: 0, y: 0, image: img); | 
| 2924 |                 p.end(); | 
| 2925 |  | 
| 2926 |                 QCOMPARE(argb32p, img.convertToFormat(argb32p.format())); | 
| 2927 |             } | 
| 2928 |         } | 
| 2929 |     } | 
| 2930 | } | 
| 2931 |  | 
| 2932 | #if !defined(Q_OS_AIX) && !defined(Q_CC_MSVC) && !defined(Q_OS_SOLARIS) && !defined(__UCLIBC__) | 
| 2933 | #include <fenv.h> | 
| 2934 |  | 
| 2935 | static const QString fpeExceptionString(int exception) | 
| 2936 | { | 
| 2937 | #ifdef FE_INEXACT | 
| 2938 |     if (exception & FE_INEXACT) | 
| 2939 |         return QLatin1String("Inexact result" ); | 
| 2940 | #endif | 
| 2941 |     if (exception & FE_UNDERFLOW) | 
| 2942 |         return QLatin1String("Underflow" ); | 
| 2943 |     if (exception & FE_OVERFLOW) | 
| 2944 |         return QLatin1String("Overflow" ); | 
| 2945 |     if (exception & FE_DIVBYZERO) | 
| 2946 |         return QLatin1String("Divide by zero" ); | 
| 2947 |     if (exception & FE_INVALID) | 
| 2948 |         return QLatin1String("Invalid operation" ); | 
| 2949 |     return QLatin1String("No exception" ); | 
| 2950 | } | 
| 2951 |  | 
| 2952 | class FpExceptionChecker | 
| 2953 | { | 
| 2954 | public: | 
| 2955 |     FpExceptionChecker(int exceptionMask) | 
| 2956 |         : m_exceptionMask(exceptionMask) | 
| 2957 |     { | 
| 2958 |         feclearexcept(excepts: m_exceptionMask); | 
| 2959 |     } | 
| 2960 |  | 
| 2961 |     ~FpExceptionChecker() | 
| 2962 |     { | 
| 2963 |         const int exceptions = fetestexcept(excepts: m_exceptionMask); | 
| 2964 |         QVERIFY2(!exceptions, qPrintable(QLatin1String("Floating point exception: " ) + fpeExceptionString(exceptions))); | 
| 2965 |     } | 
| 2966 |  | 
| 2967 | private: | 
| 2968 |     int m_exceptionMask; | 
| 2969 | }; | 
| 2970 |  | 
| 2971 | void fpe_rasterizeLine_task232012() | 
| 2972 | { | 
| 2973 |     FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO); | 
| 2974 |     QImage img(128, 128, QImage::Format_ARGB32_Premultiplied); | 
| 2975 |     img.fill(pixel: 0x0); | 
| 2976 |     QPainter p(&img); | 
| 2977 |  | 
| 2978 |     p.setBrush(Qt::black); | 
| 2979 |     p.drawRect(rect: QRectF(0, 0, 5, 0)); | 
| 2980 |     p.drawRect(rect: QRectF(0, 0, 0, 5)); | 
| 2981 | } | 
| 2982 |  | 
| 2983 | void fpe_pixmapTransform() | 
| 2984 | { | 
| 2985 |     FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO); | 
| 2986 |  | 
| 2987 |     QImage img(128, 128, QImage::Format_ARGB32_Premultiplied); | 
| 2988 |  | 
| 2989 |     QPainter p(&img); | 
| 2990 |  | 
| 2991 |     const qreal scaleFactor = 0.001; | 
| 2992 |     const int translateDistance = 1000000; | 
| 2993 |  | 
| 2994 |     p.setPen(Qt::red); | 
| 2995 |     p.setBrush(QBrush(Qt::red,Qt::Dense6Pattern)); | 
| 2996 |  | 
| 2997 |     for (int i = 0; i < 2; ++i) { | 
| 2998 |         p.setRenderHint(hint: QPainter::SmoothPixmapTransform, on: i); | 
| 2999 |  | 
| 3000 |         p.resetTransform(); | 
| 3001 |         p.scale(sx: 1.1, sy: 1.1); | 
| 3002 |         p.translate(dx: translateDistance, dy: 0); | 
| 3003 |         p.drawRect(x: -translateDistance, y: 0, w: 100, h: 100); | 
| 3004 |  | 
| 3005 |         p.resetTransform(); | 
| 3006 |         p.scale(sx: scaleFactor, sy: scaleFactor); | 
| 3007 |         p.drawRect(rect: QRectF(0, 0, 1 / scaleFactor, 1 / scaleFactor)); | 
| 3008 |     } | 
| 3009 | } | 
| 3010 |  | 
| 3011 | void fpe_zeroLengthLines() | 
| 3012 | { | 
| 3013 |     FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO); | 
| 3014 |  | 
| 3015 |     QImage img(128, 128, QImage::Format_ARGB32_Premultiplied); | 
| 3016 |  | 
| 3017 |     QPainter p(&img); | 
| 3018 |  | 
| 3019 |     p.setPen(QPen(Qt::black, 3)); | 
| 3020 |     p.drawLine(x1: 64, y1: 64, x2: 64, y2: 64); | 
| 3021 | } | 
| 3022 |  | 
| 3023 | void fpe_divByZero() | 
| 3024 | { | 
| 3025 |     FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO); | 
| 3026 |  | 
| 3027 |     QImage img(128, 128, QImage::Format_ARGB32_Premultiplied); | 
| 3028 |  | 
| 3029 |     QPainter p(&img); | 
| 3030 |  | 
| 3031 |     p.setRenderHint(hint: QPainter::Antialiasing); | 
| 3032 |  | 
| 3033 |     p.drawRect(rect: QRectF(10, 10, 100, 0)); | 
| 3034 |     p.drawRect(rect: QRectF(10, 10, 0, 100)); | 
| 3035 |  | 
| 3036 |     p.drawRect(r: QRect(10, 10, 100, 0)); | 
| 3037 |     p.drawRect(r: QRect(10, 10, 0, 100)); | 
| 3038 |  | 
| 3039 |     p.fillRect(r: QRectF(10, 10, 100, 0), c: Qt::black); | 
| 3040 |     p.fillRect(r: QRectF(10, 10, 0, 100), c: Qt::black); | 
| 3041 |  | 
| 3042 |     p.fillRect(r: QRect(10, 10, 100, 0), c: Qt::black); | 
| 3043 |     p.fillRect(r: QRect(10, 10, 0, 100), c: Qt::black); | 
| 3044 | } | 
| 3045 |  | 
| 3046 | void fpe_steepSlopes() | 
| 3047 | { | 
| 3048 |     FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO); | 
| 3049 |  | 
| 3050 |     QImage img(1024, 1024, QImage::Format_ARGB32_Premultiplied); | 
| 3051 |  | 
| 3052 |     QFETCH(QTransform, transform); | 
| 3053 |     QFETCH(QLineF, line); | 
| 3054 |     QFETCH(bool, antialiased); | 
| 3055 |  | 
| 3056 |     QPainter p(&img); | 
| 3057 |  | 
| 3058 |     p.setPen(QPen(Qt::black, 1)); | 
| 3059 |     p.setRenderHint(hint: QPainter::Antialiasing, on: antialiased); | 
| 3060 |     p.setTransform(transform); | 
| 3061 |  | 
| 3062 |     p.drawLine(l: line); | 
| 3063 | } | 
| 3064 |  | 
| 3065 | void fpe_radialGradients() | 
| 3066 | { | 
| 3067 |     FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO); | 
| 3068 |  | 
| 3069 |     QImage img(21, 21, QImage::Format_ARGB32_Premultiplied); | 
| 3070 |     img.fill(pixel: 0); | 
| 3071 |  | 
| 3072 |     double m = img.width() * 0.5; | 
| 3073 |  | 
| 3074 |     QPainter p(&img); | 
| 3075 |     p.setRenderHints(hints: QPainter::Antialiasing); | 
| 3076 |     p.setPen(Qt::NoPen); | 
| 3077 |     p.setBrush(QRadialGradient(m, m, m)); | 
| 3078 |     p.drawEllipse(r: img.rect()); | 
| 3079 | } | 
| 3080 |  | 
| 3081 | #define FPE_TEST(x) \ | 
| 3082 | void tst_QPainter::x() \ | 
| 3083 | { \ | 
| 3084 |     ::x(); \ | 
| 3085 | } | 
| 3086 | #else | 
| 3087 | #define FPE_TEST(x) \ | 
| 3088 | void tst_QPainter::x() \ | 
| 3089 | { \ | 
| 3090 |     QSKIP("Floating point exception checking (fenv.h) not available"); \ | 
| 3091 | } | 
| 3092 | #endif | 
| 3093 |  | 
| 3094 | FPE_TEST(fpe_rasterizeLine_task232012) | 
| 3095 | FPE_TEST(fpe_pixmapTransform) | 
| 3096 | FPE_TEST(fpe_zeroLengthLines) | 
| 3097 | FPE_TEST(fpe_divByZero) | 
| 3098 | FPE_TEST(fpe_steepSlopes) | 
| 3099 | FPE_TEST(fpe_radialGradients) | 
| 3100 |  | 
| 3101 | void tst_QPainter::fpe_steepSlopes_data() | 
| 3102 | { | 
| 3103 |     QTest::addColumn<QTransform>(name: "transform" ); | 
| 3104 |     QTest::addColumn<QLineF>(name: "line" ); | 
| 3105 |     QTest::addColumn<bool>(name: "antialiased" ); | 
| 3106 |  | 
| 3107 |     { | 
| 3108 |         const qreal dsin = 0.000014946676875461832484392500630665523431162000633776187896728515625; | 
| 3109 |         const qreal dcos = 0.9999999998882984630910186751862056553363800048828125; | 
| 3110 |  | 
| 3111 |         const QTransform transform = QTransform(dcos, dsin, -dsin, dcos, 64, 64); | 
| 3112 |         const QLineF line(2, 2, 2, 6); | 
| 3113 |  | 
| 3114 |         QTest::newRow(dataTag: "task 207147 aa" ) << transform << line << true; | 
| 3115 |         QTest::newRow(dataTag: "task 207147 no aa" ) << transform << line << false; | 
| 3116 |     } | 
| 3117 |  | 
| 3118 |     { | 
| 3119 |         QTransform transform; | 
| 3120 |         transform.rotate(a: 0.0000001); | 
| 3121 |         const QLineF line(5, 5, 10, 5); | 
| 3122 |  | 
| 3123 |         QTest::newRow(dataTag: "task 166702 aa" ) << transform << line << true; | 
| 3124 |         QTest::newRow(dataTag: "task 166702 no aa" ) << transform << line << false; | 
| 3125 |     } | 
| 3126 |  | 
| 3127 |     { | 
| 3128 |         const QTransform transform; | 
| 3129 |         const QLineF line(2.5, 2.5, 2.5 + 1/256., 60000.5); | 
| 3130 |  | 
| 3131 |         QTest::newRow(dataTag: "steep line aa" ) << transform << line << true; | 
| 3132 |         QTest::newRow(dataTag: "steep line no aa" ) << transform << line << false; | 
| 3133 |     } | 
| 3134 |  | 
| 3135 |     { | 
| 3136 |         const QTransform transform; | 
| 3137 |         const QLineF line(2.5, 2.5, 2.5 + 1/256., 1024); | 
| 3138 |  | 
| 3139 |         QTest::newRow(dataTag: "steep line 2 aa" ) << transform << line << true; | 
| 3140 |         QTest::newRow(dataTag: "steep line 2 no aa" ) << transform << line << false; | 
| 3141 |     } | 
| 3142 |  | 
| 3143 |     { | 
| 3144 |         const QTransform transform; | 
| 3145 |         const QLineF line(2.5, 2.5, 2.5 + 1/64., 1024); | 
| 3146 |  | 
| 3147 |         QTest::newRow(dataTag: "steep line 3 aa" ) << transform << line << true; | 
| 3148 |         QTest::newRow(dataTag: "steep line 3 no aa" ) << transform << line << false; | 
| 3149 |     } | 
| 3150 | } | 
| 3151 |  | 
| 3152 | qreal randf() | 
| 3153 | { | 
| 3154 |     return QRandomGenerator::global()->bounded(highest: 1.0); | 
| 3155 | } | 
| 3156 |  | 
| 3157 | QPointF randInRect(const QRectF &rect) | 
| 3158 | { | 
| 3159 |     const qreal x = rect.left() + rect.width() * randf(); | 
| 3160 |     const qreal y = rect.top() + rect.height() * randf(); | 
| 3161 |  | 
| 3162 |     return QPointF(x, y); | 
| 3163 | } | 
| 3164 |  | 
| 3165 | void tst_QPainter::rasterizer_asserts() | 
| 3166 | { | 
| 3167 |     QImage img(64, 64, QImage::Format_ARGB32_Premultiplied); | 
| 3168 |  | 
| 3169 |     QRectF middle(QPointF(0, 0), img.size()); | 
| 3170 |     QRectF left = middle.translated(dx: -middle.width(), dy: 0); | 
| 3171 |     QRectF right = middle.translated(dx: middle.width(), dy: 0); | 
| 3172 |  | 
| 3173 |     QPainter p(&img); | 
| 3174 |     img.fill(color: Qt::white); | 
| 3175 |     p.setCompositionMode(QPainter::CompositionMode_Destination); | 
| 3176 |     for (int i = 0; i < 100000; ++i) { | 
| 3177 |         QPainterPath path; | 
| 3178 |         path.moveTo(p: randInRect(rect: middle)); | 
| 3179 |         path.lineTo(p: randInRect(rect: left)); | 
| 3180 |         path.lineTo(p: randInRect(rect: right)); | 
| 3181 |  | 
| 3182 |         p.fillPath(path, brush: Qt::black); | 
| 3183 |     } | 
| 3184 | } | 
| 3185 |  | 
| 3186 | void tst_QPainter::rasterizer_negativeCoords() | 
| 3187 | { | 
| 3188 |     QImage img(64, 64, QImage::Format_ARGB32_Premultiplied); | 
| 3189 |     img.fill(pixel: 0x0); | 
| 3190 |  | 
| 3191 |     QImage original = img; | 
| 3192 |  | 
| 3193 |     QPainter p(&img); | 
| 3194 |     p.rotate(a: 90); | 
| 3195 |     p.fillRect(x: 0, y: 0, w: 70, h: 50, c: Qt::black); | 
| 3196 |  | 
| 3197 |     // image should not have changed | 
| 3198 |     QCOMPARE(img.pixel(0, 0), 0x0U); | 
| 3199 |     QCOMPARE(img, original); | 
| 3200 | } | 
| 3201 |  | 
| 3202 | void tst_QPainter::blendOverFlow_data() | 
| 3203 | { | 
| 3204 |     QTest::addColumn<QImage::Format>(name: "format" ); | 
| 3205 |     QTest::addColumn<int>(name: "width" ); | 
| 3206 |     QTest::addColumn<int>(name: "height" ); | 
| 3207 |  | 
| 3208 |     QImage::Format format = QImage::Format_ARGB8555_Premultiplied; | 
| 3209 |     QTest::newRow(dataTag: "555,1,1" ) << format << 1 << 1; | 
| 3210 |     QTest::newRow(dataTag: "555,2,2" ) << format << 2 << 2; | 
| 3211 |     QTest::newRow(dataTag: "555,10,10" ) << format << 10 << 10; | 
| 3212 |  | 
| 3213 |     format = QImage::Format_ARGB8565_Premultiplied; | 
| 3214 |     QTest::newRow(dataTag: "565,1,1" ) << format << 1 << 1; | 
| 3215 |     QTest::newRow(dataTag: "565,2,2" ) << format << 2 << 2; | 
| 3216 |     QTest::newRow(dataTag: "565,10,10" ) << format << 10 << 10; | 
| 3217 | } | 
| 3218 |  | 
| 3219 | void tst_QPainter::blendOverFlow() | 
| 3220 | { | 
| 3221 |     QFETCH(QImage::Format, format); | 
| 3222 |     QFETCH(int, width); | 
| 3223 |     QFETCH(int, height); | 
| 3224 |  | 
| 3225 |     QImage dest(width, height, format); | 
| 3226 |     QImage src(width, height, format); | 
| 3227 |  | 
| 3228 |     { | 
| 3229 |         QPainter p(&dest); | 
| 3230 |         p.fillRect(x: 0, y: 0, w: width, h: height, c: Qt::green); | 
| 3231 |     } | 
| 3232 |     QImage expected = dest; | 
| 3233 |  | 
| 3234 |     { | 
| 3235 |         QPainter p(&src); | 
| 3236 |         p.setCompositionMode(QPainter::CompositionMode_Source); | 
| 3237 |         p.fillRect(x: 0, y: 0, w: width, h: height, b: QColor(0, 255, 0, 6)); | 
| 3238 |     } | 
| 3239 |  | 
| 3240 |     { | 
| 3241 |         QPainter p(&dest); | 
| 3242 |         p.drawImage(x: 0, y: 0, image: src); | 
| 3243 |     } | 
| 3244 |  | 
| 3245 |     QCOMPARE(dest.pixel(0, 0), expected.pixel(0, 0)); | 
| 3246 |     QCOMPARE(dest, expected); | 
| 3247 | } | 
| 3248 |  | 
| 3249 | void tst_QPainter::largeImagePainting_data() | 
| 3250 | { | 
| 3251 |     QTest::addColumn<int>(name: "width" ); | 
| 3252 |     QTest::addColumn<int>(name: "height" ); | 
| 3253 |     QTest::addColumn<bool>(name: "antialiased" ); | 
| 3254 |  | 
| 3255 |     QTest::newRow(dataTag: "tall" ) << 1 << 32767 << false; | 
| 3256 |     QTest::newRow(dataTag: "tall aa" ) << 1 << 32767 << true; | 
| 3257 |     QTest::newRow(dataTag: "wide" ) << 32767 << 1 << false; | 
| 3258 |     QTest::newRow(dataTag: "wide aa" ) << 32767 << 1 << true; | 
| 3259 | } | 
| 3260 |  | 
| 3261 | void tst_QPainter::largeImagePainting() | 
| 3262 | { | 
| 3263 |     QPainterPath path; | 
| 3264 |     path.addRect(x: 0, y: 0, w: 1, h: 1); | 
| 3265 |     path.addRect(x: 2, y: 0, w: 1, h: 1); | 
| 3266 |     path.addRect(x: 0, y: 2, w: 1, h: 1); | 
| 3267 |  | 
| 3268 |     QFETCH(int, width); | 
| 3269 |     QFETCH(int, height); | 
| 3270 |     QFETCH(bool, antialiased); | 
| 3271 |  | 
| 3272 |     QImage img(width, height, QImage::Format_ARGB32_Premultiplied); | 
| 3273 |     img.fill(pixel: 0x0); | 
| 3274 |  | 
| 3275 |     QPainter p(&img); | 
| 3276 |     p.setPen(Qt::NoPen); | 
| 3277 |     p.setBrush(Qt::white); | 
| 3278 |  | 
| 3279 |     p.setRenderHint(hint: QPainter::Antialiasing, on: antialiased); | 
| 3280 |  | 
| 3281 |     for (int i = 0; i < img.width(); i += 4) { | 
| 3282 |         p.drawPath(path); | 
| 3283 |         p.translate(dx: 4, dy: 0); | 
| 3284 |     } | 
| 3285 |  | 
| 3286 |     p.resetTransform(); | 
| 3287 |  | 
| 3288 |     for (int i = 4; i < img.height(); i += 4) { | 
| 3289 |         p.translate(dx: 0, dy: 4); | 
| 3290 |         p.drawPath(path); | 
| 3291 |     } | 
| 3292 |  | 
| 3293 |     for (int i = 0; i < img.width(); ++i) { | 
| 3294 |         if (i % 2) | 
| 3295 |             QCOMPARE(img.pixel(i, 0), 0x0U); | 
| 3296 |         else | 
| 3297 |             QCOMPARE(img.pixel(i, 0), 0xffffffffU); | 
| 3298 |     } | 
| 3299 |  | 
| 3300 |     for (int i = 1; i < img.height(); ++i) { | 
| 3301 |         if (i % 2) | 
| 3302 |             QCOMPARE(img.pixel(0, i), 0x0U); | 
| 3303 |         else | 
| 3304 |             QCOMPARE(img.pixel(0, i), 0xffffffffU); | 
| 3305 |     } | 
| 3306 | } | 
| 3307 |  | 
| 3308 | void tst_QPainter::imageScaling_task206785() | 
| 3309 | { | 
| 3310 |     QImage src(32, 2, QImage::Format_ARGB32_Premultiplied); | 
| 3311 |     src.fill(pixel: 0xffffffff); | 
| 3312 |  | 
| 3313 |     QImage dst(128, 128, QImage::Format_ARGB32_Premultiplied); | 
| 3314 |  | 
| 3315 |     QImage expected(128, 128, QImage::Format_ARGB32_Premultiplied); | 
| 3316 |     expected.fill(pixel: 0xffffffff); | 
| 3317 |  | 
| 3318 |     for (int i = 1; i < 5; ++i) { | 
| 3319 |         qreal scale = i / qreal(5); | 
| 3320 |  | 
| 3321 |         dst.fill(pixel: 0xff000000); | 
| 3322 |  | 
| 3323 |         QPainter p(&dst); | 
| 3324 |         p.scale(sx: dst.width() / qreal(src.width()), sy: scale); | 
| 3325 |  | 
| 3326 |         for (int y = 0; y * scale < dst.height(); ++y) | 
| 3327 |             p.drawImage(x: 0, y, image: src); | 
| 3328 |  | 
| 3329 |         p.end(); | 
| 3330 |  | 
| 3331 |         QCOMPARE(dst, expected); | 
| 3332 |     } | 
| 3333 | } | 
| 3334 |  | 
| 3335 | #define FOR_EACH_NEIGHBOR_8 for (int dx = -1; dx <= 1; ++dx) for (int dy = -1; dy <= 1; ++dy) if (dx != 0 || dy != 0) | 
| 3336 | #define FOR_EACH_NEIGHBOR_4 for (int dx = -1; dx <= 1; ++dx) for (int dy = -1; dy <= 1; ++dy) if ((dx == 0) != (dy == 0)) | 
| 3337 |  | 
| 3338 | uint qHash(const QPoint &point) | 
| 3339 | { | 
| 3340 |     return qHash(key: qMakePair(x: point.x(), y: point.y())); | 
| 3341 | } | 
| 3342 |  | 
| 3343 | bool verifyOutlineFillConsistency(const QImage &img, QRgb outside, QRgb inside, QRgb outline) | 
| 3344 | { | 
| 3345 |     if (img.pixel(x: img.width() / 2, y: img.height() / 2) != inside) | 
| 3346 |         return false; | 
| 3347 |  | 
| 3348 |     int x = img.width() / 2; | 
| 3349 |     int y = img.height() / 2; | 
| 3350 |  | 
| 3351 |     while (img.pixel(x: ++x, y) == inside) | 
| 3352 |         ; | 
| 3353 |  | 
| 3354 |     if (img.pixel(x, y) != outline) | 
| 3355 |         return false; | 
| 3356 |  | 
| 3357 |     QQueue<QPoint> discovered; | 
| 3358 |     discovered.enqueue(t: QPoint(x, y)); | 
| 3359 |  | 
| 3360 |     QVector<bool> visited(img.width() * img.height()); | 
| 3361 |     visited.fill(from: false); | 
| 3362 |  | 
| 3363 |     while (!discovered.isEmpty()) { | 
| 3364 |         QPoint p = discovered.dequeue(); | 
| 3365 |         QRgb pixel = img.pixel(x: p.x(), y: p.y()); | 
| 3366 |  | 
| 3367 |         bool &v = visited[p.y() * img.width() + p.x()]; | 
| 3368 |         if (v) | 
| 3369 |             continue; | 
| 3370 |         v = true; | 
| 3371 |  | 
| 3372 |         if (pixel == outline) { | 
| 3373 |             FOR_EACH_NEIGHBOR_8 { | 
| 3374 |                 QPoint x(p.x() + dx, p.y() + dy); | 
| 3375 |                 discovered.enqueue(t: x); | 
| 3376 |             } | 
| 3377 |         } else { | 
| 3378 |             FOR_EACH_NEIGHBOR_4 { | 
| 3379 |                 if ((dx == 0) == (dy == 0)) | 
| 3380 |                     continue; | 
| 3381 |                 QRgb neighbor = img.pixel(x: p.x() + dx, y: p.y() + dy); | 
| 3382 |                 if ((pixel == inside && neighbor == outside) || | 
| 3383 |                     (pixel == outside && neighbor == inside)) | 
| 3384 |                     return false; | 
| 3385 |             } | 
| 3386 |         } | 
| 3387 |     } | 
| 3388 |  | 
| 3389 |     return true; | 
| 3390 | } | 
| 3391 |  | 
| 3392 | #undef FOR_EACH_NEIGHBOR_8 | 
| 3393 | #undef FOR_EACH_NEIGHBOR_4 | 
| 3394 |  | 
| 3395 | void tst_QPainter::outlineFillConsistency() | 
| 3396 | { | 
| 3397 |     QImage dst(256, 256, QImage::Format_ARGB32_Premultiplied); | 
| 3398 |  | 
| 3399 |     QPolygonF poly; | 
| 3400 |     poly << QPointF(5, -100) << QPointF(-70, 20) << QPointF(95, 25); | 
| 3401 |  | 
| 3402 |     QPen pen(Qt::red); | 
| 3403 |     QBrush brush(Qt::black); | 
| 3404 |  | 
| 3405 |     QRgb background = 0xffffffff; | 
| 3406 |     for (int i = 0; i < 360; ++i) { | 
| 3407 |         dst.fill(pixel: background); | 
| 3408 |  | 
| 3409 |         QPainter p(&dst); | 
| 3410 |         p.translate(dx: dst.width() / 2, dy: dst.height() / 2); | 
| 3411 |  | 
| 3412 |         QPolygonF copy = poly; | 
| 3413 |         for (int j = 0; j < copy.size(); ++j) | 
| 3414 |             copy[j] = QTransform().rotate(a: i).map(p: copy[j]); | 
| 3415 |  | 
| 3416 |         p.setPen(pen); | 
| 3417 |         p.setBrush(brush); | 
| 3418 |         p.drawPolygon(polygon: copy); | 
| 3419 |         p.end(); | 
| 3420 |  | 
| 3421 |         QVERIFY(verifyOutlineFillConsistency(dst, background, brush.color().rgba(), pen.color().rgba())); | 
| 3422 |     } | 
| 3423 | } | 
| 3424 |  | 
| 3425 | void tst_QPainter::drawImage_task217400_data() | 
| 3426 | { | 
| 3427 |     QTest::addColumn<QImage::Format>(name: "format" ); | 
| 3428 |  | 
| 3429 |     QTest::newRow(dataTag: "444" ) << QImage::Format_ARGB4444_Premultiplied; | 
| 3430 |     QTest::newRow(dataTag: "555" ) << QImage::Format_ARGB8555_Premultiplied; | 
| 3431 |     QTest::newRow(dataTag: "565" ) << QImage::Format_ARGB8565_Premultiplied; | 
| 3432 | //    QTest::newRow("666") << QImage::Format_ARGB6666_Premultiplied; | 
| 3433 |     QTest::newRow(dataTag: "888p" ) << QImage::Format_ARGB32_Premultiplied; | 
| 3434 |     QTest::newRow(dataTag: "888" ) << QImage::Format_ARGB32; | 
| 3435 | } | 
| 3436 |  | 
| 3437 | void tst_QPainter::drawImage_task217400() | 
| 3438 | { | 
| 3439 |     QFETCH(QImage::Format, format); | 
| 3440 |  | 
| 3441 |     const QImage src = QImage(QFINDTESTDATA("task217400.png" )) | 
| 3442 |                        .convertToFormat(f: format); | 
| 3443 |     QVERIFY(!src.isNull()); | 
| 3444 |  | 
| 3445 |     QImage expected(src.size(), format); | 
| 3446 |     { | 
| 3447 |         QPainter p(&expected); | 
| 3448 |         p.fillRect(x: 0, y: 0, w: expected.width(), h: expected.height(), c: Qt::white); | 
| 3449 |         p.drawImage(x: 0, y: 0, image: src); | 
| 3450 |     } | 
| 3451 |  | 
| 3452 |     for (int i = 1; i <= 4; ++i) { | 
| 3453 |         QImage dest(src.width() + i, src.height(), format); | 
| 3454 |         { | 
| 3455 |             QPainter p(&dest); | 
| 3456 |             p.fillRect(x: 0, y: 0, w: dest.width(), h: dest.height(), c: Qt::white); | 
| 3457 |             p.drawImage(x: i, y: 0, image: src); | 
| 3458 |         } | 
| 3459 |  | 
| 3460 |         const QImage result = dest.copy(x: i, y: 0, w: src.width(), h: src.height()); | 
| 3461 |  | 
| 3462 |         QCOMPARE(result, expected); | 
| 3463 |     } | 
| 3464 | } | 
| 3465 |  | 
| 3466 | void tst_QPainter::drawImage_task258776() | 
| 3467 | { | 
| 3468 |     QImage src(16, 16, QImage::Format_RGB888); | 
| 3469 |     QImage dest(33, 33, QImage::Format_RGB888); | 
| 3470 |     src.fill(pixel: 0x00ff00); | 
| 3471 |     dest.fill(pixel: 0xff0000); | 
| 3472 |  | 
| 3473 |     QPainter painter(&dest); | 
| 3474 |     painter.drawImage(targetRect: QRectF(0.499, 0.499, 32, 32), image: src, sourceRect: QRectF(0, 0, 16, 16)); | 
| 3475 |     painter.end(); | 
| 3476 |  | 
| 3477 |     QImage expected(33, 33, QImage::Format_RGB32); | 
| 3478 |     expected.fill(pixel: 0xff0000); | 
| 3479 |  | 
| 3480 |     painter.begin(&expected); | 
| 3481 |     painter.drawImage(r: QRectF(0, 0, 32, 32), image: src); | 
| 3482 |     painter.end(); | 
| 3483 |  | 
| 3484 |     dest = dest.convertToFormat(f: QImage::Format_RGB32); | 
| 3485 |  | 
| 3486 |     dest.save(fileName: "dest.png" ); | 
| 3487 |     expected.save(fileName: "expected.png" ); | 
| 3488 |     QCOMPARE(dest, expected); | 
| 3489 | } | 
| 3490 |  | 
| 3491 | void tst_QPainter::drawImage_QTBUG28324() | 
| 3492 | { | 
| 3493 |     QImage dest(512, 512, QImage::Format_ARGB32_Premultiplied); | 
| 3494 |     dest.fill(pixel: 0x0); | 
| 3495 |  | 
| 3496 |     int x = 263; int y = 89; int w = 61; int h = 39; | 
| 3497 |  | 
| 3498 |     QImage source(w, h, QImage::Format_ARGB32_Premultiplied); | 
| 3499 |     quint32 *b = (quint32 *)source.bits(); | 
| 3500 |     for (int j = 0; j < w * h; ++j) | 
| 3501 |         b[j] = 0x7f7f7f7f; | 
| 3502 |  | 
| 3503 |     // nothing to test here since the bug is about | 
| 3504 |     // an invalid memory read, which valgrind | 
| 3505 |     // would complain about | 
| 3506 |     QPainter p(&dest); | 
| 3507 |     p.drawImage(x, y, image: source); | 
| 3508 | } | 
| 3509 |  | 
| 3510 | void tst_QPainter::clipRectSaveRestore() | 
| 3511 | { | 
| 3512 |     QImage img(64, 64, QImage::Format_ARGB32_Premultiplied); | 
| 3513 |     img.fill(pixel: 0x0); | 
| 3514 |  | 
| 3515 |     QPainter p(&img); | 
| 3516 |     p.setClipRect(QRect(0, 0, 10, 10)); | 
| 3517 |     p.save(); | 
| 3518 |     p.setClipRect(QRect(5, 5, 5, 5), op: Qt::IntersectClip); | 
| 3519 |     p.restore(); | 
| 3520 |     p.fillRect(x: 0, y: 0, w: 64, h: 64, c: Qt::black); | 
| 3521 |     p.end(); | 
| 3522 |  | 
| 3523 |     QCOMPARE(img.pixel(0, 0), QColor(Qt::black).rgba()); | 
| 3524 | } | 
| 3525 |  | 
| 3526 | void tst_QPainter::clipStateSaveRestore() | 
| 3527 | { | 
| 3528 |     QImage img(16, 16, QImage::Format_RGB32); | 
| 3529 |     img.fill(color: Qt::blue); | 
| 3530 |     { | 
| 3531 |         QPainter p(&img); | 
| 3532 |         p.setClipRect(QRect(5, 5, 10, 10)); | 
| 3533 |         p.save(); | 
| 3534 |         p.setClipping(false); | 
| 3535 |         p.restore(); | 
| 3536 |         p.fillRect(x: 0, y: 0, w: 16, h: 16, c: Qt::red); | 
| 3537 |         p.end(); | 
| 3538 |         QCOMPARE(img.pixel(0, 0), QColor(Qt::blue).rgb()); | 
| 3539 |     } | 
| 3540 |  | 
| 3541 |     img.fill(color: Qt::blue); | 
| 3542 |     { | 
| 3543 |         QPainter p(&img); | 
| 3544 |         p.setClipRect(QRect(5, 5, 10, 10)); | 
| 3545 |         p.setClipping(false); | 
| 3546 |         p.save(); | 
| 3547 |         p.setClipping(true); | 
| 3548 |         p.restore(); | 
| 3549 |         p.fillRect(x: 0, y: 0, w: 16, h: 16, c: Qt::red); | 
| 3550 |         p.end(); | 
| 3551 |         QCOMPARE(img.pixel(0, 0), QColor(Qt::red).rgb()); | 
| 3552 |     } | 
| 3553 | } | 
| 3554 |  | 
| 3555 | void tst_QPainter::clippedImage() | 
| 3556 | { | 
| 3557 |     QImage img(16, 16, QImage::Format_ARGB32_Premultiplied); | 
| 3558 |     img.fill(pixel: 0x0); | 
| 3559 |  | 
| 3560 |     QImage src(16, 16, QImage::Format_RGB32); | 
| 3561 |     src.fill(pixel: QColor(Qt::red).rgba()); | 
| 3562 |  | 
| 3563 |     QPainter p(&img); | 
| 3564 |     p.setClipRect(QRect(1, 1, 14, 14)); | 
| 3565 |     p.drawImage(x: 0, y: 0, image: src); | 
| 3566 |     p.end(); | 
| 3567 |  | 
| 3568 |     QCOMPARE(img.pixel(0, 0), 0x0U); | 
| 3569 |     QCOMPARE(img.pixel(1, 1), src.pixel(1, 1)); | 
| 3570 | } | 
| 3571 |  | 
| 3572 | void tst_QPainter::stateResetBetweenQPainters() | 
| 3573 | { | 
| 3574 |     QImage img(16, 16, QImage::Format_ARGB32); | 
| 3575 |  | 
| 3576 |     { | 
| 3577 |         QPainter p(&img); | 
| 3578 |         p.setCompositionMode(QPainter::CompositionMode_Source); | 
| 3579 |         p.fillRect(x: 0, y: 0, w: 16, h: 16, c: Qt::red); | 
| 3580 |     } | 
| 3581 |  | 
| 3582 |     { | 
| 3583 |         QPainter p2(&img); | 
| 3584 |         p2.fillRect(x: 0, y: 0, w: 16, h: 16, b: QColor(0, 0, 255, 63)); | 
| 3585 |     } | 
| 3586 |  | 
| 3587 |     img.save(fileName: "foo.png" ); | 
| 3588 |  | 
| 3589 |     QVERIFY(img.pixel(0, 0) != qRgba(0, 0, 255, 63)); | 
| 3590 |     QVERIFY(qRed(img.pixel(0, 0)) > 0); // We didn't erase the red channel... | 
| 3591 |     QVERIFY(qBlue(img.pixel(0, 0)) < 255); // We blended the blue channel | 
| 3592 | } | 
| 3593 |  | 
| 3594 | void tst_QPainter::drawRect_task215378() | 
| 3595 | { | 
| 3596 |     QImage img(11, 11, QImage::Format_ARGB32_Premultiplied); | 
| 3597 |     img.fill(pixel: QColor(Qt::white).rgba()); | 
| 3598 |  | 
| 3599 |     QPainter p(&img); | 
| 3600 |     p.setPen(QColor(127, 127, 127, 127)); | 
| 3601 |     p.drawRect(x: 0, y: 0, w: 10, h: 10); | 
| 3602 |     p.end(); | 
| 3603 |  | 
| 3604 |     QCOMPARE(img.pixel(0, 0), img.pixel(1, 0)); | 
| 3605 |     QCOMPARE(img.pixel(0, 0), img.pixel(0, 1)); | 
| 3606 |     QVERIFY(img.pixel(0, 0) != img.pixel(1, 1)); | 
| 3607 | } | 
| 3608 |  | 
| 3609 | void tst_QPainter::drawRect_task247505() | 
| 3610 | { | 
| 3611 |     QImage a(10, 10, QImage::Format_ARGB32_Premultiplied); | 
| 3612 |     a.fill(pixel: 0); | 
| 3613 |     QImage b = a; | 
| 3614 |  | 
| 3615 |     QPainter p(&a); | 
| 3616 |     p.setPen(Qt::NoPen); | 
| 3617 |     p.setBrush(Qt::black); | 
| 3618 |     p.drawRect(rect: QRectF(10, 0, -10, 10)); | 
| 3619 |     p.end(); | 
| 3620 |     p.begin(&b); | 
| 3621 |     p.setPen(Qt::NoPen); | 
| 3622 |     p.setBrush(Qt::black); | 
| 3623 |     p.drawRect(rect: QRectF(0, 0, 10, 10)); | 
| 3624 |     p.end(); | 
| 3625 |  | 
| 3626 |     QCOMPARE(a, b); | 
| 3627 | } | 
| 3628 |  | 
| 3629 | void tst_QPainter::drawImage_data() | 
| 3630 | { | 
| 3631 |     QTest::addColumn<int>(name: "x" ); | 
| 3632 |     QTest::addColumn<int>(name: "y" ); | 
| 3633 |     QTest::addColumn<int>(name: "w" ); | 
| 3634 |     QTest::addColumn<int>(name: "h" ); | 
| 3635 |     QTest::addColumn<QImage::Format>(name: "srcFormat" ); | 
| 3636 |     QTest::addColumn<QImage::Format>(name: "dstFormat" ); | 
| 3637 |  | 
| 3638 |     for (int srcFormat = QImage::Format_Mono; srcFormat < QImage::NImageFormats; ++srcFormat) { | 
| 3639 |         for (int dstFormat = QImage::Format_Mono; dstFormat < QImage::NImageFormats; ++dstFormat) { | 
| 3640 |             // Indexed8 can't be painted to, and Alpha8 can't hold a color. | 
| 3641 |             if (dstFormat == QImage::Format_Indexed8 || dstFormat == QImage::Format_Alpha8) | 
| 3642 |                 continue; | 
| 3643 |             for (int odd_x = 0; odd_x <= 1; ++odd_x) { | 
| 3644 |                 for (int odd_width = 0; odd_width <= 1; ++odd_width) { | 
| 3645 |                     QTest::addRow(format: "srcFormat %d, dstFormat %d, odd x: %d, odd width: %d" , | 
| 3646 |                                   srcFormat, dstFormat, odd_x, odd_width) | 
| 3647 |                         << (10 + odd_x) << 10 << (20 + odd_width) << 20 | 
| 3648 |                         << QImage::Format(srcFormat) | 
| 3649 |                         << QImage::Format(dstFormat); | 
| 3650 |                 } | 
| 3651 |             } | 
| 3652 |         } | 
| 3653 |     } | 
| 3654 | } | 
| 3655 |  | 
| 3656 | bool verifyImage(const QImage &img, int x, int y, int w, int h, uint background) | 
| 3657 | { | 
| 3658 |     int imgWidth = img.width(); | 
| 3659 |     int imgHeight = img.height(); | 
| 3660 |     for (int i = 0; i < imgHeight; ++i) { | 
| 3661 |         for (int j = 0; j < imgWidth; ++j) { | 
| 3662 |             uint pixel = img.pixel(x: j, y: i); | 
| 3663 |             bool outside = j < x || j >= (x + w) || i < y || i >= (y + h); | 
| 3664 |             if (outside != (pixel == background)) { | 
| 3665 |                 //printf("%d %d, expected %x, got %x, outside: %d\n", x, y, background, pixel, outside); | 
| 3666 |                 return false; | 
| 3667 |             } | 
| 3668 |         } | 
| 3669 |     } | 
| 3670 |  | 
| 3671 |     return true; | 
| 3672 | } | 
| 3673 |  | 
| 3674 | void tst_QPainter::drawImage() | 
| 3675 | { | 
| 3676 |     QFETCH(int, x); | 
| 3677 |     QFETCH(int, y); | 
| 3678 |     QFETCH(int, w); | 
| 3679 |     QFETCH(int, h); | 
| 3680 |     QFETCH(QImage::Format, srcFormat); | 
| 3681 |     QFETCH(QImage::Format, dstFormat); | 
| 3682 |  | 
| 3683 |     QImage dst(40, 40, QImage::Format_RGB32); | 
| 3684 |     dst.fill(pixel: 0xffffffff); | 
| 3685 |  | 
| 3686 |     dst = dst.convertToFormat(f: dstFormat); | 
| 3687 |     uint background = dst.pixel(x: 0, y: 0); | 
| 3688 |  | 
| 3689 |     QImage src(w, h, QImage::Format_RGB32); | 
| 3690 |     src.fill(pixel: 0xff000000); | 
| 3691 |     src = src.convertToFormat(f: srcFormat); | 
| 3692 |  | 
| 3693 |     QPainter p(&dst); | 
| 3694 |     p.drawImage(x, y, image: src); | 
| 3695 |     p.end(); | 
| 3696 |  | 
| 3697 |     QVERIFY(verifyImage(dst, x, y, w, h, background)); | 
| 3698 | } | 
| 3699 |  | 
| 3700 | void tst_QPainter::imageCoordinateLimit() | 
| 3701 | { | 
| 3702 |     QImage img(64, 40000, QImage::Format_MonoLSB); | 
| 3703 |     QPainter p(&img); | 
| 3704 |     p.drawText(x: 10, y: 36000, s: QLatin1String("foo" )); | 
| 3705 |     p.setPen(QPen(Qt::black, 2)); | 
| 3706 |     p.drawLine(x1: 10, y1: 0, x2: 60, y2: 40000); | 
| 3707 |  | 
| 3708 |     p.setRenderHint(hint: QPainter::Antialiasing); | 
| 3709 |     p.drawLine(x1: 10, y1: 0, x2: 60, y2: 40000); | 
| 3710 | } | 
| 3711 |  | 
| 3712 |  | 
| 3713 | void tst_QPainter::imageBlending_data() | 
| 3714 | { | 
| 3715 |     QTest::addColumn<QImage::Format>(name: "sourceFormat" ); | 
| 3716 |     QTest::addColumn<QImage::Format>(name: "destFormat" ); | 
| 3717 |     QTest::addColumn<int>(name: "error" ); | 
| 3718 |  | 
| 3719 |     int error_rgb565 = ((1<<3) + (1<<2) + (1<<3)); | 
| 3720 |     QTest::newRow(dataTag: "rgb565_on_rgb565" ) << QImage::Format_RGB16 | 
| 3721 |                                       << QImage::Format_RGB16 | 
| 3722 |                                       << 0; | 
| 3723 |     QTest::newRow(dataTag: "argb8565_on_rgb565" ) << QImage::Format_ARGB8565_Premultiplied | 
| 3724 |                                         << QImage::Format_RGB16 | 
| 3725 |                                         << error_rgb565; | 
| 3726 |  | 
| 3727 |     QTest::newRow(dataTag: "rgb32_on_rgb565" ) << QImage::Format_RGB32 | 
| 3728 |                                      << QImage::Format_RGB16 | 
| 3729 |                                      << error_rgb565; | 
| 3730 |  | 
| 3731 |     QTest::newRow(dataTag: "argb32pm_on_rgb565" ) << QImage::Format_ARGB32_Premultiplied | 
| 3732 |                                         << QImage::Format_RGB16 | 
| 3733 |                                         << error_rgb565; | 
| 3734 | } | 
| 3735 |  | 
| 3736 | int diffColor(quint32 ap, quint32 bp) | 
| 3737 | { | 
| 3738 |     int a = qAlpha(rgb: ap) - qAlpha(rgb: bp); | 
| 3739 |     int r = qRed(rgb: ap) - qRed(rgb: bp); | 
| 3740 |     int b = qBlue(rgb: ap) - qBlue(rgb: bp); | 
| 3741 |     int g = qBlue(rgb: ap) - qBlue(rgb: bp); | 
| 3742 |  | 
| 3743 |     return qAbs(t: a) + qAbs(t: r) + qAbs(t: g) + qAbs(t: b); | 
| 3744 | } | 
| 3745 |  | 
| 3746 | // this test assumes premultiplied pixels... | 
| 3747 |  | 
| 3748 | void tst_QPainter::imageBlending() | 
| 3749 | { | 
| 3750 |     QFETCH(QImage::Format, sourceFormat); | 
| 3751 |     QFETCH(QImage::Format, destFormat); | 
| 3752 |     QFETCH(int, error); | 
| 3753 |  | 
| 3754 |     QImage dest; | 
| 3755 |     { | 
| 3756 |         QImage orig_dest(6, 6, QImage::Format_ARGB32_Premultiplied); | 
| 3757 |         orig_dest.fill(pixel: 0); | 
| 3758 |         QPainter p(&orig_dest); | 
| 3759 |         p.fillRect(x: 0, y: 0, w: 6, h: 3, b: QColor::fromRgbF(r: 1, g: 0, b: 0)); | 
| 3760 |         p.fillRect(x: 3, y: 0, w: 3, h: 6, b: QColor::fromRgbF(r: 0, g: 0, b: 1, a: 0.5)); | 
| 3761 |         p.end(); | 
| 3762 |         dest = orig_dest.convertToFormat(f: destFormat); | 
| 3763 |  | 
| 3764 |         // An image like this: (r = red, m = magenta, b = light alpha blue, 0 = transparent) | 
| 3765 |         // r r r m m m | 
| 3766 |         // r r r m m m | 
| 3767 |         // r r r m m m | 
| 3768 |         // 0 0 0 b b b | 
| 3769 |         // 0 0 0 b b b | 
| 3770 |         // 0 0 0 b b b | 
| 3771 |     } | 
| 3772 |  | 
| 3773 |     QImage source; | 
| 3774 |     { | 
| 3775 |         QImage orig_source(6, 6, QImage::Format_ARGB32_Premultiplied); | 
| 3776 |         orig_source.fill(pixel: 0); | 
| 3777 |         QPainter p(&orig_source); | 
| 3778 |         p.fillRect(x: 1, y: 1, w: 4, h: 4, b: QColor::fromRgbF(r: 0, g: 1, b: 0, a: 0.5)); | 
| 3779 |         p.fillRect(x: 2, y: 2, w: 2, h: 2, b: QColor::fromRgbF(r: 0, g: 1, b: 0)); | 
| 3780 |         p.end(); | 
| 3781 |         source = orig_source.convertToFormat(f: sourceFormat); | 
| 3782 |  | 
| 3783 |         // An image like this: (0 = transparent, . = green at 0.5 alpha, g = opaque green. | 
| 3784 |         // 0 0 0 0 0 0 | 
| 3785 |         // 0 . . . . 0 | 
| 3786 |         // 0 . g g . 0 | 
| 3787 |         // 0 . g g . 0 | 
| 3788 |         // 0 . . . . 0 | 
| 3789 |         // 0 0 0 0 0 0 | 
| 3790 |     } | 
| 3791 |  | 
| 3792 |     QPainter p(&dest); | 
| 3793 |     p.drawImage(x: 0, y: 0, image: source); | 
| 3794 |     p.end(); | 
| 3795 |  | 
| 3796 |     // resulting image: | 
| 3797 |     // r  r  r  m  m  m | 
| 3798 |     // r  r. r. m. m. m | 
| 3799 |     // r  r. g  g  m. m | 
| 3800 |     // 0  .  g  g  b. b | 
| 3801 |     // 0  .  .  b. b. b | 
| 3802 |     // 0  0  0  b  b  b | 
| 3803 |  | 
| 3804 |     // the g pixels, always green.. | 
| 3805 |     QVERIFY(diffColor(dest.pixel(2, 2), 0xff00ff00) <= error); // g | 
| 3806 |  | 
| 3807 |     if (source.hasAlphaChannel()) { | 
| 3808 |         QVERIFY(diffColor(dest.pixel(0, 0), 0xffff0000) <= error); // r | 
| 3809 |         QVERIFY(diffColor(dest.pixel(5, 0), 0xff7f007f) <= error); // m | 
| 3810 |         QVERIFY(diffColor(dest.pixel(1, 1), 0xff7f7f00) <= error); // r. | 
| 3811 |         QVERIFY(diffColor(dest.pixel(4, 1), 0xff3f7f3f) <= error); // m. | 
| 3812 |         if (dest.hasAlphaChannel()) { | 
| 3813 |             QVERIFY(diffColor(dest.pixel(1, 3), 0x7f007f00) <= error); // . | 
| 3814 |             QVERIFY(diffColor(dest.pixel(4, 3), 0x7f007f3f) <= error); // b. | 
| 3815 |             QVERIFY(diffColor(dest.pixel(4, 3), 0x7f007f3f) <= error); // b. | 
| 3816 |             QVERIFY(diffColor(dest.pixel(4, 4), 0x7f00007f) <= error); // b | 
| 3817 |             QVERIFY(diffColor(dest.pixel(4, 0), 0) <= 0); // 0 | 
| 3818 |        } | 
| 3819 |     } else { | 
| 3820 |         QVERIFY(diffColor(dest.pixel(0, 0), 0xff000000) <= 0); | 
| 3821 |         QVERIFY(diffColor(dest.pixel(1, 1), 0xff007f00) <= error); | 
| 3822 |     } | 
| 3823 | } | 
| 3824 |  | 
| 3825 | void tst_QPainter::imageBlending_clipped() | 
| 3826 | { | 
| 3827 |     QImage src(20, 20, QImage::Format_RGB16); | 
| 3828 |     QPainter p(&src); | 
| 3829 |     p.fillRect(r: src.rect(), c: Qt::red); | 
| 3830 |     p.end(); | 
| 3831 |  | 
| 3832 |     QImage dst(40, 20, QImage::Format_RGB16); | 
| 3833 |     p.begin(&dst); | 
| 3834 |     p.fillRect(r: dst.rect(), c: Qt::white); | 
| 3835 |     p.end(); | 
| 3836 |  | 
| 3837 |     QImage expected = dst; | 
| 3838 |  | 
| 3839 |     p.begin(&dst); | 
| 3840 |     p.setClipRect(QRect(23, 0, 20, 20)); | 
| 3841 |  | 
| 3842 |     // should be completely clipped | 
| 3843 |     p.drawImage(r: QRectF(3, 0, 20, 20), image: src); | 
| 3844 |     p.end(); | 
| 3845 |  | 
| 3846 |     // dst should be left unchanged | 
| 3847 |     QCOMPARE(dst, expected); | 
| 3848 | } | 
| 3849 |  | 
| 3850 | void tst_QPainter::paintOnNullPixmap() | 
| 3851 | { | 
| 3852 |     QPixmap pix(16, 16); | 
| 3853 |  | 
| 3854 |     QPixmap textPixmap; | 
| 3855 |     QPainter p(&textPixmap); | 
| 3856 |     p.drawPixmap(x: 10, y: 10, pm: pix); | 
| 3857 |     p.end(); | 
| 3858 |  | 
| 3859 |     QPixmap textPixmap2(16,16); | 
| 3860 |     p.begin(&textPixmap2); | 
| 3861 |     p.end(); | 
| 3862 | } | 
| 3863 |  | 
| 3864 | void tst_QPainter::checkCompositionMode() | 
| 3865 | { | 
| 3866 |     QImage refImage(50,50,QImage::Format_ARGB32); | 
| 3867 |     QPainter painter(&refImage); | 
| 3868 |     painter.fillRect(r: QRect(0,0,50,50),c: Qt::blue); | 
| 3869 |  | 
| 3870 |     QImage testImage(50,50,QImage::Format_ARGB32); | 
| 3871 |     QPainter p(&testImage); | 
| 3872 |     p.fillRect(r: QRect(0,0,50,50),c: Qt::red); | 
| 3873 |     p.save(); | 
| 3874 |     p.setCompositionMode(QPainter::CompositionMode_SourceOut); | 
| 3875 |     p.restore(); | 
| 3876 |     p.fillRect(r: QRect(0,0,50,50),c: Qt::blue); | 
| 3877 |  | 
| 3878 |     QCOMPARE(refImage.pixel(20,20),testImage.pixel(20,20)); | 
| 3879 | } | 
| 3880 |  | 
| 3881 | static QLinearGradient inverseGradient(QLinearGradient g) | 
| 3882 | { | 
| 3883 |     QLinearGradient g2 = g; | 
| 3884 |  | 
| 3885 |     QGradientStops stops = g.stops(); | 
| 3886 |  | 
| 3887 |     QGradientStops inverse; | 
| 3888 |     foreach (QGradientStop stop, stops) | 
| 3889 |         inverse << QGradientStop(1 - stop.first, stop.second); | 
| 3890 |  | 
| 3891 |     g2.setStops(inverse); | 
| 3892 |     return g2; | 
| 3893 | } | 
| 3894 |  | 
| 3895 | void tst_QPainter::linearGradientSymmetry_data() | 
| 3896 | { | 
| 3897 |     QTest::addColumn<QGradientStops>(name: "stops" ); | 
| 3898 |  | 
| 3899 |     if (sizeof(qreal) != sizeof(float)) { | 
| 3900 |         QGradientStops stops; | 
| 3901 |         stops << qMakePair(x: qreal(0.0), y: QColor(Qt::blue)); | 
| 3902 |         stops << qMakePair(x: qreal(0.2), y: QColor(220, 220, 220, 0)); | 
| 3903 |         stops << qMakePair(x: qreal(0.6), y: QColor(Qt::red)); | 
| 3904 |         stops << qMakePair(x: qreal(0.9), y: QColor(220, 220, 220, 255)); | 
| 3905 |         stops << qMakePair(x: qreal(1.0), y: QColor(Qt::black)); | 
| 3906 |         QTest::newRow(dataTag: "multiple stops" ) << stops; | 
| 3907 |     } | 
| 3908 |  | 
| 3909 |     { | 
| 3910 |         QGradientStops stops; | 
| 3911 |         stops << qMakePair(x: qreal(0.0), y: QColor(Qt::blue)); | 
| 3912 |         stops << qMakePair(x: qreal(1.0), y: QColor(Qt::black)); | 
| 3913 |         QTest::newRow(dataTag: "two stops" ) << stops; | 
| 3914 |     } | 
| 3915 |  | 
| 3916 |     if (sizeof(qreal) != sizeof(float)) { | 
| 3917 |         QGradientStops stops; | 
| 3918 |         stops << qMakePair(x: qreal(0.3), y: QColor(Qt::blue)); | 
| 3919 |         stops << qMakePair(x: qreal(0.6), y: QColor(Qt::black)); | 
| 3920 |         QTest::newRow(dataTag: "two stops 2" ) << stops; | 
| 3921 |     } | 
| 3922 | } | 
| 3923 |  | 
| 3924 | void tst_QPainter::linearGradientSymmetry() | 
| 3925 | { | 
| 3926 |     QFETCH(QGradientStops, stops); | 
| 3927 |  | 
| 3928 |     QImage a(64, 8, QImage::Format_ARGB32_Premultiplied); | 
| 3929 |     QImage b(64, 8, QImage::Format_ARGB32_Premultiplied); | 
| 3930 |  | 
| 3931 |     a.fill(pixel: 0); | 
| 3932 |     b.fill(pixel: 0); | 
| 3933 |  | 
| 3934 |     QLinearGradient gradient(QRectF(b.rect()).topLeft(), QRectF(b.rect()).topRight()); | 
| 3935 |     gradient.setStops(stops); | 
| 3936 |  | 
| 3937 |     QPainter pa(&a); | 
| 3938 |     pa.fillRect(a.rect(), gradient); | 
| 3939 |     pa.end(); | 
| 3940 |  | 
| 3941 |     QPainter pb(&b); | 
| 3942 |     pb.fillRect(b.rect(), inverseGradient(g: gradient)); | 
| 3943 |     pb.end(); | 
| 3944 |  | 
| 3945 |     b = b.mirrored(horizontally: true); | 
| 3946 |     QCOMPARE(a, b); | 
| 3947 | } | 
| 3948 |  | 
| 3949 | void tst_QPainter::gradientPixelFormat_data() | 
| 3950 | { | 
| 3951 |     QTest::addColumn<QImage::Format>(name: "format" ); | 
| 3952 |  | 
| 3953 |     QTest::newRow(dataTag: "argb32" ) << QImage::Format_ARGB32; | 
| 3954 |     QTest::newRow(dataTag: "rgb32" ) << QImage::Format_RGB32; | 
| 3955 |     QTest::newRow(dataTag: "rgb888" ) << QImage::Format_RGB888; | 
| 3956 |     QTest::newRow(dataTag: "rgbx8888" ) << QImage::Format_RGBX8888; | 
| 3957 |     QTest::newRow(dataTag: "rgba8888" ) << QImage::Format_RGBA8888; | 
| 3958 |     QTest::newRow(dataTag: "rgba8888_pm" ) << QImage::Format_RGBA8888_Premultiplied; | 
| 3959 |     QTest::newRow(dataTag: "rgbx64" ) << QImage::Format_RGBX64; | 
| 3960 |     QTest::newRow(dataTag: "rgba64_pm" ) << QImage::Format_RGBA64_Premultiplied; | 
| 3961 | } | 
| 3962 |  | 
| 3963 | void tst_QPainter::gradientPixelFormat() | 
| 3964 | { | 
| 3965 |     QFETCH(QImage::Format, format); | 
| 3966 |  | 
| 3967 |     QImage a(8, 64, QImage::Format_ARGB32_Premultiplied); | 
| 3968 |     QImage b(8, 64, format); | 
| 3969 |  | 
| 3970 |  | 
| 3971 |     QGradientStops stops; | 
| 3972 |     stops << qMakePair(x: qreal(0.0), y: QColor(Qt::blue)); | 
| 3973 |     stops << qMakePair(x: qreal(0.3), y: QColor(Qt::red)); | 
| 3974 |     stops << qMakePair(x: qreal(0.6), y: QColor(Qt::green)); | 
| 3975 |     stops << qMakePair(x: qreal(1.0), y: QColor(Qt::black)); | 
| 3976 |  | 
| 3977 |     a.fill(pixel: 0); | 
| 3978 |     b.fill(pixel: 0); | 
| 3979 |  | 
| 3980 |     QLinearGradient gradient(QRectF(b.rect()).topLeft(), QRectF(b.rect()).bottomLeft()); | 
| 3981 |     gradient.setStops(stops); | 
| 3982 |  | 
| 3983 |     QPainter pa(&a); | 
| 3984 |     pa.fillRect(a.rect(), gradient); | 
| 3985 |     pa.end(); | 
| 3986 |  | 
| 3987 |     QPainter pb(&b); | 
| 3988 |     pb.fillRect(b.rect(), gradient); | 
| 3989 |     pb.end(); | 
| 3990 |  | 
| 3991 |     QCOMPARE(a, b.convertToFormat(QImage::Format_ARGB32_Premultiplied)); | 
| 3992 | } | 
| 3993 |  | 
| 3994 | void tst_QPainter::gradientInterpolation() | 
| 3995 | { | 
| 3996 |     QImage image(256, 8, QImage::Format_ARGB32_Premultiplied); | 
| 3997 |     QPainter painter; | 
| 3998 |  | 
| 3999 |     QLinearGradient gradient(QRectF(image.rect()).topLeft(), QRectF(image.rect()).topRight()); | 
| 4000 |     gradient.setColorAt(pos: 0.0, color: QColor(255, 0, 0, 0)); | 
| 4001 |     gradient.setColorAt(pos: 1.0, color: Qt::blue); | 
| 4002 |  | 
| 4003 |     image.fill(pixel: 0); | 
| 4004 |     painter.begin(&image); | 
| 4005 |     painter.fillRect(image.rect(), gradient); | 
| 4006 |     painter.end(); | 
| 4007 |  | 
| 4008 |     const QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(3)); | 
| 4009 |  | 
| 4010 |     for (int i = 0; i < 256; ++i) { | 
| 4011 |         QCOMPARE(qAlpha(line[i]), qBlue(line[i])); // bright blue | 
| 4012 |         QVERIFY(qAbs(qAlpha(line[i]) - i) < 3); // linear alpha | 
| 4013 |         QCOMPARE(qRed(line[i]), 0); // no red component | 
| 4014 |         QCOMPARE(qGreen(line[i]), 0); // no green component | 
| 4015 |     } | 
| 4016 |  | 
| 4017 |     gradient.setInterpolationMode(QGradient::ComponentInterpolation); | 
| 4018 |  | 
| 4019 |     image.fill(pixel: 0); | 
| 4020 |     painter.begin(&image); | 
| 4021 |     painter.fillRect(image.rect(), gradient); | 
| 4022 |     painter.end(); | 
| 4023 |  | 
| 4024 |     for (int i = 1; i < 256; ++i) { | 
| 4025 |         if (i < 128) { | 
| 4026 |             QVERIFY(qRed(line[i]) >= qBlue(line[i])); // red is dominant | 
| 4027 |         } else { | 
| 4028 |             QVERIFY(qRed(line[i]) <= qBlue(line[i])); // blue is dominant | 
| 4029 |         } | 
| 4030 |         QVERIFY((qRed(line[i]) - 0.5) * (qAlpha(line[i - 1]) - 0.5) <= (qRed(line[i - 1]) + 0.5) * (qAlpha(line[i]) + 0.5)); // decreasing red | 
| 4031 |         QVERIFY((qBlue(line[i]) + 0.5) * (qAlpha(line[i - 1]) + 0.5) >= (qBlue(line[i - 1]) - 0.5) * (qAlpha(line[i]) - 0.5)); // increasing blue | 
| 4032 |         QVERIFY(qAbs(qAlpha(line[i]) - i) < 3); // linear alpha | 
| 4033 |         QCOMPARE(qGreen(line[i]), 0); // no green component | 
| 4034 |     } | 
| 4035 | } | 
| 4036 |  | 
| 4037 | #if QT_CONFIG(raster_64bit) | 
| 4038 | void tst_QPainter::linearGradientRgb30_data() | 
| 4039 | { | 
| 4040 |     QTest::addColumn<QColor>(name: "stop0" ); | 
| 4041 |     QTest::addColumn<QColor>(name: "stop1" ); | 
| 4042 |  | 
| 4043 |     QTest::newRow(dataTag: "white->black" ) << QColor(Qt::white) << QColor(Qt::black); | 
| 4044 |     QTest::newRow(dataTag: "blue->black" ) << QColor(Qt::blue) << QColor(Qt::black); | 
| 4045 |     QTest::newRow(dataTag: "white->red" ) << QColor(Qt::white) << QColor(Qt::red); | 
| 4046 | } | 
| 4047 |  | 
| 4048 | void tst_QPainter::linearGradientRgb30() | 
| 4049 | { | 
| 4050 |     QFETCH(QColor, stop0); | 
| 4051 |     QFETCH(QColor, stop1); | 
| 4052 |  | 
| 4053 |     QLinearGradient gradient(0, 0, 1000, 1); | 
| 4054 |     gradient.setColorAt(pos: 0.0, color: stop0); | 
| 4055 |     gradient.setColorAt(pos: 1.0, color: stop1); | 
| 4056 |  | 
| 4057 |     QImage image(1000, 1, QImage::Format_RGB30); | 
| 4058 |     QPainter painter(&image); | 
| 4059 |     painter.fillRect(image.rect(), gradient); | 
| 4060 |     painter.end(); | 
| 4061 |  | 
| 4062 |     for (int i = 1; i < 1000; ++i) { | 
| 4063 |         QColor p1 = image.pixelColor(x: i - 1, y: 0); | 
| 4064 |         QColor p2 = image.pixelColor(x: i, y: 0); | 
| 4065 |         QVERIFY(p1 != p2); | 
| 4066 |         QVERIFY(qGray(p1.rgb()) >= qGray(p2.rgb())); | 
| 4067 |     } | 
| 4068 | } | 
| 4069 |  | 
| 4070 | void tst_QPainter::radialGradientRgb30_data() | 
| 4071 | { | 
| 4072 |     linearGradientRgb30_data(); | 
| 4073 | } | 
| 4074 |  | 
| 4075 | void tst_QPainter::radialGradientRgb30() | 
| 4076 | { | 
| 4077 |     QFETCH(QColor, stop0); | 
| 4078 |     QFETCH(QColor, stop1); | 
| 4079 |  | 
| 4080 |     QRadialGradient gradient(0, 0, 1000); | 
| 4081 |     gradient.setColorAt(pos: 0.0, color: stop0); | 
| 4082 |     gradient.setColorAt(pos: 1.0, color: stop1); | 
| 4083 |  | 
| 4084 |     QImage image(1000, 1, QImage::Format_A2BGR30_Premultiplied); | 
| 4085 |     QPainter painter(&image); | 
| 4086 |     painter.fillRect(image.rect(), gradient); | 
| 4087 |     painter.end(); | 
| 4088 |  | 
| 4089 |     for (int i = 1; i < 1000; ++i) { | 
| 4090 |         QColor p1 = image.pixelColor(x: i - 1, y: 0); | 
| 4091 |         QColor p2 = image.pixelColor(x: i, y: 0); | 
| 4092 |         QVERIFY(p1 != p2); | 
| 4093 |         QVERIFY(qGray(p1.rgb()) >= qGray(p2.rgb())); | 
| 4094 |     } | 
| 4095 | } | 
| 4096 | #endif | 
| 4097 |  | 
| 4098 | void tst_QPainter::drawPolygon() | 
| 4099 | { | 
| 4100 |     QImage img(128, 128, QImage::Format_ARGB32_Premultiplied); | 
| 4101 |  | 
| 4102 |     QPainterPathStroker stroker; | 
| 4103 |     stroker.setWidth(1.5); | 
| 4104 |  | 
| 4105 |     QPainterPath path; | 
| 4106 |     path.moveTo(x: 2, y: 34); | 
| 4107 |     path.lineTo(x: 34, y: 2); | 
| 4108 |  | 
| 4109 |     QPolygonF poly = stroker.createStroke(path).toFillPolygon(matrix: QTransform()); | 
| 4110 |  | 
| 4111 |     img.fill(pixel: 0xffffffff); | 
| 4112 |     QPainter p(&img); | 
| 4113 |     p.setRenderHint(hint: QPainter::Antialiasing); | 
| 4114 |     p.setBrush(Qt::red); | 
| 4115 |     p.setPen(Qt::NoPen); | 
| 4116 |     p.drawPolygon(polygon: poly); | 
| 4117 |     p.translate(dx: 64, dy: 64); | 
| 4118 |     p.drawPolygon(polygon: poly); | 
| 4119 |     p.end(); | 
| 4120 |  | 
| 4121 |     QImage a = img.copy(); | 
| 4122 |  | 
| 4123 |     img.fill(pixel: 0xffffffff); | 
| 4124 |     p.begin(&img); | 
| 4125 |     p.setRenderHint(hint: QPainter::Antialiasing); | 
| 4126 |     p.setBrush(Qt::red); | 
| 4127 |     p.setPen(Qt::NoPen); | 
| 4128 |     p.translate(dx: 64, dy: 64); | 
| 4129 |     p.drawPolygon(polygon: poly); | 
| 4130 |     p.resetTransform(); | 
| 4131 |     p.drawPolygon(polygon: poly); | 
| 4132 |     p.end(); | 
| 4133 |  | 
| 4134 |     QCOMPARE(a, img); | 
| 4135 | } | 
| 4136 |  | 
| 4137 | void tst_QPainter::inactivePainter() | 
| 4138 | { | 
| 4139 |     // This test succeeds if it doesn't segfault. | 
| 4140 |  | 
| 4141 |     QPainter p; | 
| 4142 |     QPainterPath path; | 
| 4143 |     QRegion region(QRect(20, 20, 60, 40)); | 
| 4144 |     QPolygonF polygon(QVector<QPointF>() << QPointF(0, 0) << QPointF(12, 0) << QPointF(8, 6)); | 
| 4145 |     path.addPolygon(polygon); | 
| 4146 |  | 
| 4147 |     p.save(); | 
| 4148 |     p.restore(); | 
| 4149 |  | 
| 4150 |     p.background(); | 
| 4151 |     p.setBackground(QBrush(Qt::blue)); | 
| 4152 |  | 
| 4153 |     p.brush(); | 
| 4154 |     p.setBrush(Qt::red); | 
| 4155 |     p.setBrush(Qt::NoBrush); | 
| 4156 |     p.setBrush(QBrush(Qt::white, Qt::DiagCrossPattern)); | 
| 4157 |  | 
| 4158 |     p.backgroundMode(); | 
| 4159 |     p.setBackgroundMode(Qt::OpaqueMode); | 
| 4160 |  | 
| 4161 |     p.boundingRect(rect: QRectF(0, 0, 100, 20), flags: Qt::AlignCenter, text: QLatin1String("Hello, World!" )); | 
| 4162 |     p.boundingRect(rect: QRect(0, 0, 100, 20), flags: Qt::AlignCenter, text: QLatin1String("Hello, World!" )); | 
| 4163 |  | 
| 4164 |     p.brushOrigin(); | 
| 4165 |     p.setBrushOrigin(QPointF(12, 34)); | 
| 4166 |     p.setBrushOrigin(QPoint(12, 34)); | 
| 4167 |  | 
| 4168 |     p.clipPath(); | 
| 4169 |     p.clipRegion(); | 
| 4170 |     p.hasClipping(); | 
| 4171 |     p.setClipPath(path); | 
| 4172 |     p.setClipRect(QRectF(42, 42, 42, 42)); | 
| 4173 |     p.setClipRect(QRect(42, 42, 42, 42)); | 
| 4174 |     p.setClipRegion(region); | 
| 4175 |     p.setClipping(true); | 
| 4176 |  | 
| 4177 | #if QT_DEPRECATED_SINCE(5, 13) | 
| 4178 | QT_WARNING_PUSH | 
| 4179 | QT_WARNING_DISABLE_DEPRECATED | 
| 4180 |     p.combinedMatrix(); | 
| 4181 | QT_WARNING_POP | 
| 4182 | #endif | 
| 4183 |     p.combinedTransform(); | 
| 4184 |  | 
| 4185 |     p.compositionMode(); | 
| 4186 |     p.setCompositionMode(QPainter::CompositionMode_Plus); | 
| 4187 |  | 
| 4188 |     p.device(); | 
| 4189 | #if QT_DEPRECATED_SINCE(5, 13) | 
| 4190 | QT_WARNING_PUSH | 
| 4191 | QT_WARNING_DISABLE_DEPRECATED | 
| 4192 |     p.deviceMatrix(); | 
| 4193 | QT_WARNING_POP | 
| 4194 | #endif | 
| 4195 |     p.deviceTransform(); | 
| 4196 |  | 
| 4197 |     p.font(); | 
| 4198 |     p.setFont(QFont(QLatin1String("Times" ), 24)); | 
| 4199 |  | 
| 4200 |     p.fontInfo(); | 
| 4201 |     p.fontMetrics(); | 
| 4202 |  | 
| 4203 |     p.layoutDirection(); | 
| 4204 |     p.setLayoutDirection(Qt::RightToLeft); | 
| 4205 |  | 
| 4206 |     p.opacity(); | 
| 4207 |     p.setOpacity(0.75); | 
| 4208 |  | 
| 4209 |     p.pen(); | 
| 4210 |     p.setPen(QPen(Qt::red)); | 
| 4211 |     p.setPen(Qt::green); | 
| 4212 |     p.setPen(Qt::NoPen); | 
| 4213 |  | 
| 4214 |     p.renderHints(); | 
| 4215 |     p.setRenderHint(hint: QPainter::Antialiasing, on: true); | 
| 4216 |     p.setRenderHints(hints: QPainter::Antialiasing | QPainter::SmoothPixmapTransform, on: false); | 
| 4217 |  | 
| 4218 | #if QT_DEPRECATED_SINCE(5, 13) | 
| 4219 | QT_WARNING_PUSH | 
| 4220 | QT_WARNING_DISABLE_DEPRECATED | 
| 4221 |     p.resetMatrix(); | 
| 4222 | QT_WARNING_POP | 
| 4223 | #endif | 
| 4224 |     p.resetTransform(); | 
| 4225 |     p.rotate(a: 1); | 
| 4226 |     p.scale(sx: 2, sy: 2); | 
| 4227 |     p.shear(sh: -1, sv: 1); | 
| 4228 |     p.translate(dx: 3, dy: 14); | 
| 4229 |  | 
| 4230 |     p.viewTransformEnabled(); | 
| 4231 |     p.setViewTransformEnabled(true); | 
| 4232 |  | 
| 4233 |     p.viewport(); | 
| 4234 |     p.setViewport(QRect(10, 10, 620, 460)); | 
| 4235 |  | 
| 4236 |     p.window(); | 
| 4237 |     p.setWindow(QRect(10, 10, 620, 460)); | 
| 4238 |  | 
| 4239 | #if QT_DEPRECATED_SINCE(5, 13) | 
| 4240 | QT_WARNING_PUSH | 
| 4241 | QT_WARNING_DISABLE_DEPRECATED | 
| 4242 |     p.worldMatrix(); | 
| 4243 |     p.setWorldMatrix(matrix: QMatrix().translate(dx: 43, dy: 21), combine: true); | 
| 4244 | QT_WARNING_POP | 
| 4245 | #endif | 
| 4246 |     p.setWorldMatrixEnabled(true); | 
| 4247 |  | 
| 4248 |     p.transform(); | 
| 4249 |     p.setTransform(transform: QTransform().translate(dx: 12, dy: 34), combine: true); | 
| 4250 |  | 
| 4251 |     p.worldTransform(); | 
| 4252 |     p.setWorldTransform(matrix: QTransform().scale(sx: 0.5, sy: 0.5), combine: true); | 
| 4253 | } | 
| 4254 |  | 
| 4255 | bool testCompositionMode(int src, int dst, int expected, QPainter::CompositionMode op, qreal opacity = 1.0) | 
| 4256 | { | 
| 4257 |     // The test image needs to be large enough to test SIMD code | 
| 4258 |     const QSize imageSize(100, 100); | 
| 4259 |  | 
| 4260 |     QImage actual(imageSize, QImage::Format_ARGB32_Premultiplied); | 
| 4261 |     actual.fill(pixel: QColor(dst, dst, dst).rgb()); | 
| 4262 |  | 
| 4263 |     QPainter p(&actual); | 
| 4264 |     p.setCompositionMode(op); | 
| 4265 |     p.setOpacity(opacity); | 
| 4266 |     p.fillRect(QRect(QPoint(), imageSize), color: QColor(src, src, src)); | 
| 4267 |     p.end(); | 
| 4268 |  | 
| 4269 |     if (qRed(rgb: actual.pixel(x: 0, y: 0)) != expected) { | 
| 4270 |         qDebug(msg: "Fail: mode %d, src[%d] dst [%d] actual [%d] expected [%d]" , op, | 
| 4271 |                src, dst, qRed(rgb: actual.pixel(x: 0, y: 0)), expected); | 
| 4272 |         return false; | 
| 4273 |     } else { | 
| 4274 |         QImage refImage(imageSize, QImage::Format_ARGB32_Premultiplied); | 
| 4275 |         refImage.fill(pixel: QColor(expected, expected, expected).rgb()); | 
| 4276 |         return actual == refImage; | 
| 4277 |     } | 
| 4278 | } | 
| 4279 |  | 
| 4280 | void tst_QPainter::extendedBlendModes() | 
| 4281 | { | 
| 4282 |     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Plus)); | 
| 4283 |     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Plus)); | 
| 4284 |     QVERIFY(testCompositionMode(127, 128, 255, QPainter::CompositionMode_Plus)); | 
| 4285 |     QVERIFY(testCompositionMode(127,   0, 127, QPainter::CompositionMode_Plus)); | 
| 4286 |     QVERIFY(testCompositionMode(  0, 127, 127, QPainter::CompositionMode_Plus)); | 
| 4287 |     QVERIFY(testCompositionMode(255,   0, 255, QPainter::CompositionMode_Plus)); | 
| 4288 |     QVERIFY(testCompositionMode(  0, 255, 255, QPainter::CompositionMode_Plus)); | 
| 4289 |     QVERIFY(testCompositionMode(128, 128, 255, QPainter::CompositionMode_Plus)); | 
| 4290 |  | 
| 4291 |     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Plus, 0.3)); | 
| 4292 |     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Plus, 0.3)); | 
| 4293 |     QVERIFY(testCompositionMode(126, 128, 165, QPainter::CompositionMode_Plus, 0.3)); | 
| 4294 |     QVERIFY(testCompositionMode(127,   0,  38, QPainter::CompositionMode_Plus, 0.3)); | 
| 4295 |     QVERIFY(testCompositionMode(  0, 127, 127, QPainter::CompositionMode_Plus, 0.3)); | 
| 4296 |     QVERIFY(testCompositionMode(255,   0,  76, QPainter::CompositionMode_Plus, 0.3)); | 
| 4297 |     QVERIFY(testCompositionMode(  0, 255, 255, QPainter::CompositionMode_Plus, 0.3)); | 
| 4298 |     QVERIFY(testCompositionMode(128, 128, 166, QPainter::CompositionMode_Plus, 0.3)); | 
| 4299 |     QVERIFY(testCompositionMode(186, 200, 255, QPainter::CompositionMode_Plus, 0.3)); | 
| 4300 |  | 
| 4301 |     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Multiply)); | 
| 4302 |     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Multiply)); | 
| 4303 |     QVERIFY(testCompositionMode(127, 255, 127, QPainter::CompositionMode_Multiply)); | 
| 4304 |     QVERIFY(testCompositionMode(255, 127, 127, QPainter::CompositionMode_Multiply)); | 
| 4305 |     QVERIFY(testCompositionMode( 63, 255,  63, QPainter::CompositionMode_Multiply)); | 
| 4306 |     QVERIFY(testCompositionMode(255,  63,  63, QPainter::CompositionMode_Multiply)); | 
| 4307 |     QVERIFY(testCompositionMode(127, 127,  63, QPainter::CompositionMode_Multiply)); | 
| 4308 |  | 
| 4309 |     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Screen)); | 
| 4310 |     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Screen)); | 
| 4311 |     QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Screen)); | 
| 4312 |     QVERIFY(testCompositionMode(255,  63, 255, QPainter::CompositionMode_Screen)); | 
| 4313 |     QVERIFY(testCompositionMode( 63,   0,  63, QPainter::CompositionMode_Screen)); | 
| 4314 |     QVERIFY(testCompositionMode(  0,  63,  63, QPainter::CompositionMode_Screen)); | 
| 4315 |     QVERIFY(testCompositionMode(127, 127, 191, QPainter::CompositionMode_Screen)); | 
| 4316 |  | 
| 4317 |     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Overlay)); | 
| 4318 |     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Overlay)); | 
| 4319 |     QVERIFY(testCompositionMode( 63,  63,  31, QPainter::CompositionMode_Overlay)); | 
| 4320 |     QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Overlay)); | 
| 4321 |  | 
| 4322 |     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Darken)); | 
| 4323 |     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Darken)); | 
| 4324 |     QVERIFY(testCompositionMode( 63,  63,  63, QPainter::CompositionMode_Darken)); | 
| 4325 |     QVERIFY(testCompositionMode( 63, 255,  63, QPainter::CompositionMode_Darken)); | 
| 4326 |     QVERIFY(testCompositionMode(255,  63,  63, QPainter::CompositionMode_Darken)); | 
| 4327 |     QVERIFY(testCompositionMode( 63, 127,  63, QPainter::CompositionMode_Darken)); | 
| 4328 |     QVERIFY(testCompositionMode(127,  63,  63, QPainter::CompositionMode_Darken)); | 
| 4329 |  | 
| 4330 |     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Lighten)); | 
| 4331 |     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Lighten)); | 
| 4332 |     QVERIFY(testCompositionMode( 63,  63,  63, QPainter::CompositionMode_Lighten)); | 
| 4333 |     QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Lighten)); | 
| 4334 |     QVERIFY(testCompositionMode(255,  63, 255, QPainter::CompositionMode_Lighten)); | 
| 4335 |     QVERIFY(testCompositionMode( 63, 127, 127, QPainter::CompositionMode_Lighten)); | 
| 4336 |     QVERIFY(testCompositionMode(127,  63, 127, QPainter::CompositionMode_Lighten)); | 
| 4337 |  | 
| 4338 |     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_ColorDodge)); | 
| 4339 |     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_ColorDodge)); | 
| 4340 |     QVERIFY(testCompositionMode( 63, 127, 169, QPainter::CompositionMode_ColorDodge)); | 
| 4341 |     QVERIFY(testCompositionMode(191, 127, 255, QPainter::CompositionMode_ColorDodge)); | 
| 4342 |     QVERIFY(testCompositionMode(127, 191, 255, QPainter::CompositionMode_ColorDodge)); | 
| 4343 |  | 
| 4344 |     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_ColorBurn)); | 
| 4345 |     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_ColorBurn)); | 
| 4346 |     QVERIFY(testCompositionMode(127, 127,   0, QPainter::CompositionMode_ColorBurn)); | 
| 4347 |     QVERIFY(testCompositionMode(128, 128,   2, QPainter::CompositionMode_ColorBurn)); | 
| 4348 |     QVERIFY(testCompositionMode(191, 127,  84, QPainter::CompositionMode_ColorBurn)); | 
| 4349 |  | 
| 4350 |     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_HardLight)); | 
| 4351 |     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_HardLight)); | 
| 4352 |     QVERIFY(testCompositionMode(127, 127, 127, QPainter::CompositionMode_HardLight)); | 
| 4353 |     QVERIFY(testCompositionMode( 63,  63,  31, QPainter::CompositionMode_HardLight)); | 
| 4354 |     QVERIFY(testCompositionMode(127,  63,  63, QPainter::CompositionMode_HardLight)); | 
| 4355 |  | 
| 4356 |     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_SoftLight)); | 
| 4357 |     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_SoftLight)); | 
| 4358 |     QVERIFY(testCompositionMode(127, 127, 126, QPainter::CompositionMode_SoftLight)); | 
| 4359 |     QVERIFY(testCompositionMode( 63,  63,  39, QPainter::CompositionMode_SoftLight)); | 
| 4360 |     QVERIFY(testCompositionMode(127,  63,  62, QPainter::CompositionMode_SoftLight)); | 
| 4361 |  | 
| 4362 |     QVERIFY(testCompositionMode(255, 255,   0, QPainter::CompositionMode_Difference)); | 
| 4363 |     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Difference)); | 
| 4364 |     QVERIFY(testCompositionMode(255,   0, 255, QPainter::CompositionMode_Difference)); | 
| 4365 |     QVERIFY(testCompositionMode(127, 127,   0, QPainter::CompositionMode_Difference)); | 
| 4366 |     QVERIFY(testCompositionMode(127, 128,   1, QPainter::CompositionMode_Difference)); | 
| 4367 |     QVERIFY(testCompositionMode(127,  63,  64, QPainter::CompositionMode_Difference)); | 
| 4368 |     QVERIFY(testCompositionMode(  0, 127, 127, QPainter::CompositionMode_Difference)); | 
| 4369 |  | 
| 4370 |     QVERIFY(testCompositionMode(255, 255,   0, QPainter::CompositionMode_Exclusion)); | 
| 4371 |     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Exclusion)); | 
| 4372 |     QVERIFY(testCompositionMode(255,   0, 255, QPainter::CompositionMode_Exclusion)); | 
| 4373 |     QVERIFY(testCompositionMode(127, 127, 127, QPainter::CompositionMode_Exclusion)); | 
| 4374 |     QVERIFY(testCompositionMode( 63, 127, 127, QPainter::CompositionMode_Exclusion)); | 
| 4375 |     QVERIFY(testCompositionMode( 63,  63,  95, QPainter::CompositionMode_Exclusion)); | 
| 4376 |     QVERIFY(testCompositionMode(191, 191,  96, QPainter::CompositionMode_Exclusion)); | 
| 4377 | } | 
| 4378 |  | 
| 4379 | void tst_QPainter::zeroOpacity() | 
| 4380 | { | 
| 4381 |     QImage source(1, 1, QImage::Format_ARGB32_Premultiplied); | 
| 4382 |     source.fill(pixel: 0xffffffff); | 
| 4383 |  | 
| 4384 |     QImage target(1, 1, QImage::Format_RGB32); | 
| 4385 |     target.fill(pixel: 0xff000000); | 
| 4386 |  | 
| 4387 |     QPainter p(&target); | 
| 4388 |     p.setOpacity(0.0); | 
| 4389 |     p.drawImage(x: 0, y: 0, image: source); | 
| 4390 |     p.end(); | 
| 4391 |  | 
| 4392 |     QCOMPARE(target.pixel(0, 0), 0xff000000); | 
| 4393 | } | 
| 4394 |  | 
| 4395 | void tst_QPainter::clippingBug() | 
| 4396 | { | 
| 4397 |     QImage img(32, 32, QImage::Format_ARGB32_Premultiplied); | 
| 4398 |     img.fill(pixel: 0); | 
| 4399 |  | 
| 4400 |     QImage expected = img; | 
| 4401 |     QPainter p(&expected); | 
| 4402 |     p.fillRect(x: 1, y: 1, w: 30, h: 30, c: Qt::red); | 
| 4403 |     p.end(); | 
| 4404 |  | 
| 4405 |     QPainterPath path; | 
| 4406 |     path.addRect(x: 1, y: 1, w: 30, h: 30); | 
| 4407 |     path.addRect(x: 1, y: 1, w: 30, h: 30); | 
| 4408 |     path.addRect(x: 1, y: 1, w: 30, h: 30); | 
| 4409 |  | 
| 4410 |     p.begin(&img); | 
| 4411 |     p.setClipPath(path); | 
| 4412 |     p.fillRect(x: 0, y: 0, w: 32, h: 32, c: Qt::red); | 
| 4413 |     p.end(); | 
| 4414 |  | 
| 4415 |     QCOMPARE(img, expected); | 
| 4416 | } | 
| 4417 |  | 
| 4418 | void tst_QPainter::emptyClip() | 
| 4419 | { | 
| 4420 |     QImage img(64, 64, QImage::Format_ARGB32_Premultiplied); | 
| 4421 |     QPainter p(&img); | 
| 4422 |     p.setRenderHints(hints: QPainter::Antialiasing); | 
| 4423 |     p.setClipRect(x: 0, y: 32, w: 64, h: 0); | 
| 4424 |     p.fillRect(x: 0, y: 0, w: 64, h: 64, c: Qt::white); | 
| 4425 |  | 
| 4426 |     QPainterPath path; | 
| 4427 |     path.lineTo(x: 64, y: 0); | 
| 4428 |     path.lineTo(x: 64, y: 64); | 
| 4429 |     path.lineTo(x: 40, y: 64); | 
| 4430 |     path.lineTo(x: 40, y: 80); | 
| 4431 |     path.lineTo(x: 0, y: 80); | 
| 4432 |  | 
| 4433 |     p.fillPath(path, brush: Qt::green); | 
| 4434 | } | 
| 4435 |  | 
| 4436 | void tst_QPainter::drawImage_1x1() | 
| 4437 | { | 
| 4438 |     QImage source(1, 1, QImage::Format_ARGB32_Premultiplied); | 
| 4439 |     source.fill(pixel: 0xffffffff); | 
| 4440 |  | 
| 4441 |     QImage img(32, 32, QImage::Format_ARGB32_Premultiplied); | 
| 4442 |     img.fill(pixel: 0xff000000); | 
| 4443 |     QPainter p(&img); | 
| 4444 |     p.drawImage(r: QRectF(0.9, 0.9, 32, 32), image: source); | 
| 4445 |     p.end(); | 
| 4446 |  | 
| 4447 |     QImage expected = img; | 
| 4448 |     expected.fill(pixel: 0xff000000); | 
| 4449 |     p.begin(&expected); | 
| 4450 |     p.fillRect(x: 1, y: 1, w: 31, h: 31, c: Qt::white); | 
| 4451 |     p.end(); | 
| 4452 |  | 
| 4453 |     QCOMPARE(img, expected); | 
| 4454 | } | 
| 4455 |  | 
| 4456 | void tst_QPainter::taskQT4444_dontOverflowDashOffset() | 
| 4457 | { | 
| 4458 |     QPainter p; | 
| 4459 |  | 
| 4460 |     QPen pen; | 
| 4461 |     pen.setWidth(2); | 
| 4462 |     pen.setStyle(Qt::DashDotLine); | 
| 4463 |  | 
| 4464 |     QPointF point[4]; | 
| 4465 |     point[0] = QPointF(182.50868749707968,347.78457234212630); | 
| 4466 |     point[1] = QPointF(182.50868749707968,107.22501998401277); | 
| 4467 |     point[2] = QPointF(182.50868749707968,107.22501998401277); | 
| 4468 |     point[3] = QPointF(520.46600762283651,107.22501998401277); | 
| 4469 |  | 
| 4470 |     QImage crashImage(QSize(1000, 120), QImage::Format_ARGB32_Premultiplied); | 
| 4471 |     p.begin(&crashImage); | 
| 4472 |     p.setPen(pen); | 
| 4473 |     p.drawLines(pointPairs: point, lineCount: 2); | 
| 4474 |     p.end(); | 
| 4475 |  | 
| 4476 |     QVERIFY(true); // Don't crash | 
| 4477 | } | 
| 4478 |  | 
| 4479 | void tst_QPainter::painterBegin() | 
| 4480 | { | 
| 4481 |     QImage nullImage; | 
| 4482 |     QImage indexed8Image(16, 16, QImage::Format_Indexed8); | 
| 4483 |     QImage rgb32Image(16, 16, QImage::Format_RGB32); | 
| 4484 |     QImage argb32Image(16, 16, QImage::Format_ARGB32_Premultiplied); | 
| 4485 |  | 
| 4486 |     QPainter p; | 
| 4487 |  | 
| 4488 |     // Painting on null image should fail. | 
| 4489 |     QVERIFY(!p.begin(&nullImage)); | 
| 4490 |  | 
| 4491 |     // Check that the painter is not messed up by using it on another image. | 
| 4492 |     QVERIFY(p.begin(&rgb32Image)); | 
| 4493 |     QVERIFY(p.end()); | 
| 4494 |  | 
| 4495 |     // If painting on indexed8 image fails, the painter state should still be OK. | 
| 4496 |     if (p.begin(&indexed8Image)) | 
| 4497 |         QVERIFY(p.end()); | 
| 4498 |     QVERIFY(p.begin(&rgb32Image)); | 
| 4499 |     QVERIFY(p.end()); | 
| 4500 |  | 
| 4501 |     // Try opening a painter on the two different images. | 
| 4502 |     QVERIFY(p.begin(&rgb32Image)); | 
| 4503 |     QVERIFY(!p.begin(&argb32Image)); | 
| 4504 |     QVERIFY(p.end()); | 
| 4505 |  | 
| 4506 |     // Try opening two painters on the same image. | 
| 4507 |     QVERIFY(p.begin(&rgb32Image)); | 
| 4508 |     QPainter q; | 
| 4509 |     QVERIFY(!q.begin(&rgb32Image)); | 
| 4510 |     QVERIFY(!q.end()); | 
| 4511 |     QVERIFY(p.end()); | 
| 4512 |  | 
| 4513 |     // Try ending an inactive painter. | 
| 4514 |     QVERIFY(!p.end()); | 
| 4515 | } | 
| 4516 |  | 
| 4517 | void tst_QPainter::setPenColor(QPainter& p) | 
| 4518 | { | 
| 4519 |     p.setPen(Qt::NoPen); | 
| 4520 |  | 
| 4521 |     // Setting color, then style | 
| 4522 |     // Should work even though the pen is "NoPen with color", temporarily. | 
| 4523 |     QPen newPen(p.pen()); | 
| 4524 |     newPen.setColor(Qt::red); | 
| 4525 |     QCOMPARE(p.pen().style(), newPen.style()); | 
| 4526 |     QCOMPARE(p.pen().style(), Qt::NoPen); | 
| 4527 |     p.setPen(newPen); | 
| 4528 |  | 
| 4529 |     QCOMPARE(p.pen().color().name(), QString("#ff0000" )); | 
| 4530 |  | 
| 4531 |     QPen newPen2(p.pen()); | 
| 4532 |     newPen2.setStyle(Qt::SolidLine); | 
| 4533 |     p.setPen(newPen2); | 
| 4534 |  | 
| 4535 |     QCOMPARE(p.pen().color().name(), QString("#ff0000" )); | 
| 4536 | } | 
| 4537 |  | 
| 4538 | void tst_QPainter::setPenColorOnImage() | 
| 4539 | { | 
| 4540 |     QImage img(QSize(10, 10), QImage::Format_ARGB32_Premultiplied); | 
| 4541 |     QPainter p(&img); | 
| 4542 |     setPenColor(p); | 
| 4543 | } | 
| 4544 |  | 
| 4545 | void tst_QPainter::setPenColorOnPixmap() | 
| 4546 | { | 
| 4547 |     QPixmap pix(10, 10); | 
| 4548 |     QPainter p(&pix); | 
| 4549 |     setPenColor(p); | 
| 4550 | } | 
| 4551 |  | 
| 4552 | #ifndef QT_NO_WIDGETS | 
| 4553 | class TestProxy : public QGraphicsProxyWidget | 
| 4554 | { | 
| 4555 | public: | 
| 4556 |     TestProxy() : QGraphicsProxyWidget() {} | 
| 4557 |     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) | 
| 4558 |     { | 
| 4559 |         QGraphicsProxyWidget::paint(painter, option, widget); | 
| 4560 |         deviceTransform = painter->deviceTransform(); | 
| 4561 |     } | 
| 4562 |     QTransform deviceTransform; | 
| 4563 | }; | 
| 4564 |  | 
| 4565 | class TestWidget : public QWidget | 
| 4566 | { | 
| 4567 | Q_OBJECT | 
| 4568 | public: | 
| 4569 |     TestWidget() : QWidget(), painted(false) {} | 
| 4570 |     void paintEvent(QPaintEvent *) | 
| 4571 |     { | 
| 4572 |         QPainter p(this); | 
| 4573 |         deviceTransform = p.deviceTransform(); | 
| 4574 |         worldTransform = p.worldTransform(); | 
| 4575 |         painted = true; | 
| 4576 |     } | 
| 4577 |     QTransform deviceTransform; | 
| 4578 |     QTransform worldTransform; | 
| 4579 |     bool painted; | 
| 4580 | }; | 
| 4581 |  | 
| 4582 | void tst_QPainter::QTBUG5939_attachPainterPrivate() | 
| 4583 | { | 
| 4584 |     QWidget *w = new QWidget(); | 
| 4585 |     QGraphicsScene *scene = new QGraphicsScene(); | 
| 4586 |     QGraphicsView *view = new QGraphicsView(scene, w); | 
| 4587 |     view->move(ax: 50 ,ay: 50); | 
| 4588 |     TestProxy *proxy = new TestProxy(); | 
| 4589 |     TestWidget *widget = new TestWidget(); | 
| 4590 |     proxy->setWidget(widget); | 
| 4591 |     scene->addItem(item: proxy); | 
| 4592 |     proxy->setTransform(matrix: QTransform().rotate(a: 45)); | 
| 4593 |     w->resize(scene->sceneRect().size().toSize()); | 
| 4594 |  | 
| 4595 |     w->show(); | 
| 4596 |     QTRY_VERIFY(widget->painted); | 
| 4597 |  | 
| 4598 |     QVERIFY(widget->worldTransform.isIdentity()); | 
| 4599 |     QCOMPARE(widget->deviceTransform, proxy->deviceTransform); | 
| 4600 | } | 
| 4601 | #endif | 
| 4602 |  | 
| 4603 | void tst_QPainter::clipBoundingRect() | 
| 4604 | { | 
| 4605 |     QPixmap pix(500, 500); | 
| 4606 |  | 
| 4607 |     QPainter p(&pix); | 
| 4608 |  | 
| 4609 |     // Test a basic rectangle | 
| 4610 |     p.setClipRect(x: 100, y: 100, w: 200, h: 100); | 
| 4611 |     QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); | 
| 4612 |     QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200))); | 
| 4613 |     p.setClipRect(x: 120, y: 120, w: 20, h: 20, op: Qt::IntersectClip); | 
| 4614 |     QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20))); | 
| 4615 |     QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); | 
| 4616 |  | 
| 4617 |     // Test a basic float rectangle | 
| 4618 |     p.setClipRect(QRectF(100, 100, 200, 100)); | 
| 4619 |     QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); | 
| 4620 |     QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200))); | 
| 4621 |     p.setClipRect(QRectF(120, 120, 20, 20), op: Qt::IntersectClip); | 
| 4622 |     QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20))); | 
| 4623 |     QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); | 
| 4624 |  | 
| 4625 |     // Test a basic path + region | 
| 4626 |     QPainterPath path; | 
| 4627 |     path.addRect(x: 100, y: 100, w: 200, h: 100); | 
| 4628 |     p.setClipPath(path); | 
| 4629 |     QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); | 
| 4630 |     QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200))); | 
| 4631 |     p.setClipRegion(QRegion(120, 120, 20, 20), op: Qt::IntersectClip); | 
| 4632 |     QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20))); | 
| 4633 |     QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); | 
| 4634 |  | 
| 4635 |     p.setClipRect(x: 0, y: 0, w: 500, h: 500); | 
| 4636 |     p.translate(dx: 250, dy: 250); | 
| 4637 |     for (int i=0; i<360; ++i) { | 
| 4638 |         p.rotate(a: 1); | 
| 4639 |         p.setClipRect(x: -100, y: -100, w: 200, h: 200, op: Qt::IntersectClip); | 
| 4640 |     } | 
| 4641 |     QVERIFY(p.clipBoundingRect().contains(QRectF(-100, -100, 200, 200))); | 
| 4642 |     QVERIFY(!p.clipBoundingRect().contains(QRectF(-250, -250, 500, 500))); | 
| 4643 |  | 
| 4644 | } | 
| 4645 |  | 
| 4646 | void tst_QPainter::transformedClip() | 
| 4647 | { | 
| 4648 |     QImage img(8, 4, QImage::Format_ARGB32_Premultiplied); | 
| 4649 |     QImage img2(img.size(), img.format()); | 
| 4650 |     QRect clip(0, 0, 2, 1); | 
| 4651 |     QTransform xf; | 
| 4652 |     xf.translate(dx: 0.2, dy: 0); | 
| 4653 |     xf.scale(sx: 2.2, sy: 1); | 
| 4654 |     // setClipRect(QRectF) | 
| 4655 |     { | 
| 4656 |         img.fill(color: Qt::green); | 
| 4657 |         QPainter p(&img); | 
| 4658 |         p.setTransform(transform: xf); | 
| 4659 |         p.setClipRect(QRectF(clip)); | 
| 4660 |         p.fillRect(r: img.rect(), c: Qt::white); | 
| 4661 |     } | 
| 4662 |     // setClipRect(QRect) | 
| 4663 |     { | 
| 4664 |         img2.fill(color: Qt::green); | 
| 4665 |         QPainter p(&img2); | 
| 4666 |         p.setTransform(transform: xf); | 
| 4667 |         p.setClipRect(clip); | 
| 4668 |         p.fillRect(r: img2.rect(), c: Qt::white); | 
| 4669 |         QCOMPARE(img, img2); | 
| 4670 |     } | 
| 4671 |     // setClipRegion | 
| 4672 |     { | 
| 4673 |         img2.fill(color: Qt::green); | 
| 4674 |         QPainter p(&img2); | 
| 4675 |         p.setTransform(transform: xf); | 
| 4676 |         p.setClipRegion(QRegion(clip) + QRect(0, 3, 1, 1));  // dummy extra rect to avoid single-rect codepath | 
| 4677 |         p.fillRect(r: img2.rect(), c: Qt::white); | 
| 4678 |         QCOMPARE(img.copy(0, 0, 8, 2), img2.copy(0, 0, 8, 2)); | 
| 4679 |     } | 
| 4680 |     // setClipPath | 
| 4681 |     { | 
| 4682 |         img2.fill(color: Qt::green); | 
| 4683 |         QPainter p(&img2); | 
| 4684 |         p.setTransform(transform: xf); | 
| 4685 |         QPainterPath path; | 
| 4686 |         path.addRect(rect: clip); | 
| 4687 |         p.setClipPath(path); | 
| 4688 |         p.fillRect(r: img2.rect(), c: Qt::white); | 
| 4689 |         QCOMPARE(img, img2); | 
| 4690 |     } | 
| 4691 | } | 
| 4692 |  | 
| 4693 | #if defined(Q_OS_MAC) | 
| 4694 | // Only Mac supports sub pixel positions in raster engine currently | 
| 4695 | void tst_QPainter::drawText_subPixelPositionsInRaster_qtbug5053() | 
| 4696 | { | 
| 4697 |     QFontMetricsF fm(qApp->font()); | 
| 4698 |  | 
| 4699 |     QImage baseLine(fm.horizontalAdvance(QChar::fromLatin1('e')), fm.height(), QImage::Format_RGB32); | 
| 4700 |     baseLine.fill(Qt::white); | 
| 4701 |     { | 
| 4702 |         QPainter p(&baseLine); | 
| 4703 |         p.setRenderHint(QPainter::Qt4CompatiblePainting); | 
| 4704 |         p.drawText(0, fm.ascent(), QString::fromLatin1("e" )); | 
| 4705 |     } | 
| 4706 |  | 
| 4707 |     bool foundDifferentRasterization = false; | 
| 4708 |     for (int i=1; i<12; ++i) { | 
| 4709 |         QImage comparison(baseLine.size(), QImage::Format_RGB32); | 
| 4710 |         comparison.fill(Qt::white); | 
| 4711 |  | 
| 4712 |         { | 
| 4713 |             QPainter p(&comparison); | 
| 4714 |             p.setRenderHint(QPainter::Qt4CompatiblePainting); | 
| 4715 |             p.drawText(QPointF(i / 12.0, fm.ascent()), QString::fromLatin1("e" )); | 
| 4716 |         } | 
| 4717 |  | 
| 4718 |         if (comparison != baseLine) { | 
| 4719 |             foundDifferentRasterization = true; | 
| 4720 |             break; | 
| 4721 |         } | 
| 4722 |     } | 
| 4723 |  | 
| 4724 |     QVERIFY(foundDifferentRasterization); | 
| 4725 | } | 
| 4726 | #endif | 
| 4727 |  | 
| 4728 | void tst_QPainter::drawPointScaled() | 
| 4729 | { | 
| 4730 |     QImage image(32, 32, QImage::Format_RGB32); | 
| 4731 |     image.fill(pixel: 0xffffffff); | 
| 4732 |  | 
| 4733 |     QPainter p(&image); | 
| 4734 |  | 
| 4735 |     p.scale(sx: 0.1, sy: 0.1); | 
| 4736 |  | 
| 4737 |     QPen pen; | 
| 4738 |     pen.setWidth(1000); | 
| 4739 |     pen.setColor(Qt::red); | 
| 4740 |  | 
| 4741 |     p.setPen(pen); | 
| 4742 |     p.drawPoint(x: 0, y: 0); | 
| 4743 |     p.end(); | 
| 4744 |  | 
| 4745 |     QCOMPARE(image.pixel(16, 16), 0xffff0000); | 
| 4746 | } | 
| 4747 |  | 
| 4748 | class GradientProducer : public QThread | 
| 4749 | { | 
| 4750 | protected: | 
| 4751 |     void run(); | 
| 4752 | }; | 
| 4753 |  | 
| 4754 | void GradientProducer::run() | 
| 4755 | { | 
| 4756 |     QImage image(1, 1, QImage::Format_RGB32); | 
| 4757 |     QPainter p(&image); | 
| 4758 |  | 
| 4759 |     for (int i = 0; i < 1000; ++i) { | 
| 4760 |         QLinearGradient g; | 
| 4761 |         g.setColorAt(pos: 0, color: QColor(i % 256, 0, 0)); | 
| 4762 |         g.setColorAt(pos: 1, color: Qt::white); | 
| 4763 |  | 
| 4764 |         p.fillRect(image.rect(), g); | 
| 4765 |     } | 
| 4766 | } | 
| 4767 |  | 
| 4768 | void tst_QPainter::QTBUG14614_gradientCacheRaceCondition() | 
| 4769 | { | 
| 4770 |     const int threadCount = 16; | 
| 4771 |     GradientProducer producers[threadCount]; | 
| 4772 |     for (int i = 0; i < threadCount; ++i) | 
| 4773 |         producers[i].start(); | 
| 4774 |     for (int i = 0; i < threadCount; ++i) | 
| 4775 |         producers[i].wait(); | 
| 4776 | } | 
| 4777 |  | 
| 4778 | void tst_QPainter::drawTextOpacity() | 
| 4779 | { | 
| 4780 |     QImage image(32, 32, QImage::Format_RGB32); | 
| 4781 |     image.fill(pixel: 0xffffffff); | 
| 4782 |  | 
| 4783 |     QPainter p(&image); | 
| 4784 |     p.setPen(QColor("#6F6F6F" )); | 
| 4785 |     p.setOpacity(0.5); | 
| 4786 |     p.drawText(x: 5, y: 30, s: QLatin1String("Qt" )); | 
| 4787 |     p.end(); | 
| 4788 |  | 
| 4789 |     QImage copy = image; | 
| 4790 |     image.fill(pixel: 0xffffffff); | 
| 4791 |  | 
| 4792 |     p.begin(&image); | 
| 4793 |     p.setPen(QColor("#6F6F6F" )); | 
| 4794 |     p.drawLine(x1: -10, y1: -10, x2: -1, y2: -1); | 
| 4795 |     p.setOpacity(0.5); | 
| 4796 |     p.drawText(x: 5, y: 30, s: QLatin1String("Qt" )); | 
| 4797 |     p.end(); | 
| 4798 |  | 
| 4799 |     QCOMPARE(image, copy); | 
| 4800 | } | 
| 4801 |  | 
| 4802 | void tst_QPainter::QTBUG17053_zeroDashPattern() | 
| 4803 | { | 
| 4804 |     QImage image(32, 32, QImage::Format_RGB32); | 
| 4805 |     image.fill(pixel: 0xffffffff); | 
| 4806 |  | 
| 4807 |     QImage original = image; | 
| 4808 |  | 
| 4809 |     QVector<qreal> pattern; | 
| 4810 |     pattern << qreal(0) << qreal(0); | 
| 4811 |  | 
| 4812 |     QPainter p(&image); | 
| 4813 |     QPen pen(Qt::black, 2.0); | 
| 4814 |     pen.setDashPattern(pattern); | 
| 4815 |  | 
| 4816 |     p.setPen(pen); | 
| 4817 |     p.drawLine(x1: 0, y1: 0, x2: image.width(), y2: image.height()); | 
| 4818 |  | 
| 4819 |     QCOMPARE(image, original); | 
| 4820 | } | 
| 4821 |  | 
| 4822 | void tst_QPainter::QTBUG38781_NoBrushAndQBitmap() | 
| 4823 | { | 
| 4824 |     QBitmap bitmap(10, 10); | 
| 4825 |     bitmap.fill(fillColor: Qt::color0); | 
| 4826 |     QPainter p(&bitmap); | 
| 4827 |     p.setPen(Qt::color1); | 
| 4828 |     p.drawLine(x1: 0, y1: 1, x2: 9, y2: 1); // at horizontal line at y=1 | 
| 4829 |     p.setBrush(Qt::NoBrush); | 
| 4830 |     p.drawRect(x: 0, y: 0, w: 9, h: 9); // a rect all around | 
| 4831 |  | 
| 4832 |     QRgb white = qRgb(r: 0xff, g: 0xff, b: 0xff); | 
| 4833 |     QRgb black = qRgb(r: 0, g: 0, b: 0); | 
| 4834 |     QImage image = bitmap.toImage(); | 
| 4835 |     QCOMPARE(image.pixel(0, 0), black); | 
| 4836 |     QCOMPARE(image.pixel(5, 5), white); | 
| 4837 |  | 
| 4838 |     // Check that the rect didn't overwrite the line | 
| 4839 |     QCOMPARE(image.pixel(5, 1), black); | 
| 4840 | } | 
| 4841 |  | 
| 4842 | class TextDrawerThread : public QThread | 
| 4843 | { | 
| 4844 | public: | 
| 4845 |     void run(); | 
| 4846 |     QImage rendering; | 
| 4847 | }; | 
| 4848 |  | 
| 4849 | void TextDrawerThread::run() | 
| 4850 | { | 
| 4851 |     rendering = QImage(100, 100, QImage::Format_ARGB32_Premultiplied); | 
| 4852 |     rendering.fill(pixel: 0); | 
| 4853 |     QPainter p(&rendering); | 
| 4854 |     p.fillRect(x: 10, y: 10, w: 100, h: 100, c: Qt::blue); | 
| 4855 |     p.setPen(Qt::green); | 
| 4856 |     p.drawText(x: 20, y: 20, s: "some text" ); | 
| 4857 |     p.end(); | 
| 4858 | } | 
| 4859 |  | 
| 4860 | void tst_QPainter::drawTextOutsideGuiThread() | 
| 4861 | { | 
| 4862 |     QImage referenceRendering(100, 100, QImage::Format_ARGB32_Premultiplied); | 
| 4863 |     referenceRendering.fill(pixel: 0); | 
| 4864 |     QPainter p(&referenceRendering); | 
| 4865 |     p.fillRect(x: 10, y: 10, w: 100, h: 100, c: Qt::blue); | 
| 4866 |     p.setPen(Qt::green); | 
| 4867 |     p.drawText(x: 20, y: 20, s: "some text" ); | 
| 4868 |     p.end(); | 
| 4869 |  | 
| 4870 |     TextDrawerThread t; | 
| 4871 |     t.start(); | 
| 4872 |     t.wait(); | 
| 4873 |  | 
| 4874 |     QCOMPARE(referenceRendering, t.rendering); | 
| 4875 | } | 
| 4876 |  | 
| 4877 | void tst_QPainter::drawTextWithComplexBrush() | 
| 4878 | { | 
| 4879 |     QImage texture(10, 10, QImage::Format_ARGB32_Premultiplied); | 
| 4880 |     texture.fill(color: Qt::red); | 
| 4881 |  | 
| 4882 |     QImage image(100, 100, QImage::Format_ARGB32_Premultiplied); | 
| 4883 |     image.fill(color: Qt::white); | 
| 4884 |     QPainter p(&image); | 
| 4885 |     QFont f = p.font(); | 
| 4886 |     f.setPixelSize(70); | 
| 4887 |     p.setFont(f); | 
| 4888 |  | 
| 4889 |     QBrush brush(Qt::white); | 
| 4890 |     brush.setTextureImage(texture); | 
| 4891 |     p.setPen(QPen(brush, 2)); | 
| 4892 |  | 
| 4893 |     p.drawText(x: 10, y: 10, s: "Hello World" ); | 
| 4894 |  | 
| 4895 |     int paintedPixels = getPaintedPixels(image, background: Qt::white); | 
| 4896 |     QVERIFY(paintedPixels > 0); | 
| 4897 | } | 
| 4898 |  | 
| 4899 | void tst_QPainter::QTBUG26013_squareCapStroke() | 
| 4900 | { | 
| 4901 |     QImage image(4, 4, QImage::Format_RGB32); | 
| 4902 |  | 
| 4903 |     QPainter p(&image); | 
| 4904 |     p.setPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap)); | 
| 4905 |  | 
| 4906 |     for (int i = 0; i < 3; ++i) { | 
| 4907 |         qreal d = i / 3.0; | 
| 4908 |  | 
| 4909 |         image.fill(pixel: 0xffffffff); | 
| 4910 |  | 
| 4911 |         p.drawLine(l: QLineF(0, d, 0, d + 2)); | 
| 4912 |         p.drawLine(l: QLineF(1, d, 3, d)); | 
| 4913 |  | 
| 4914 |         // ensure that a horizontal line and a vertical line with square cap round up (downwards) at the same time | 
| 4915 |         QCOMPARE(image.pixel(0, 0), image.pixel(1, 0)); | 
| 4916 |  | 
| 4917 |         image.fill(pixel: 0xffffffff); | 
| 4918 |  | 
| 4919 |         p.drawLine(l: QLineF(d, 0, d + 2, 0)); | 
| 4920 |         p.drawLine(l: QLineF(d, 1, d, 3)); | 
| 4921 |  | 
| 4922 |         // ensure that a vertical line and a horizontal line with square cap round up (to the right) at the same time | 
| 4923 |         QCOMPARE(image.pixel(0, 0), image.pixel(0, 1)); | 
| 4924 |     } | 
| 4925 | } | 
| 4926 |  | 
| 4927 | void tst_QPainter::QTBUG25153_drawLine() | 
| 4928 | { | 
| 4929 |     QImage image(2, 2, QImage::Format_RGB32); | 
| 4930 |  | 
| 4931 |     QVector<Qt::PenCapStyle> styles; | 
| 4932 |     styles << Qt::FlatCap << Qt::SquareCap << Qt::RoundCap; | 
| 4933 |  | 
| 4934 |     foreach (Qt::PenCapStyle style, styles) { | 
| 4935 |         image.fill(pixel: 0xffffffff); | 
| 4936 |         QPainter p(&image); | 
| 4937 |         p.setPen(QPen(Qt::black, 0, Qt::SolidLine, style)); | 
| 4938 |         p.drawLine(l: QLineF(0, 0, 0, 0)); | 
| 4939 |         p.end(); | 
| 4940 |  | 
| 4941 |         QCOMPARE(image.pixel(0, 0), 0xff000000); | 
| 4942 |         QCOMPARE(image.pixel(0, 1), 0xffffffff); | 
| 4943 |         QCOMPARE(image.pixel(1, 0), 0xffffffff); | 
| 4944 |     } | 
| 4945 | } | 
| 4946 |  | 
| 4947 | void tst_QPainter::blendARGBonRGB_data() | 
| 4948 | { | 
| 4949 |     QTest::addColumn<QImage::Format>(name: "dst_format" ); | 
| 4950 |     QTest::addColumn<QImage::Format>(name: "src_format" ); | 
| 4951 |     QTest::addColumn<QPainter::CompositionMode>(name: "compositionMode" ); | 
| 4952 |     QTest::addColumn<QRgb>(name: "color" ); | 
| 4953 |     QTest::addColumn<int>(name: "expected_red" ); | 
| 4954 |  | 
| 4955 |     QTest::newRow(dataTag: "ARGB over ARGB32" ) << QImage::Format_ARGB32 << QImage::Format_ARGB32 | 
| 4956 |                                       << QPainter::CompositionMode_SourceOver << qRgba(r: 255, g: 0, b: 0, a: 127) << 127 ; | 
| 4957 |     QTest::newRow(dataTag: "ARGB_PM over ARGB32" ) << QImage::Format_ARGB32 << QImage::Format_ARGB32_Premultiplied | 
| 4958 |                                          << QPainter::CompositionMode_SourceOver<< qRgba(r: 127, g: 0, b: 0, a: 127) << 127; | 
| 4959 |     QTest::newRow(dataTag: "ARGB source ARGB32" ) << QImage::Format_ARGB32 << QImage::Format_ARGB32 | 
| 4960 |                                         << QPainter::CompositionMode_Source << qRgba(r: 255, g: 0, b: 0, a: 127) << 255; | 
| 4961 |     QTest::newRow(dataTag: "ARGB_PM source ARGB32" ) << QImage::Format_ARGB32 << QImage::Format_ARGB32_Premultiplied | 
| 4962 |                                            << QPainter::CompositionMode_Source << qRgba(r: 127, g: 0, b: 0, a: 127) << 255; | 
| 4963 |     QTest::newRow(dataTag: "ARGB source-in ARGB32" ) << QImage::Format_ARGB32 << QImage::Format_ARGB32 | 
| 4964 |                                            << QPainter::CompositionMode_SourceIn << qRgba(r: 255, g: 0, b: 0, a: 127) << 255 ; | 
| 4965 |     QTest::newRow(dataTag: "ARGB_PM source-in ARGB32" ) << QImage::Format_ARGB32 << QImage::Format_ARGB32_Premultiplied | 
| 4966 |                                               << QPainter::CompositionMode_SourceIn << qRgba(r: 127, g: 0, b: 0, a: 127) << 255; | 
| 4967 |     QTest::newRow(dataTag: "ARGB over RGBA8888" ) << QImage::Format_RGBA8888 << QImage::Format_ARGB32 | 
| 4968 |                                         << QPainter::CompositionMode_SourceOver << qRgba(r: 255, g: 0, b: 0, a: 127) << 127; | 
| 4969 |     QTest::newRow(dataTag: "ARGB_PM over RGBA8888" ) << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied | 
| 4970 |                                            << QPainter::CompositionMode_SourceOver << qRgba(r: 127, g: 0, b: 0, a: 127) << 127; | 
| 4971 |     QTest::newRow(dataTag: "ARGB source RGBA8888" ) << QImage::Format_RGBA8888 << QImage::Format_ARGB32 | 
| 4972 |                                           << QPainter::CompositionMode_Source << qRgba(r: 255, g: 0, b: 0, a: 127) << 255; | 
| 4973 |     QTest::newRow(dataTag: "ARGB_PM source RGBA8888" ) << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied | 
| 4974 |                                              << QPainter::CompositionMode_Source << qRgba(r: 127, g: 0, b: 0, a: 127) << 255; | 
| 4975 |     QTest::newRow(dataTag: "ARGB source-in RGBA8888" ) << QImage::Format_RGBA8888 << QImage::Format_ARGB32 | 
| 4976 |                                              << QPainter::CompositionMode_SourceIn << qRgba(r: 255, g: 0, b: 0, a: 127) << 255; | 
| 4977 |     QTest::newRow(dataTag: "ARGB_PM source-in RGBA8888" ) << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied | 
| 4978 |                                                 << QPainter::CompositionMode_SourceIn << qRgba(r: 127, g: 0, b: 0, a: 127) << 255; | 
| 4979 |     // Only ARGB32 and RGBA8888 does inverse premultiply, on the rest over and source gives similar results: | 
| 4980 |     QTest::newRow(dataTag: "ARGB over RGB32" ) << QImage::Format_RGB32 << QImage::Format_ARGB32 | 
| 4981 |                                      << QPainter::CompositionMode_SourceOver << qRgba(r: 255, g: 0, b: 0, a: 127) << 127; | 
| 4982 |     QTest::newRow(dataTag: "ARGB_PM over RGB32" ) << QImage::Format_RGB32 << QImage::Format_ARGB32_Premultiplied | 
| 4983 |                                         << QPainter::CompositionMode_SourceOver << qRgba(r: 127, g: 0, b: 0, a: 127) << 127; | 
| 4984 |     QTest::newRow(dataTag: "ARGB source RGB32" ) << QImage::Format_RGB32 << QImage::Format_ARGB32 | 
| 4985 |                                        << QPainter::CompositionMode_Source << qRgba(r: 255, g: 0, b: 0, a: 127) << 127; | 
| 4986 |     QTest::newRow(dataTag: "ARGB_PM source RGB32" ) << QImage::Format_RGB32 << QImage::Format_ARGB32_Premultiplied | 
| 4987 |                                           << QPainter::CompositionMode_Source << qRgba(r: 127, g: 0, b: 0, a: 127) << 127; | 
| 4988 |     QTest::newRow(dataTag: "ARGB source-in RGB32" ) << QImage::Format_RGB32 << QImage::Format_ARGB32 | 
| 4989 |                                           << QPainter::CompositionMode_SourceIn << qRgba(r: 255, g: 0, b: 0, a: 127) << 127; | 
| 4990 |     QTest::newRow(dataTag: "ARGB_PM source-in RGB32" ) << QImage::Format_RGB32 << QImage::Format_ARGB32_Premultiplied | 
| 4991 |                                              << QPainter::CompositionMode_SourceIn << qRgba(r: 127, g: 0, b: 0, a: 127) << 127; | 
| 4992 |     QTest::newRow(dataTag: "ARGB over RGB888" ) << QImage::Format_RGB888 << QImage::Format_ARGB32 | 
| 4993 |                                       << QPainter::CompositionMode_SourceOver << qRgba(r: 255, g: 0, b: 0, a: 127) << 127; | 
| 4994 |     QTest::newRow(dataTag: "ARGB_PM over RGB888" ) << QImage::Format_RGB888 << QImage::Format_ARGB32_Premultiplied | 
| 4995 |                                          << QPainter::CompositionMode_SourceOver << qRgba(r: 127, g: 0, b: 0, a: 127) << 127; | 
| 4996 |     QTest::newRow(dataTag: "ARGB source RGB888" ) << QImage::Format_RGB888 << QImage::Format_ARGB32 | 
| 4997 |                                         << QPainter::CompositionMode_Source << qRgba(r: 255, g: 0, b: 0, a: 127) << 127; | 
| 4998 |     QTest::newRow(dataTag: "ARGB_PM source RGB888" ) << QImage::Format_RGB888 << QImage::Format_ARGB32_Premultiplied | 
| 4999 |                                            << QPainter::CompositionMode_Source << qRgba(r: 127, g: 0, b: 0, a: 127) << 127; | 
| 5000 |     QTest::newRow(dataTag: "ARGB source-in RGB888" ) << QImage::Format_RGB888 << QImage::Format_ARGB32 | 
| 5001 |                                            << QPainter::CompositionMode_SourceIn << qRgba(r: 255, g: 0, b: 0, a: 127) << 127; | 
| 5002 |     QTest::newRow(dataTag: "ARGB_PM source-in RGB888" ) << QImage::Format_RGB888 << QImage::Format_ARGB32_Premultiplied | 
| 5003 |                                               << QPainter::CompositionMode_SourceIn << qRgba(r: 127, g: 0, b: 0, a: 127) << 127; | 
| 5004 |     QTest::newRow(dataTag: "ARGB over RGBx8888" ) << QImage::Format_RGBX8888 << QImage::Format_ARGB32 | 
| 5005 |                                         << QPainter::CompositionMode_SourceOver << qRgba(r: 255, g: 0, b: 0, a: 127) << 127; | 
| 5006 |     QTest::newRow(dataTag: "ARGB_PM over RGBx8888" ) << QImage::Format_RGBX8888 << QImage::Format_ARGB32_Premultiplied | 
| 5007 |                                            << QPainter::CompositionMode_SourceOver << qRgba(r: 127, g: 0, b: 0, a: 127) << 127; | 
| 5008 |     QTest::newRow(dataTag: "ARGB source RGBx8888" ) << QImage::Format_RGBX8888 << QImage::Format_ARGB32 | 
| 5009 |                                           << QPainter::CompositionMode_Source << qRgba(r: 255, g: 0, b: 0, a: 127) << 127; | 
| 5010 |     QTest::newRow(dataTag: "ARGB_PM source RGBx8888" ) << QImage::Format_RGBX8888 << QImage::Format_ARGB32_Premultiplied | 
| 5011 |                                              << QPainter::CompositionMode_Source << qRgba(r: 127, g: 0, b: 0, a: 127) << 127; | 
| 5012 |     QTest::newRow(dataTag: "ARGB source-in RGBx8888" ) << QImage::Format_RGBX8888 << QImage::Format_ARGB32 | 
| 5013 |                                              << QPainter::CompositionMode_SourceIn << qRgba(r: 255, g: 0, b: 0, a: 127) << 127; | 
| 5014 |     QTest::newRow(dataTag: "ARGB_PM source-in RGBx8888" ) << QImage::Format_RGBX8888 << QImage::Format_ARGB32_Premultiplied | 
| 5015 |                                                 << QPainter::CompositionMode_SourceIn << qRgba(r: 127, g: 0, b: 0, a: 127) << 127; | 
| 5016 |     QTest::newRow(dataTag: "ARGB over RGB16" ) << QImage::Format_RGB16 << QImage::Format_ARGB32 | 
| 5017 |                                      << QPainter::CompositionMode_SourceOver << qRgba(r: 255, g: 0, b: 0, a: 127) << 123; | 
| 5018 |     QTest::newRow(dataTag: "ARGB_PM over RGB16" ) << QImage::Format_RGB16 << QImage::Format_ARGB32_Premultiplied | 
| 5019 |                                         << QPainter::CompositionMode_SourceOver << qRgba(r: 127, g: 0, b: 0, a: 127) << 123; | 
| 5020 |     QTest::newRow(dataTag: "ARGB source RGB16" ) << QImage::Format_RGB16 << QImage::Format_ARGB32 | 
| 5021 |                                        << QPainter::CompositionMode_Source << qRgba(r: 255, g: 0, b: 0, a: 127) << 123; | 
| 5022 |     QTest::newRow(dataTag: "ARGB_PM source RGB16" ) << QImage::Format_RGB16 << QImage::Format_ARGB32_Premultiplied | 
| 5023 |                                           << QPainter::CompositionMode_Source << qRgba(r: 127, g: 0, b: 0, a: 127) << 123; | 
| 5024 |     QTest::newRow(dataTag: "ARGB source-in RGB16" ) << QImage::Format_RGB16 << QImage::Format_ARGB32 | 
| 5025 |                                           << QPainter::CompositionMode_SourceIn << qRgba(r: 255, g: 0, b: 0, a: 127) << 123; | 
| 5026 |     QTest::newRow(dataTag: "ARGB_PM source-in RGB16" ) << QImage::Format_RGB16 << QImage::Format_ARGB32_Premultiplied | 
| 5027 |                                              << QPainter::CompositionMode_SourceIn << qRgba(r: 127, g: 0, b: 0, a: 127) << 123; | 
| 5028 |     QTest::newRow(dataTag: "ARGB over RGB666" ) << QImage::Format_RGB666 << QImage::Format_ARGB32 | 
| 5029 |                                       << QPainter::CompositionMode_SourceOver << qRgba(r: 255, g: 0, b: 0, a: 127) << 125; | 
| 5030 |     QTest::newRow(dataTag: "ARGB_PM over RGB666" ) << QImage::Format_RGB666 << QImage::Format_ARGB32_Premultiplied | 
| 5031 |                                          << QPainter::CompositionMode_SourceOver << qRgba(r: 127, g: 0, b: 0, a: 127) << 125; | 
| 5032 |     QTest::newRow(dataTag: "ARGB source RGB666" ) << QImage::Format_RGB666 << QImage::Format_ARGB32 | 
| 5033 |                                         << QPainter::CompositionMode_Source << qRgba(r: 255, g: 0, b: 0, a: 127) << 125; | 
| 5034 |     QTest::newRow(dataTag: "ARGB_PM source RGB666" ) << QImage::Format_RGB666 << QImage::Format_ARGB32_Premultiplied | 
| 5035 |                                            << QPainter::CompositionMode_Source << qRgba(r: 127, g: 0, b: 0, a: 127) << 125; | 
| 5036 |     QTest::newRow(dataTag: "ARGB source-in RGB666" ) << QImage::Format_RGB666 << QImage::Format_ARGB32 | 
| 5037 |                                            << QPainter::CompositionMode_SourceIn << qRgba(r: 255, g: 0, b: 0, a: 127) << 125; | 
| 5038 |     QTest::newRow(dataTag: "ARGB_PM source-in RGB666" ) << QImage::Format_RGB666 << QImage::Format_ARGB32_Premultiplied | 
| 5039 |                                               << QPainter::CompositionMode_SourceIn << qRgba(r: 127, g: 0, b: 0, a: 127) << 125; | 
| 5040 |     QTest::newRow(dataTag: "ARGB over RGB30" ) << QImage::Format_RGB30 << QImage::Format_ARGB32 | 
| 5041 |                                      << QPainter::CompositionMode_SourceOver << qRgba(r: 255, g: 0, b: 0, a: 85) << 85; | 
| 5042 |     QTest::newRow(dataTag: "ARGB_PM over RGB30" ) << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied | 
| 5043 |                                         << QPainter::CompositionMode_SourceOver << qRgba(r: 85, g: 0, b: 0, a: 85) << 85; | 
| 5044 | #if QT_CONFIG(raster_64bit) | 
| 5045 |     QTest::newRow(dataTag: "ARGB source RGB30" ) << QImage::Format_RGB30 << QImage::Format_ARGB32 | 
| 5046 |                                        << QPainter::CompositionMode_Source << qRgba(r: 255, g: 0, b: 0, a: 85) << 85; | 
| 5047 |     QTest::newRow(dataTag: "ARGB source RGB30" ) << QImage::Format_RGB30 << QImage::Format_ARGB32 | 
| 5048 |                                        << QPainter::CompositionMode_Source << qRgba(r: 255, g: 0, b: 0, a: 120) << 85; | 
| 5049 | #endif | 
| 5050 |     QTest::newRow(dataTag: "ARGB_PM source RGB30" ) << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied | 
| 5051 |                                           << QPainter::CompositionMode_Source << qRgba(r: 85, g: 0, b: 0, a: 85) << 85; | 
| 5052 | #if QT_CONFIG(raster_64bit) | 
| 5053 |     QTest::newRow(dataTag: "ARGB_PM source RGB30" ) << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied | 
| 5054 |                                           << QPainter::CompositionMode_Source << qRgba(r: 180, g: 0, b: 0, a: 180) << 170; | 
| 5055 | #endif | 
| 5056 |     QTest::newRow(dataTag: "ARGB source-in RGB30" ) << QImage::Format_RGB30 << QImage::Format_ARGB32 | 
| 5057 |                                           << QPainter::CompositionMode_SourceIn << qRgba(r: 255, g: 0, b: 0, a: 85) << 85; | 
| 5058 |     QTest::newRow(dataTag: "ARGB_PM source-in RGB30" ) << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied | 
| 5059 |                                              << QPainter::CompositionMode_SourceIn << qRgba(r: 85, g: 0, b: 0, a: 85) << 85; | 
| 5060 | } | 
| 5061 |  | 
| 5062 | void tst_QPainter::blendARGBonRGB() | 
| 5063 | { | 
| 5064 |     QFETCH(QImage::Format, dst_format); | 
| 5065 |     QFETCH(QImage::Format, src_format); | 
| 5066 |     QFETCH(QPainter::CompositionMode, compositionMode); | 
| 5067 |     QFETCH(QRgb, color); | 
| 5068 |     QFETCH(int, expected_red); | 
| 5069 |  | 
| 5070 |     QImage imageRgb(16,16, dst_format); | 
| 5071 |     QImage imageArgb(16,16, src_format); | 
| 5072 |     QPainter painter; | 
| 5073 |  | 
| 5074 |     imageArgb.fill(pixel: color); | 
| 5075 |  | 
| 5076 |     imageRgb.fill(color: Qt::black); | 
| 5077 |     painter.begin(&imageRgb); | 
| 5078 |     painter.setCompositionMode(compositionMode); | 
| 5079 |     painter.drawImage(x: 0, y: 0, image: imageArgb); | 
| 5080 |     painter.end(); | 
| 5081 |  | 
| 5082 |     QCOMPARE(imageRgb.pixelColor(0,0).red(), expected_red); | 
| 5083 | } | 
| 5084 |  | 
| 5085 | enum CosmeticStrokerPaint | 
| 5086 | { | 
| 5087 |     Antialiasing, | 
| 5088 |     Dashing | 
| 5089 | }; | 
| 5090 |  | 
| 5091 | static void paint_func(QPainter *p, CosmeticStrokerPaint type) | 
| 5092 | { | 
| 5093 |     p->save(); | 
| 5094 |     switch (type) { | 
| 5095 |     case Antialiasing: | 
| 5096 |         p->setPen(Qt::black); | 
| 5097 |         p->setRenderHint(hint: QPainter::Antialiasing); | 
| 5098 |         p->drawLine(x1: 4, y1: 8, x2: 42, y2: 42); | 
| 5099 |         break; | 
| 5100 |     case Dashing: | 
| 5101 |         p->setPen(QPen(Qt::black, 1, Qt::DashLine, Qt::RoundCap, Qt::MiterJoin)); | 
| 5102 |         p->drawLine(x1: 8, y1: 8, x2: 42, y2: 8); | 
| 5103 |         p->drawLine(x1: 42, y1: 8, x2: 42, y2: 42); | 
| 5104 |         p->drawLine(x1: 42, y1: 42, x2: 8, y2: 42); | 
| 5105 |         p->drawLine(x1: 8, y1: 42, x2: 8, y2: 8); | 
| 5106 |         break; | 
| 5107 |     default: | 
| 5108 |         Q_ASSERT(false); | 
| 5109 |         break; | 
| 5110 |     } | 
| 5111 |     p->restore(); | 
| 5112 | } | 
| 5113 |  | 
| 5114 | Q_DECLARE_METATYPE(CosmeticStrokerPaint) | 
| 5115 |  | 
| 5116 | void tst_QPainter::cosmeticStrokerClipping_data() | 
| 5117 | { | 
| 5118 |     QTest::addColumn<CosmeticStrokerPaint>(name: "paint" ); | 
| 5119 |  | 
| 5120 |     QTest::newRow(dataTag: "antialiasing_paint" ) << Antialiasing; | 
| 5121 |     QTest::newRow(dataTag: "dashing_paint" ) << Dashing; | 
| 5122 | } | 
| 5123 |  | 
| 5124 | void tst_QPainter::cosmeticStrokerClipping() | 
| 5125 | { | 
| 5126 |     QFETCH(CosmeticStrokerPaint, paint); | 
| 5127 |  | 
| 5128 |     QImage image(50, 50, QImage::Format_RGB32); | 
| 5129 |     image.fill(color: Qt::white); | 
| 5130 |  | 
| 5131 |     QPainter p(&image); | 
| 5132 |     paint_func(p: &p, type: paint); | 
| 5133 |     p.end(); | 
| 5134 |  | 
| 5135 |     QImage old = image.copy(); | 
| 5136 |  | 
| 5137 |     image.paintEngine()->setSystemClip(QRect(10, 0, image.width() - 10, image.height())); | 
| 5138 |  | 
| 5139 |     p.begin(&image); | 
| 5140 |     p.fillRect(r: image.rect(), c: Qt::white); | 
| 5141 |     paint_func(p: &p, type: paint); | 
| 5142 |  | 
| 5143 |     // doing same paint operation again with different system clip should not change the image | 
| 5144 |     QCOMPARE(old, image); | 
| 5145 |  | 
| 5146 |     old = image; | 
| 5147 |  | 
| 5148 |     p.setClipRect(QRect(20, 20, 30, 30)); | 
| 5149 |     p.fillRect(r: image.rect(), c: Qt::white); | 
| 5150 |     paint_func(p: &p, type: paint); | 
| 5151 |  | 
| 5152 |     // ditto for regular clips | 
| 5153 |     QCOMPARE(old, image); | 
| 5154 | } | 
| 5155 |  | 
| 5156 | void tst_QPainter::RasterOp_NotDestination() | 
| 5157 | { | 
| 5158 |     QImage image(3, 3, QImage::Format_RGB32); | 
| 5159 |     image.fill(color: Qt::red); | 
| 5160 |  | 
| 5161 |     { | 
| 5162 |         QPainter p(&image); | 
| 5163 |         p.setCompositionMode(QPainter::RasterOp_NotDestination); | 
| 5164 |         p.fillRect(r: image.rect(), c: Qt::black); | 
| 5165 |     } | 
| 5166 |  | 
| 5167 |     uint pixel = image.pixel(x: 1, y: 1); | 
| 5168 |     QCOMPARE(pixel, 0xff00ffff); | 
| 5169 | } | 
| 5170 |  | 
| 5171 | void tst_QPainter::drawTextNoHinting() | 
| 5172 | { | 
| 5173 |     { | 
| 5174 |         QImage image(250, 250, QImage::Format_RGB32); | 
| 5175 |         QPainter p(&image); | 
| 5176 |         QFont font("Arial" , 8); | 
| 5177 |         font.setHintingPreference(QFont::PreferNoHinting); | 
| 5178 |         font.setStyleStrategy(QFont::PreferAntialias); | 
| 5179 |         p.setFont(font); | 
| 5180 |         p.drawText(r: image.rect(), text: "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz" ); | 
| 5181 |     } | 
| 5182 |     // Testing for a crash when DirectWrite is used on Windows | 
| 5183 |     QVERIFY(true); | 
| 5184 | } | 
| 5185 |  | 
| 5186 | void tst_QPainter::drawPolyline_data() | 
| 5187 | { | 
| 5188 |     QTest::addColumn< QVector<QPointF> >(name: "points" ); | 
| 5189 |  | 
| 5190 |     QTest::newRow(dataTag: "basic" ) << (QVector<QPointF>() << QPointF(10, 10) << QPointF(20, 10) << QPointF(20, 20)); | 
| 5191 |     QTest::newRow(dataTag: "clipped" ) << (QVector<QPointF>() << QPoint(-10, 100) << QPoint(-1, 100) << QPoint(-1,  -2) << QPoint(100, -2) << QPoint(100, 40)); // QTBUG-31579 | 
| 5192 |     QTest::newRow(dataTag: "shortsegment" ) << (QVector<QPointF>() << QPoint(20, 100) << QPoint(20, 99) << QPoint(21, 99) << QPoint(21, 104)); // QTBUG-42398 | 
| 5193 |     QTest::newRow(dataTag: "edge" ) << (QVector<QPointF>() << QPointF(4.5, 121.6) << QPointF(9.4, 150.9) << QPointF(14.2, 184.8) << QPointF(19.1, 130.4)); | 
| 5194 | } | 
| 5195 |  | 
| 5196 | void tst_QPainter::drawPolyline() | 
| 5197 | { | 
| 5198 |     QFETCH(QVector<QPointF>, points); | 
| 5199 |     QImage images[2]; | 
| 5200 |  | 
| 5201 |     for (int r = 0; r < 2; r++) { | 
| 5202 |         images[r] = QImage(150, 150, QImage::Format_ARGB32); | 
| 5203 |         images[r].fill(color: Qt::white); | 
| 5204 |         QPainter p(images + r); | 
| 5205 |         QPen pen(Qt::red, 0, Qt::SolidLine, Qt::FlatCap); | 
| 5206 |         p.setPen(pen); | 
| 5207 |         QVERIFY(p.pen().isCosmetic()); | 
| 5208 |         if (r) { | 
| 5209 |             for (int i = 0; i < points.count()-1; i++) { | 
| 5210 |                 p.drawLine(p1: points.at(i), p2: points.at(i: i+1)); | 
| 5211 |             } | 
| 5212 |         } else { | 
| 5213 |             p.drawPolyline(polyline: points); | 
| 5214 |         } | 
| 5215 |     } | 
| 5216 |  | 
| 5217 |     QCOMPARE(images[0], images[1]); | 
| 5218 | } | 
| 5219 |  | 
| 5220 | void tst_QPainter::QTBUG50153_drawImage_assert() | 
| 5221 | { | 
| 5222 |     QImage::Format formats[] = { | 
| 5223 |         QImage::Format_RGB32,  // fetchTransformedBilinearARGB32PM | 
| 5224 |         QImage::Format_ARGB32  // fetchTransformedBilinear | 
| 5225 |     }; | 
| 5226 |  | 
| 5227 |     for (unsigned i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) { | 
| 5228 |         QImage image(3027, 2999, formats[i]); | 
| 5229 |  | 
| 5230 |         QImage backingStore(image.size(), QImage::Format_ARGB32); | 
| 5231 |         QPainter backingStorePainter(&backingStore); | 
| 5232 |  | 
| 5233 |         QTransform transform; | 
| 5234 |         transform.scale( sx: 0.999987, sy: 0.999987 ); | 
| 5235 |  | 
| 5236 |         backingStorePainter.setTransform(transform); | 
| 5237 |         backingStorePainter.setRenderHint(hint: QPainter::SmoothPixmapTransform, on: true); | 
| 5238 |         backingStorePainter.drawImage(x: 0, y: 0, image); | 
| 5239 |  | 
| 5240 |         // No crash, all fine | 
| 5241 |     } | 
| 5242 | } | 
| 5243 |  | 
| 5244 | void tst_QPainter::rotateImage_data() | 
| 5245 | { | 
| 5246 |     QTest::addColumn<QImage>(name: "image" ); | 
| 5247 |     QTest::addColumn<bool>(name: "smooth" ); | 
| 5248 |  | 
| 5249 |     QImage image(128, 128, QImage::Format_RGB32); | 
| 5250 |     for (int y = 0; y < 128; ++y) { | 
| 5251 |         for (int x = 0; x < 128; ++x) { | 
| 5252 |             image.setPixel(x, y, index_or_rgb: qRgb(r: x + y, g: x + y, b: x + y)); | 
| 5253 |         } | 
| 5254 |     } | 
| 5255 |  | 
| 5256 |     QTest::newRow(dataTag: "fast" ) << image << false; | 
| 5257 |     QTest::newRow(dataTag: "smooth" ) << image << true; | 
| 5258 | } | 
| 5259 |  | 
| 5260 | void tst_QPainter::rotateImage() | 
| 5261 | { | 
| 5262 |     QFETCH(QImage, image); | 
| 5263 |     QFETCH(bool, smooth); | 
| 5264 |  | 
| 5265 |     QImage dest(184, 184, QImage::Format_ARGB32_Premultiplied); | 
| 5266 |     dest.fill(color: Qt::transparent); | 
| 5267 |  | 
| 5268 |     QPainter painter(&dest); | 
| 5269 |     QTransform transform; | 
| 5270 |     transform.translate(dx: 92, dy: 0); | 
| 5271 |     transform.rotate(a: 45); | 
| 5272 |     painter.setTransform(transform); | 
| 5273 |     painter.setRenderHint(hint: QPainter::SmoothPixmapTransform, on: smooth); | 
| 5274 |     painter.drawImage(x: 0, y: 0, image); | 
| 5275 |     painter.end(); | 
| 5276 |  | 
| 5277 |     QRgb lastRow = qRgba(r: 0, g: 0, b: 0, a: 0); | 
| 5278 |     for (int y = 0; y < 184; ++y) { | 
| 5279 |         QRgb row = qRgba(r: 0, g: 0, b: 0, a: 0); | 
| 5280 |         for (int x = 0; x < 184; ++x) { | 
| 5281 |             QRgb pixel = dest.pixel(x, y); | 
| 5282 |             if (qAlpha(rgb: pixel) < 255) | 
| 5283 |                 continue; | 
| 5284 |             if (qAlpha(rgb: row) == 0) { | 
| 5285 |                 row = pixel; | 
| 5286 |             } else { | 
| 5287 |                 QCOMPARE(qRed(pixel), qGreen(pixel)); | 
| 5288 |                 QCOMPARE(qGreen(pixel), qBlue(pixel)); | 
| 5289 |                 QVERIFY(qAbs(qRed(row) - qRed(pixel)) <= 2); | 
| 5290 |                 QVERIFY(qAbs(qGreen(row) - qGreen(pixel)) <= 2); | 
| 5291 |                 QVERIFY(qAbs(qBlue(row) - qBlue(pixel)) <= 2); | 
| 5292 |             } | 
| 5293 |  | 
| 5294 |         } | 
| 5295 |         if (qAlpha(rgb: row) && qAlpha(rgb: lastRow)) | 
| 5296 |             QVERIFY(qGray(lastRow) <= qGray(row)); | 
| 5297 |         lastRow = row; | 
| 5298 |     } | 
| 5299 |  | 
| 5300 | } | 
| 5301 |  | 
| 5302 | void tst_QPainter::QTBUG56252() | 
| 5303 | { | 
| 5304 |     QImage sourceImage(1770, 1477, QImage::Format_RGB32); | 
| 5305 |     QImage rotatedImage(1478, 1771, QImage::Format_RGB32); | 
| 5306 |     QTransform transformCenter; | 
| 5307 |     transformCenter.translate(dx: 739.0, dy: 885.5); | 
| 5308 |     transformCenter.rotate(a: 270.0); | 
| 5309 |     transformCenter.translate(dx: -885.0, dy: -738.5); | 
| 5310 |     QPainter painter; | 
| 5311 |     painter.begin(&rotatedImage); | 
| 5312 |     painter.setTransform(transform: transformCenter); | 
| 5313 |     painter.drawImage(p: QPoint(0, 0),image: sourceImage); | 
| 5314 |     painter.end(); | 
| 5315 |  | 
| 5316 |     // If no crash or illegal memory read, all is fine | 
| 5317 | } | 
| 5318 |  | 
| 5319 | void tst_QPainter::blendNullRGB32() | 
| 5320 | { | 
| 5321 |     quint32 data[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 
| 5322 |  | 
| 5323 |     QImage nullImage((const uchar*)data, 16, 1,  QImage::Format_RGB32); | 
| 5324 |     QImage image(16, 1, QImage::Format_RGB32); | 
| 5325 |     image.fill(color: Qt::white); | 
| 5326 |  | 
| 5327 |     QPainter paint(&image); | 
| 5328 |     paint.setCompositionMode(QPainter::CompositionMode_Source); | 
| 5329 |     paint.setOpacity(0.5); | 
| 5330 |     paint.drawImage(x: 0, y: 0, image: nullImage); | 
| 5331 |     paint.end(); | 
| 5332 |  | 
| 5333 |     for (int i=0; i < image.width(); ++i) | 
| 5334 |         QVERIFY(image.pixel(i,0) != 0xffffffff); | 
| 5335 | } | 
| 5336 |  | 
| 5337 | void tst_QPainter::toRGB64() | 
| 5338 | { | 
| 5339 |     QImage dst(10, 1, QImage::Format_BGR30); | 
| 5340 |     QImage src(10, 1, QImage::Format_RGB16); | 
| 5341 |     src.fill(color: Qt::white); | 
| 5342 |  | 
| 5343 |     QPainter paint(&dst); | 
| 5344 |     paint.drawImage(x: 0, y: 0, image: src); | 
| 5345 |     paint.end(); | 
| 5346 |  | 
| 5347 |     for (int i=0; i < dst.width(); ++i) { | 
| 5348 |         QVERIFY(dst.pixelColor(i,0) == QColor(Qt::white)); | 
| 5349 |     } | 
| 5350 | } | 
| 5351 |  | 
| 5352 | void tst_QPainter::fillPolygon() | 
| 5353 | { | 
| 5354 |     QImage image(50, 50, QImage::Format_RGB32); | 
| 5355 |     image.fill(color: Qt::white); | 
| 5356 |  | 
| 5357 |     QPainter painter(&image); | 
| 5358 |     QBrush brush(Qt::black, Qt::SolidPattern); | 
| 5359 |     painter.setBrush(brush); | 
| 5360 |  | 
| 5361 |     QPen pen(Qt::red, 0, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); | 
| 5362 |     painter.setPen(pen); | 
| 5363 |  | 
| 5364 |     const QPoint diamondpoints[5] = { | 
| 5365 |         QPoint(-15, 0), | 
| 5366 |         QPoint(0, -15), | 
| 5367 |         QPoint(15, 0), | 
| 5368 |         QPoint(0, 15), | 
| 5369 |         QPoint(-15, 0) | 
| 5370 |     }; | 
| 5371 |     enum { Outside1, Border1, Inside, Border2, Outside2 } state; | 
| 5372 |  | 
| 5373 |     for (int i = 0; i < 16 ; i++) | 
| 5374 |     { | 
| 5375 |         for (int j = 0; j < 16 ; j++) | 
| 5376 |         { | 
| 5377 |             image.fill(color: Qt::white); | 
| 5378 |             painter.resetTransform(); | 
| 5379 |             painter.translate(dx: 25 + i/16., dy: 25 + j/16.); | 
| 5380 |             painter.drawPolygon(points: diamondpoints, pointCount: 5); | 
| 5381 |  | 
| 5382 |             for (int x = 0; x < 50; x++) { | 
| 5383 |                 state = Outside1; | 
| 5384 |                 for (int y = 0; y < 50; y++) { | 
| 5385 |                     QRgb c = image.pixel(x, y); | 
| 5386 |                     switch (state) { | 
| 5387 |                     case Outside1: | 
| 5388 |                         if (c == QColor(Qt::red).rgb()) | 
| 5389 |                             state = Border1; | 
| 5390 |                         else | 
| 5391 |                             QCOMPARE(c, QColor(Qt::white).rgb()); | 
| 5392 |                         break; | 
| 5393 |                     case Border1: | 
| 5394 |                         if (c == QColor(Qt::black).rgb()) | 
| 5395 |                             state = Inside; | 
| 5396 |                         else if (c == QColor(Qt::white).rgb()) | 
| 5397 |                             state = Outside2; | 
| 5398 |                         else | 
| 5399 |                             QCOMPARE(c, QColor(Qt::red).rgb()); | 
| 5400 |                         break; | 
| 5401 |                     case Inside: | 
| 5402 |                         if (c == QColor(Qt::red).rgb()) | 
| 5403 |                             state = Border2; | 
| 5404 |                         else | 
| 5405 |                             QCOMPARE(c, QColor(Qt::black).rgb()); | 
| 5406 |                         break; | 
| 5407 |                     case Border2: | 
| 5408 |                         if (c == QColor(Qt::white).rgb()) | 
| 5409 |                             state = Outside2; | 
| 5410 |                         else | 
| 5411 |                             QCOMPARE(c, QColor(Qt::red).rgb()); | 
| 5412 |                         break; | 
| 5413 |                     case Outside2: | 
| 5414 |                         QCOMPARE(c, QColor(Qt::white).rgb()); | 
| 5415 |                     } | 
| 5416 |                 } | 
| 5417 |             } | 
| 5418 |             for (int y = 0; y < 50; y++) { | 
| 5419 |                 state = Outside1; | 
| 5420 |                 for (int x = 0; x < 50; x++) { | 
| 5421 |                     QRgb c = image.pixel(x, y); | 
| 5422 |                     switch (state) { | 
| 5423 |                     case Outside1: | 
| 5424 |                         if (c == QColor(Qt::red).rgb()) | 
| 5425 |                             state = Border1; | 
| 5426 |                         else | 
| 5427 |                             QCOMPARE(c, QColor(Qt::white).rgb()); | 
| 5428 |                         break; | 
| 5429 |                     case Border1: | 
| 5430 |                         if (c == QColor(Qt::black).rgb()) | 
| 5431 |                             state = Inside; | 
| 5432 |                         else if (c == QColor(Qt::white).rgb()) | 
| 5433 |                             state = Outside2; | 
| 5434 |                         else | 
| 5435 |                             QCOMPARE(c, QColor(Qt::red).rgb()); | 
| 5436 |                         break; | 
| 5437 |                     case Inside: | 
| 5438 |                         if (c == QColor(Qt::red).rgb()) | 
| 5439 |                             state = Border2; | 
| 5440 |                         else | 
| 5441 |                             QCOMPARE(c, QColor(Qt::black).rgb()); | 
| 5442 |                         break; | 
| 5443 |                     case Border2: | 
| 5444 |                         if (c == QColor(Qt::white).rgb()) | 
| 5445 |                             state = Outside2; | 
| 5446 |                         else | 
| 5447 |                             QCOMPARE(c, QColor(Qt::red).rgb()); | 
| 5448 |                         break; | 
| 5449 |                     case Outside2: | 
| 5450 |                         QCOMPARE(c, QColor(Qt::white).rgb()); | 
| 5451 |                     } | 
| 5452 |                 } | 
| 5453 |             } | 
| 5454 |         } | 
| 5455 |     } | 
| 5456 | } | 
| 5457 |  | 
| 5458 | void tst_QPainter::drawImageAtPointF() | 
| 5459 | { | 
| 5460 |     // Just test we do not crash | 
| 5461 |     QImage image1(10, 10, QImage::Format_RGB32); | 
| 5462 |     QImage image2(200, 200, QImage::Format_RGB32); | 
| 5463 |  | 
| 5464 |     QPainter paint(&image2); | 
| 5465 |     paint.setClipRect(x: 97, y: 46, w: 14, h: 14); | 
| 5466 |     paint.setCompositionMode(QPainter::CompositionMode_Source); | 
| 5467 |     paint.drawImage(p: QPointF(96, std::numeric_limits<int>::max()), image: image1); | 
| 5468 |     paint.drawImage(p: QPointF(std::numeric_limits<int>::min(), 48), image: image1); | 
| 5469 |     paint.end(); | 
| 5470 | } | 
| 5471 |  | 
| 5472 | void tst_QPainter::scaledDashes() | 
| 5473 | { | 
| 5474 |     // Test that we do not hit the limit-huge-number-of-dashes path | 
| 5475 |     QRgb fore = qRgb(r: 0, g: 0, b: 0xff); | 
| 5476 |     QRgb back = qRgb(r: 0xff, g: 0xff, b: 0); | 
| 5477 |     QImage image(5, 32, QImage::Format_RGB32); | 
| 5478 |     image.fill(pixel: back); | 
| 5479 |     QPainter p(&image); | 
| 5480 |     QPen pen(QColor(fore), 3, Qt::DotLine); | 
| 5481 |     p.setPen(pen); | 
| 5482 |     p.scale(sx: 1, sy: 2); | 
| 5483 |     p.drawLine(x1: 2, y1: 0, x2: 2, y2: 16); | 
| 5484 |     p.end(); | 
| 5485 |  | 
| 5486 |     bool foreFound = false; | 
| 5487 |     bool backFound = false; | 
| 5488 |     int i = 0; | 
| 5489 |     while (i < 32 && (!foreFound || !backFound)) { | 
| 5490 |         QRgb pix = image.pixel(x: 3, y: i); | 
| 5491 |         if (pix == fore) | 
| 5492 |             foreFound = true; | 
| 5493 |         else if (pix == back) | 
| 5494 |             backFound = true; | 
| 5495 |         i++; | 
| 5496 |     } | 
| 5497 |  | 
| 5498 |     QVERIFY(foreFound); | 
| 5499 |     QVERIFY(backFound); | 
| 5500 | } | 
| 5501 |  | 
| 5502 | QTEST_MAIN(tst_QPainter) | 
| 5503 |  | 
| 5504 | #include "tst_qpainter.moc" | 
| 5505 |  |