1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
43 #include <QtTest/QtTest>
45 #include <qdrawutil.h>
46 #include <qapplication.h>
48 #include <qfontmetrics.h>
53 #if !defined(Q_OS_WINCE)
57 #include <qpaintengine.h>
58 #include <qdesktopwidget.h>
67 #include <qgraphicsview.h>
68 #include <qgraphicsscene.h>
69 #include <qgraphicsproxywidget.h>
71 #include <qfontdatabase.h>
73 Q_DECLARE_METATYPE(QGradientStops)
74 Q_DECLARE_METATYPE(QLine)
75 Q_DECLARE_METATYPE(QRect)
76 Q_DECLARE_METATYPE(QSize)
77 Q_DECLARE_METATYPE(QPoint)
78 Q_DECLARE_METATYPE(QPainterPath)
83 class tst_QPainter : public QObject
89 virtual ~tst_QPainter();
97 void qt_format_text_clip();
98 void qt_format_text_boundingRect();
100 void drawPixmap_comp_data();
101 void drawPixmap_comp();
103 void saveAndRestore_data();
104 void saveAndRestore();
106 void drawBorderPixmap();
107 void drawPixmapFragments();
109 void drawLine_data();
111 void drawLine_clipped();
112 void drawLine_task121143();
113 void drawLine_task216948();
115 void drawLine_task190634();
116 void drawLine_task229459();
117 void drawLine_task234891();
119 void drawRect_data() { fillData(); }
128 void drawEllipse_data();
130 void drawClippedEllipse_data();
131 void drawClippedEllipse();
133 void drawPath_data();
138 void drawRoundRect_data() { fillData(); }
139 void drawRoundRect();
141 void qimageFormats_data();
142 void qimageFormats();
143 void textOnTransparentImage();
149 void combinedMatrix();
152 void disableEnableClipping();
154 void setEqualClipRegionAndPath_data();
155 void setEqualClipRegionAndPath();
157 void clipRectSaveRestore();
159 void clippedFillPath_data();
160 void clippedFillPath();
161 void clippedLines_data();
163 void clippedPolygon_data();
164 void clippedPolygon();
168 void clipBoundingRect();
170 void setOpacity_data();
173 void drawhelper_blend_untransformed_data();
174 void drawhelper_blend_untransformed();
175 void drawhelper_blend_tiled_untransformed_data();
176 void drawhelper_blend_tiled_untransformed();
178 void porterDuff_warning();
180 void drawhelper_blend_color();
182 void childWidgetViewport();
184 void fillRect_objectBoundingModeGradient();
185 void fillRect_stretchToDeviceMode();
189 void linearGradientSymmetry_data();
190 void linearGradientSymmetry();
192 void gradientInterpolation();
194 void fpe_pixmapTransform();
195 void fpe_zeroLengthLines();
196 void fpe_divByZero();
198 void fpe_steepSlopes_data();
199 void fpe_steepSlopes();
200 void fpe_rasterizeLine_task232012();
202 void fpe_radialGradients();
204 void rasterizer_asserts();
205 void rasterizer_negativeCoords();
207 void blendOverFlow_data();
208 void blendOverFlow();
210 void largeImagePainting_data();
211 void largeImagePainting();
213 void imageScaling_task206785();
215 void outlineFillConsistency();
217 void drawImage_task217400_data();
218 void drawImage_task217400();
219 void drawImage_1x1();
220 void drawImage_task258776();
221 void drawRect_task215378();
222 void drawRect_task247505();
224 #if defined(Q_OS_MAC)
225 void drawText_subPixelPositionsInRaster_qtbug5053();
228 void drawImage_data();
233 void stateResetBetweenQPainters();
235 void imageCoordinateLimit();
236 void imageBlending_data();
237 void imageBlending();
238 void imageBlending_clipped();
240 void paintOnNullPixmap();
241 void checkCompositionMode();
245 void inactivePainter();
247 void extendedBlendModes();
253 void taskQT4444_dontOverflowDashOffset();
256 void setPenColorOnImage();
257 void setPenColorOnPixmap();
259 void QTBUG5939_attachPainterPrivate();
261 void drawPointScaled();
263 void QTBUG14614_gradientCacheRaceCondition();
264 void drawTextOpacity();
266 void QTBUG17053_zeroDashPattern();
268 void drawTextOutsideGuiThread();
272 void setPenColor(QPainter& p);
273 QColor baseColor( int k, int intensity=255 );
274 QImage getResImage( const QString &dir, const QString &addition, const QString &extension );
275 QBitmap getBitmap( const QString &dir, const QString &filename, bool mask );
278 // Testing get/set functions
279 void tst_QPainter::getSetCheck()
281 QImage img(QSize(10, 10), QImage::Format_ARGB32_Premultiplied);
284 // CompositionMode QPainter::compositionMode()
285 // void QPainter::setCompositionMode(CompositionMode)
286 obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceOver));
287 QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceOver), obj1.compositionMode());
288 obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOver));
289 QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOver), obj1.compositionMode());
290 obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Clear));
291 QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Clear), obj1.compositionMode());
292 obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Source));
293 QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Source), obj1.compositionMode());
294 obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Destination));
295 QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Destination), obj1.compositionMode());
296 obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceIn));
297 QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceIn), obj1.compositionMode());
298 obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationIn));
299 QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationIn), obj1.compositionMode());
300 obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceOut));
301 QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceOut), obj1.compositionMode());
302 obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOut));
303 QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOut), obj1.compositionMode());
304 obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceAtop));
305 QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceAtop), obj1.compositionMode());
306 obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationAtop));
307 QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationAtop), obj1.compositionMode());
308 obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Xor));
309 QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Xor), obj1.compositionMode());
311 // const QPen & QPainter::pen()
312 // void QPainter::setPen(const QPen &)
315 QCOMPARE(var3, obj1.pen());
317 QCOMPARE(QPen(), obj1.pen());
319 // const QBrush & QPainter::brush()
320 // void QPainter::setBrush(const QBrush &)
321 QBrush var4(Qt::red);
323 QCOMPARE(var4, obj1.brush());
324 obj1.setBrush(QBrush());
325 QCOMPARE(QBrush(), obj1.brush());
327 // const QBrush & QPainter::background()
328 // void QPainter::setBackground(const QBrush &)
329 QBrush var5(Qt::yellow);
330 obj1.setBackground(var5);
331 QCOMPARE(var5, obj1.background());
332 obj1.setBackground(QBrush());
333 QCOMPARE(QBrush(), obj1.background());
335 // bool QPainter::matrixEnabled()
336 // void QPainter::setMatrixEnabled(bool)
337 obj1.setMatrixEnabled(false);
338 QCOMPARE(false, obj1.matrixEnabled());
339 obj1.setMatrixEnabled(true);
340 QCOMPARE(true, obj1.matrixEnabled());
342 // bool QPainter::viewTransformEnabled()
343 // void QPainter::setViewTransformEnabled(bool)
344 obj1.setViewTransformEnabled(false);
345 QCOMPARE(false, obj1.viewTransformEnabled());
346 obj1.setViewTransformEnabled(true);
347 QCOMPARE(true, obj1.viewTransformEnabled());
350 Q_DECLARE_METATYPE(QPixmap)
351 Q_DECLARE_METATYPE(QPolygon)
352 Q_DECLARE_METATYPE(QBrush)
353 Q_DECLARE_METATYPE(QPen)
354 Q_DECLARE_METATYPE(QFont)
355 Q_DECLARE_METATYPE(QColor)
356 Q_DECLARE_METATYPE(QRegion)
358 tst_QPainter::tst_QPainter()
360 // QtTestCase sets this to false, but this turns off alpha pixmaps on Unix.
361 QApplication::setDesktopSettingsAware(TRUE);
364 tst_QPainter::~tst_QPainter()
368 void tst_QPainter::init()
372 void tst_QPainter::cleanup()
376 /* tests the clipping operations in qt_format_text, making sure
377 the clip rectangle after the call is the same as before
379 void tst_QPainter::qt_format_text_clip()
381 QSKIP("Needs fixing...");
383 QWidget *w = new QWidget( 0 );
385 int modes[] = { Qt::AlignVCenter|Qt::TextSingleLine,
386 Qt::AlignVCenter|Qt::TextSingleLine|Qt::TextDontClip,
387 Qt::AlignVCenter|Qt::TextWordWrap,
388 Qt::AlignVCenter|Qt::TextWordWrap|Qt::TextDontClip,
396 QRegion clipreg = p.clipRegion();
397 bool hasClipping = p.hasClipping();
398 qreal tx = p.matrix().dx();
399 qreal ty = p.matrix().dy();
401 p.drawText( 10, 10, 100, 100, *m,
404 QVERIFY( clipreg == p.clipRegion() );
405 QVERIFY( hasClipping == p.hasClipping() );
406 QCOMPARE( tx, p.matrix().dx() );
407 QCOMPARE( ty, p.matrix().dy() );
409 p.setClipRect( QRect( 5, 5, 50, 50 ) );
410 clipreg = p.clipRegion();
411 hasClipping = p.hasClipping();
413 p.drawText( 10, 10, 100, 100, *m,
416 QVERIFY( clipreg == p.clipRegion() );
417 QVERIFY( hasClipping == p.hasClipping() );
418 QCOMPARE( tx, p.matrix().dx() );
419 QCOMPARE( ty, p.matrix().dy() );
423 p.setMatrix( QMatrix( 2, 1, 3, 4, 5, 6 ) );
424 QRegion clipreg = p.clipRegion();
425 bool hasClipping = p.hasClipping();
426 qreal tx = p.matrix().dx();
427 qreal ty = p.matrix().dy();
429 p.drawText( 10, 10, 100, 100, *m,
432 QVERIFY( clipreg == p.clipRegion() );
433 QVERIFY( hasClipping == p.hasClipping() );
434 QCOMPARE( tx, p.matrix().dx() );
435 QCOMPARE( ty, p.matrix().dy() );
437 p.setClipRect( QRect( 5, 5, 50, 50 ) );
438 clipreg = p.clipRegion();
439 hasClipping = p.hasClipping();
441 p.drawText( 10, 10, 100, 100, *m,
444 QVERIFY( clipreg == p.clipRegion() );
445 QVERIFY( hasClipping == p.hasClipping() );
446 QCOMPARE( tx, p.matrix().dx() );
447 QCOMPARE( ty, p.matrix().dy() );
451 QRegion clipreg = p.clipRegion();
452 bool hasClipping = p.hasClipping();
453 qreal tx = p.matrix().dx();
454 qreal ty = p.matrix().dy();
456 p.drawText( 10, 10, 100, 100, *m,
459 QVERIFY( clipreg == p.clipRegion() );
460 QVERIFY( hasClipping == p.hasClipping() );
461 QCOMPARE( tx, p.matrix().dx() );
462 QCOMPARE( ty, p.matrix().dy() );
464 p.setClipRect( QRect( 5, 5, 50, 50 ));
465 clipreg = p.clipRegion();
466 hasClipping = p.hasClipping();
468 p.drawText( 10, 10, 100, 100, *m,
471 QVERIFY( clipreg == p.clipRegion() );
472 QVERIFY( hasClipping == p.hasClipping() );
473 QCOMPARE( tx, p.matrix().dx() );
474 QCOMPARE( ty, p.matrix().dy() );
478 p.setMatrix( QMatrix( 2, 1, 3, 4, 5, 6 ) );
479 QRegion clipreg = p.clipRegion();
480 bool hasClipping = p.hasClipping();
481 qreal tx = p.matrix().dx();
482 qreal ty = p.matrix().dy();
484 p.drawText( 10, 10, 100, 100, *m,
487 QVERIFY( clipreg == p.clipRegion() );
488 QVERIFY( hasClipping == p.hasClipping() );
489 QCOMPARE( tx, p.matrix().dx() );
490 QCOMPARE( ty, p.matrix().dy() );
492 p.setClipRect(QRect( 5, 5, 50, 50 ));
493 clipreg = p.clipRegion();
494 hasClipping = p.hasClipping();
496 p.drawText( 10, 10, 100, 100, *m,
499 QVERIFY( clipreg == p.clipRegion() );
500 QVERIFY( hasClipping == p.hasClipping() );
501 QCOMPARE( tx, p.matrix().dx() );
502 QCOMPARE( ty, p.matrix().dy() );
509 /* tests the bounding rect calculations in qt_format_text, making sure
510 the bounding rect has a reasonable value.
512 void tst_QPainter::qt_format_text_boundingRect()
514 QSKIP("Needs fixing...");
517 const char * strings[] = {
521 "this is a longer string",
522 "\327\222\327\223\327\233\327\223\327\222\327\233\327\222\327\223\327\233",
523 "aa\327\222\327\233aa",
524 "\327\222\327\223\327\233\327\223\327\222\327\233\327\222\327\223\327\233",
525 "\327\222\327\233aa",
527 "some text longer than 30 chars with a line break at the end\n",
528 "some text\nwith line breaks\nin the middle\nand at the end\n",
533 int modes[] = { Qt::AlignVCenter|Qt::TextSingleLine,
534 Qt::AlignVCenter|Qt::TextSingleLine|Qt::TextDontClip,
535 Qt::AlignVCenter|Qt::TextWordWrap,
536 Qt::AlignVCenter|Qt::TextWordWrap|Qt::TextDontClip,
544 for(int i = 5; i < 15; ++i) {
547 const char **str = strings;
551 QRect br = fm.boundingRect( 0, 0, 2000, 100, *m, QString::fromUtf8( *str ) );
552 QVERIFY( br.width() < 800 );
554 QRect br2 = fm.boundingRect( br.x(), br.y(), br.width(), br.height(), *m, QString::fromUtf8( *str ) );
559 printer.setOutputToFile(TRUE);
560 printer.setOutputFileName("tmp.prn");
561 QPainter p(&printer);
562 QRect pbr = p.fontMetrics().boundingRect( 0, 0, 2000, 100, *m, QString::fromUtf8( *str ) );
566 #if !defined(QT_NO_PRINTER) && !defined(Q_OS_WINCE)
568 QPrinter printer(QPrinter::HighResolution);
569 if (printer.printerName().isEmpty())
570 QSKIP("No printers installed, skipping bounding rect test");
572 printer.setOutputFileName("tmp.prn");
573 QPainter p(&printer);
574 QRect pbr = p.fontMetrics().boundingRect( 0, 0, 12000, 600, *m, QString::fromUtf8( *str ) );
575 QVERIFY(pbr.width() > 2*br.width());
576 QVERIFY(pbr.height() > 2*br.height());
587 const char * strings[] = {
593 "this is a longer string",
594 // "\327\222\327\223\327\233\327\223\327\222\327\233\327\222\327\223\327\233",
595 // "aa\327\222\327\233aa",
596 // "\327\222\327\223\327\233\327\223\327\222\327\233\327\222\327\223\327\233",
597 // "\327\222\327\233aa",
598 // "linebreakatend\n",
599 // "some text longer than 30 chars with a line break at the end\n",
600 // "some text\nwith line breaks\nin the middle\nand at the end\n",
604 // "\347\231\273\351\214\262\346\203\205\345\240\261\343\201\214\350\246\213\343\201\244\343\201\213\343\202\211\343\201\252\343\201\204\343\201\213\347\204\241\345\212\271\343\201\252\343\201\237\343\202\201\343\200\201\nPhotoshop Album \343\202\222\350\265\267\345\213\225\343\201\247\343\201\215\343\201\276\343\201\233\343\202\223\343\200\202\345\206\215\343\202\244\343\203\263\343\202\271\343\203\210\343\203\274\343\203\253\343\201\227\343\201\246\343\201\217\343\201\240\343\201\225\343\201\204\343\200\202"
605 // "\347\231\273\351\214\262\346\203\205\345\240\261\343\201\214\350\246\213\343\201\244\343\201\213\343\202\211\343\201\252\343\201\204\343\201\213\347\204\241\345\212\271\343\201\252\343\201\237\343\202\201\343\200\201\n\343\202\222\350\265\267\345\213\225\343\201\247\343\201\215\343\201\276\343\201\233\343\202\223\343\200\202\345\206\215\343\202\244\343\203\263\343\202\271\343\203\210\343\203\274\343\203\253\343\201\227\343\201\246\343\201\217\343\201\240\343\201\225\343\201\204\343\200\202",
609 int modes[] = { Qt::AlignVCenter,
618 for(int i = 5; i < 15; ++i) {
621 const char **str = strings;
625 QString s = QString::fromUtf8(*str);
626 QRect br = fm.boundingRect(0, 0, 1000, 1000, *m, s );
629 int expectedHeight = fm.height()+lines*fm.lineSpacing();
630 QCOMPARE(br.height(), expectedHeight);
635 QRect br = fm.boundingRect(0, 0, 100, 0, Qt::TextWordWrap,
636 "A paragraph with gggggggggggggggggggggggggggggggggggg in the middle.");
637 QVERIFY(br.height() >= fm.height()+2*fm.lineSpacing());
643 static const char* const maskSource_data[] = {
665 static const char* const maskResult_data[] = {
688 // Mac has other ideas about alpha composition
690 void tst_QPainter::drawPixmap_comp_data()
692 if (qApp->desktop()->depth() < 24)
693 QSKIP("Test only works on 32 bit displays");
695 QTest::addColumn<uint>("dest");
696 QTest::addColumn<uint>("source");
698 QTest::newRow("0% on 0%, 1") << 0x00000000u<< 0x00000000u;
699 QTest::newRow("0% on 0%, 2") << 0x00007fffu << 0x00ff007fu;
701 QTest::newRow("50% on a=0%") << 0x00000000u << 0x7fff0000u;
702 QTest::newRow("50% on a=50%") << 0x7f000000u << 0x7fff0000u;
703 QTest::newRow("50% on deadbeef") << 0xdeafbeefu << 0x7fff0000u;
704 QTest::newRow("deadbeef on a=0%") << 0x00000000u << 0xdeadbeefu;
705 QTest::newRow("deadbeef on a=50%") << 0x7f000000u << 0xdeadbeefu;
706 QTest::newRow("50% blue on 50% red") << 0x7fff0000u << 0x7f0000ffu;
707 QTest::newRow("50% blue on 50% green") << 0x7f00ff00u << 0x7f0000ffu;
708 QTest::newRow("50% red on 50% green") << 0x7f00ff00u << 0x7fff0000u;
709 QTest::newRow("0% on 50%") << 0x7fff00ffu << 0x00ffffffu;
710 QTest::newRow("100% on deadbeef") << 0xdeafbeefu << 0xffabcdefu;
711 QTest::newRow("100% on a=0%") << 0x00000000u << 0xffabcdefu;
714 QRgb qt_compose_alpha(QRgb source, QRgb dest)
716 int r1 = qRed(dest), g1 = qGreen(dest), b1 = qBlue(dest), a1 = qAlpha(dest);
717 int r2 = qRed(source), g2 = qGreen(source), b2 = qBlue(source), a2 = qAlpha(source);
719 int alpha = qMin(a2 + ((255 - a2) * a1 + 127) / 255, 255);
721 return qRgba(0, 0, 0, 0);
724 qMin((r2 * a2 + (255 - a2) * r1 * a1 / 255) / alpha, 255),
725 qMin((g2 * a2 + (255 - a2) * g1 * a1 / 255) / alpha, 255),
726 qMin((b2 * a2 + (255 - a2) * b1 * a1 / 255) / alpha, 255),
730 /* Tests that drawing masked pixmaps works
732 void tst_QPainter::drawPixmap_comp()
735 QFETCH(uint, source);
737 QRgb expected = qt_compose_alpha(source, dest);
739 QColor c1(qRed(dest), qGreen(dest), qBlue(dest), qAlpha(dest));
740 QColor c2(qRed(source), qGreen(source), qBlue(source), qAlpha(source));
742 QPixmap destPm(10, 10), srcPm(10, 10);
746 #if defined(Q_WS_X11)
747 if (!destPm.x11PictureHandle())
748 QSKIP("Requires XRender support");
752 p.drawPixmap(0, 0, srcPm);
755 QImage result = destPm.toImage().convertToFormat(QImage::Format_ARGB32);
756 bool different = false;
757 for (int y=0; y<result.height(); ++y)
758 for (int x=0; x<result.width(); ++x) {
760 if (qAlpha(expected) == 0) {
761 diff = qAlpha(result.pixel(x, y)) != 0;
763 // Compensate for possible roundoff / platform fudge
765 QRgb pix = result.pixel(x, y);
766 diff = (qAbs(qRed(pix) - qRed(expected)) > off)
767 || (qAbs(qGreen(pix) - qGreen(expected)) > off)
768 || (qAbs(qBlue(pix) - qBlue(expected)) > off)
769 || (qAbs(qAlpha(pix) - qAlpha(expected)) > off);
771 if (diff && !different)
772 qDebug( "Different at %d,%d pixel [%d,%d,%d,%d] expected [%d,%d,%d,%d]", x, y,
773 qRed(result.pixel(x, y)), qGreen(result.pixel(x, y)),
774 qBlue(result.pixel(x, y)), qAlpha(result.pixel(x, y)),
775 qRed(expected), qGreen(expected), qBlue(expected), qAlpha(expected));
783 void tst_QPainter::saveAndRestore_data()
785 QTest::addColumn<QFont>("font");
786 QTest::addColumn<QPen>("pen");
787 QTest::addColumn<QBrush>("brush");
788 QTest::addColumn<QColor>("backgroundColor");
789 QTest::addColumn<int>("backgroundMode");
790 QTest::addColumn<QPoint>("brushOrigin");
791 QTest::addColumn<QRegion>("clipRegion");
792 QTest::addColumn<QRect>("window");
793 QTest::addColumn<QRect>("viewport");
795 QPixmap pixmap(1, 1);
797 QFont font = p.font();
799 QBrush brush = p.brush();
800 QColor backgroundColor = p.background().color();
801 Qt::BGMode backgroundMode = p.backgroundMode();
802 QPoint brushOrigin = p.brushOrigin();
803 QRegion clipRegion = p.clipRegion();
804 QRect window = p.window();
805 QRect viewport = p.viewport();
807 QTest::newRow("Original") << font << pen << brush << backgroundColor << int(backgroundMode)
808 << brushOrigin << clipRegion << window << viewport;
811 font2.setPointSize( 24 );
812 QTest::newRow("Modified font.pointSize, brush, backgroundColor, backgroundMode")
813 << font2 << pen << QBrush(Qt::red) << QColor(Qt::blue) << int(Qt::TransparentMode)
814 << brushOrigin << clipRegion << window << viewport;
817 font2.setPixelSize( 20 );
818 QTest::newRow("Modified font.pixelSize, brushOrigin, pos")
819 << font2 << pen << brush << backgroundColor << int(backgroundMode)
820 << QPoint( 50, 32 ) << clipRegion << window << viewport;
822 QTest::newRow("Modified clipRegion, window, viewport")
823 << font << pen << brush << backgroundColor << int(backgroundMode)
824 << brushOrigin << clipRegion.subtracted(QRect(10,10,50,30))
825 << QRect(-500, -500, 500, 500 ) << QRect( 0, 0, 50, 50 );
828 void tst_QPainter::saveAndRestore()
830 QFETCH( QFont, font );
832 QFETCH( QBrush, brush );
833 QFETCH( QColor, backgroundColor );
834 QFETCH( int, backgroundMode );
835 QFETCH( QPoint, brushOrigin );
836 QFETCH( QRegion, clipRegion );
837 QFETCH( QRect, window );
838 QFETCH( QRect, viewport );
840 QPixmap pixmap(1, 1);
841 QPainter painter(&pixmap);
843 QFont font_org = painter.font();
844 QPen pen_org = painter.pen();
845 QBrush brush_org = painter.brush();
846 QColor backgroundColor_org = painter.background().color();
847 Qt::BGMode backgroundMode_org = painter.backgroundMode();
848 QPoint brushOrigin_org = painter.brushOrigin();
849 QRegion clipRegion_org = painter.clipRegion();
850 QRect window_org = painter.window();
851 QRect viewport_org = painter.viewport();
854 painter.setFont( font );
855 painter.setPen( QPen(pen) );
856 painter.setBrush( brush );
857 painter.setBackground( backgroundColor );
858 painter.setBackgroundMode( (Qt::BGMode)backgroundMode );
859 painter.setBrushOrigin( brushOrigin );
860 painter.setClipRegion( clipRegion );
861 painter.setWindow( window );
862 painter.setViewport( viewport );
865 QCOMPARE( painter.font(), font_org );
866 QCOMPARE( painter.font().pointSize(), font_org.pointSize() );
867 QCOMPARE( painter.font().pixelSize(), font_org.pixelSize() );
868 QCOMPARE( painter.pen(), pen_org );
869 QCOMPARE( painter.brush(), brush_org );
870 QCOMPARE( painter.background().color(), backgroundColor_org );
871 QCOMPARE( painter.backgroundMode(), backgroundMode_org );
872 QCOMPARE( painter.brushOrigin(), brushOrigin_org );
873 QCOMPARE( painter.clipRegion(), clipRegion_org );
874 QCOMPARE( painter.window(), window_org );
875 QCOMPARE( painter.viewport(), viewport_org );
882 QColor tst_QPainter::baseColor( int k, int intensity )
884 int r = ( k & 1 ) * intensity;
885 int g = ( (k>>1) & 1 ) * intensity;
886 int b = ( (k>>2) & 1 ) * intensity;
887 return QColor( r, g, b );
890 QImage tst_QPainter::getResImage( const QString &dir, const QString &addition, const QString &extension )
893 QString resFilename = dir + QString( "/res_%1." ).arg( addition ) + extension;
894 if ( !res.load( resFilename ) ) {
895 QWARN(QString("Could not load result data %s %1").arg(resFilename).toLatin1());
901 QBitmap tst_QPainter::getBitmap( const QString &dir, const QString &filename, bool mask )
904 QString bmFilename = dir + QString( "/%1.xbm" ).arg( filename );
905 if ( !bm.load( bmFilename ) ) {
906 QWARN(QString("Could not load bitmap '%1'").arg(bmFilename).toLatin1());
911 QString maskFilename = dir + QString( "/%1-mask.xbm" ).arg( filename );
912 if ( !mask.load( maskFilename ) ) {
913 QWARN(QString("Could not load mask '%1'").arg(maskFilename).toLatin1());
921 static int getPaintedPixels(const QImage &image, const QColor &background)
923 uint color = background.rgba();
927 for (int y = 0; y < image.height(); ++y)
928 for (int x = 0; x < image.width(); ++x)
929 if (image.pixel(x, y) != color)
935 static QRect getPaintedSize(const QImage &image, const QColor &background)
937 // not the fastest but at least it works..
938 int xmin = image.width() + 1;
940 int ymin = image.height() +1;
943 uint color = background.rgba();
945 for ( int y = 0; y < image.height(); ++y ) {
946 for ( int x = 0; x < image.width(); ++x ) {
947 QRgb pixel = image.pixel( x, y );
948 if ( pixel != color && x < xmin )
950 if ( pixel != color && x > xmax )
952 if ( pixel != color && y < ymin )
954 if ( pixel != color && y > ymax )
959 return QRect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
962 static QRect getPaintedSize(const QPixmap &pm, const QColor &background)
964 return getPaintedSize(pm.toImage(), background);
967 void tst_QPainter::initFrom()
969 QWidget *widget = new QWidget();
970 QPalette pal = widget->palette();
971 pal.setColor(QPalette::Foreground, QColor(255, 0, 0));
972 pal.setBrush(QPalette::Background, QColor(0, 255, 0));
973 widget->setPalette(pal);
975 QFont font = widget->font();
976 font.setPointSize(26);
977 font.setItalic(true);
978 widget->setFont(font);
980 QPixmap pm(100, 100);
984 QCOMPARE(p.font(), font);
985 QCOMPARE(p.pen().color(), pal.color(QPalette::Foreground));
986 QCOMPARE(p.background(), pal.background());
991 void tst_QPainter::drawBorderPixmap()
994 src.fill(Qt::transparent);
996 QImage pm(200,200,QImage::Format_RGB32);
998 p.setTransform(QTransform(-1,0,0,-1,173.5,153.5));
999 qDrawBorderPixmap(&p, QRect(0,0,75,105), QMargins(39,39,39,39), src, QRect(0,0,79,79), QMargins(39,39,39,39),
1000 QTileRules(Qt::StretchTile,Qt::StretchTile), 0);
1003 void tst_QPainter::drawPixmapFragments()
1005 QPixmap origPixmap(20, 20);
1006 QPixmap resPixmap(20, 20);
1007 QPainter::PixmapFragment fragments[4] = { {15, 15, 0, 0, 10, 10, 1, 1, 0, 1},
1008 { 5, 15, 10, 0, 10, 10, 1, 1, 0, 1},
1009 {15, 5, 0, 10, 10, 10, 1, 1, 0, 1},
1010 { 5, 5, 10, 10, 10, 10, 1, 1, 0, 1} };
1012 QPainter p(&origPixmap);
1013 p.fillRect(0, 0, 10, 10, Qt::red);
1014 p.fillRect(10, 0, 10, 10, Qt::green);
1015 p.fillRect(0, 10, 10, 10, Qt::blue);
1016 p.fillRect(10, 10, 10, 10, Qt::yellow);
1019 QPainter p(&resPixmap);
1020 p.drawPixmapFragments(fragments, 4, origPixmap);
1023 QImage origImage = origPixmap.toImage().convertToFormat(QImage::Format_ARGB32);
1024 QImage resImage = resPixmap.toImage().convertToFormat(QImage::Format_ARGB32);
1026 QVERIFY(resImage.size() == resPixmap.size());
1027 QVERIFY(resImage.pixel(5, 5) == origImage.pixel(15, 15));
1028 QVERIFY(resImage.pixel(5, 15) == origImage.pixel(15, 5));
1029 QVERIFY(resImage.pixel(15, 5) == origImage.pixel(5, 15));
1030 QVERIFY(resImage.pixel(15, 15) == origImage.pixel(5, 5));
1033 QPainter::PixmapFragment fragment = QPainter::PixmapFragment::create(QPointF(20, 20), QRectF(30, 30, 2, 2));
1034 QVERIFY(fragment.x == 20);
1035 QVERIFY(fragment.y == 20);
1036 QVERIFY(fragment.sourceLeft == 30);
1037 QVERIFY(fragment.sourceTop == 30);
1038 QVERIFY(fragment.width == 2);
1039 QVERIFY(fragment.height == 2);
1040 QVERIFY(fragment.scaleX == 1);
1041 QVERIFY(fragment.scaleY == 1);
1042 QVERIFY(fragment.rotation == 0);
1043 QVERIFY(fragment.opacity == 1);
1046 void tst_QPainter::drawLine_data()
1048 QTest::addColumn<QLine>("line");
1050 QTest::newRow("0-45") << QLine(0, 20, 100, 0);
1051 QTest::newRow("45-90") << QLine(0, 100, 20, 0);
1052 QTest::newRow("90-135") << QLine(20, 100, 0, 0);
1053 QTest::newRow("135-180") << QLine(100, 20, 0, 0);
1054 QTest::newRow("180-225") << QLine(100, 0, 0, 20);
1055 QTest::newRow("225-270") << QLine(20, 0, 0, 100);
1056 QTest::newRow("270-315") << QLine(0, 0, 20, 100);
1057 QTest::newRow("315-360") << QLine(0, 0, 100, 20);
1060 void tst_QPainter::drawLine()
1062 const int offset = 5;
1063 const int epsilon = 1; // allow for one pixel difference
1065 QFETCH(QLine, line);
1067 QPixmap pixmapUnclipped(qMin(line.x1(), line.x2())
1068 + 2*offset + qAbs(line.dx()),
1069 qMin(line.y1(), line.y2())
1070 + 2*offset + qAbs(line.dy()));
1073 pixmapUnclipped.fill(Qt::white);
1074 QPainter p(&pixmapUnclipped);
1075 p.translate(offset, offset);
1076 p.setPen(QPen(Qt::black));
1080 const QRect painted = getPaintedSize(pixmapUnclipped, Qt::white);
1083 l.translate(offset, offset);
1084 QVERIFY(qAbs(painted.width() - qAbs(l.dx())) <= epsilon);
1085 QVERIFY(qAbs(painted.height() - qAbs(l.dy())) <= epsilon);
1086 QVERIFY(qAbs(painted.top() - qMin(l.y1(), l.y2())) <= epsilon);
1087 QVERIFY(qAbs(painted.left() - qMin(l.x1(), l.x2())) <= epsilon);
1088 QVERIFY(qAbs(painted.bottom() - qMax(l.y1(), l.y2())) <= epsilon);
1089 QVERIFY(qAbs(painted.right() - qMax(l.x1(), l.x2())) <= epsilon);
1092 QPixmap pixmapClipped(qMin(line.x1(), line.x2())
1093 + 2*offset + qAbs(line.dx()),
1094 qMin(line.y1(), line.y2())
1095 + 2*offset + qAbs(line.dy()));
1097 const QRect clip = QRect(line.p1(), line.p2()).normalized();
1099 pixmapClipped.fill(Qt::white);
1100 QPainter p(&pixmapClipped);
1101 p.translate(offset, offset);
1102 p.setClipRect(clip);
1103 p.setPen(QPen(Qt::black));
1108 const QImage unclipped = pixmapUnclipped.toImage();
1109 const QImage clipped = pixmapClipped.toImage();
1110 QCOMPARE(unclipped, clipped);
1113 void tst_QPainter::drawLine_clipped()
1115 QImage image(16, 1, QImage::Format_ARGB32_Premultiplied);
1119 p.setPen(QPen(Qt::black, 10));
1121 // this should fill the whole image
1122 p.drawLine(-1, -1, 17, 1);
1125 for (int x = 0; x < 16; ++x)
1126 QCOMPARE(image.pixel(x, 0), 0xff000000);
1129 void tst_QPainter::drawLine_task121143()
1131 QPen pen(Qt::black);
1133 QImage image(5, 5, QImage::Format_ARGB32_Premultiplied);
1134 image.fill(0xffffffff);
1137 p.drawLine(QLine(0, 0+4, 0+4, 0));
1140 QImage expected(5, 5, QImage::Format_ARGB32_Premultiplied);
1141 expected.fill(0xffffffff);
1142 for (int x = 0; x < 5; ++x)
1143 expected.setPixel(x, 5-x-1, pen.color().rgb());
1145 QCOMPARE(image, expected);
1148 void tst_QPainter::drawLine_task190634()
1150 QPen pen(Qt::black, 3);
1152 QImage image(32, 32, QImage::Format_ARGB32_Premultiplied);
1154 p.fillRect(0, 0, image.width(), image.height(), Qt::white);
1157 p.drawLine(QLineF(2, -1.6, 10, -1.6));
1160 const uint *data = reinterpret_cast<uint *>(image.bits());
1162 for (int i = 0; i < image.width() * image.height(); ++i)
1163 QCOMPARE(data[i], 0xffffffff);
1166 p.fillRect(0, 0, image.width(), image.height(), Qt::white);
1169 p.drawLine(QLineF(-1.6, 2, -1.6, 10));
1172 data = reinterpret_cast<uint *>(image.bits());
1174 for (int i = 0; i < image.width() * image.height(); ++i)
1175 QCOMPARE(data[i], 0xffffffff);
1178 p.fillRect(0, 0, image.width(), image.height(), Qt::white);
1181 p.drawLine( QPoint(2,-2), QPoint(3,-5) );
1184 data = reinterpret_cast<uint *>(image.bits());
1186 for (int i = 0; i < image.width() * image.height(); ++i)
1187 QCOMPARE(data[i], 0xffffffff);
1190 void tst_QPainter::drawLine_task229459()
1192 QImage image(32, 32, QImage::Format_ARGB32_Premultiplied);
1194 QPen pen(Qt::black, 64);
1198 p.drawLine(-8, -8, 10000000, 10000000);
1201 QImage expected = image;
1202 expected.fill(0xff000000);
1204 QCOMPARE(image, expected);
1207 void tst_QPainter::drawLine_task234891()
1209 QImage img(100, 1000, QImage::Format_ARGB32_Premultiplied);
1211 QImage expected = img;
1214 p.setPen(QPen(QBrush(QColor(255,0,0)), 6));
1215 p.drawLine(QPointF(25000,100),QPointF(30000,105));
1217 p.setPen(QPen(QBrush(QColor(0,255,0)), 6));
1218 p.drawLine(QPointF(30000,150),QPointF(35000,155));
1220 p.setPen(QPen(QBrush(QColor(0,0,255)), 6));
1221 p.drawLine(QPointF(65000,200),QPointF(66000,205));
1223 QCOMPARE(expected, img);
1226 void tst_QPainter::drawLine_task216948()
1228 QImage img(1, 10, QImage::Format_ARGB32_Premultiplied);
1232 QLine line(10, 0, 10, 10);
1233 p.translate(-10, 0);
1237 for (int i = 0; i < img.height(); ++i)
1238 QCOMPARE(img.pixel(0, i), QColor(Qt::black).rgba());
1241 void tst_QPainter::drawRect()
1243 QFETCH(QRect, rect);
1244 QFETCH(bool, usePen);
1246 QPixmap pixmap(rect.x() + rect.width() + 10,
1247 rect.y() + rect.height() + 10);
1249 pixmap.fill(Qt::white);
1250 QPainter p(&pixmap);
1251 p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen));
1252 p.setBrush(Qt::black);
1256 int increment = usePen ? 1 : 0;
1258 const QRect painted = getPaintedSize(pixmap, Qt::white);
1259 QCOMPARE(painted.width(), rect.width() + increment);
1260 QCOMPARE(painted.height(), rect.height() + increment);
1264 void tst_QPainter::drawRect2()
1266 QImage image(64, 64, QImage::Format_ARGB32_Premultiplied);
1268 image.fill(0xffffffff);
1270 QTransform transform(0.368567, 0, 0, 0, 0.368567, 0, 0.0289, 0.0289, 1);
1273 p.setTransform(transform);
1274 p.setBrush(Qt::red);
1275 p.setPen(Qt::NoPen);
1276 p.drawRect(QRect(14, 14, 39, 39));
1279 QRect fill = getPaintedSize(image, Qt::white);
1280 image.fill(0xffffffff);
1283 p.setTransform(transform);
1284 p.drawRect(QRect(14, 14, 39, 39));
1287 QRect stroke = getPaintedSize(image, Qt::white);
1288 QCOMPARE(stroke.adjusted(1, 1, 0, 0), fill.adjusted(0, 0, 1, 1));
1292 void tst_QPainter::fillRect()
1294 QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
1295 image.fill(QColor(0, 0, 0, 0).rgba());
1299 p.fillRect(0, 0, 100, 100, QColor(255, 0, 0, 127));
1301 // pixmap.save("bla1.png", "PNG");
1302 QCOMPARE(getPaintedSize(image, QColor(0, 0, 0, 0)),
1303 QRect(0, 0, 100, 100));
1304 QCOMPARE(getPaintedSize(image, QColor(127, 0, 0, 127)).isValid(),
1307 p.setCompositionMode(QPainter::CompositionMode_SourceIn);
1308 p.fillRect(50, 0, 50, 100, QColor(0, 0, 255, 255));
1310 QCOMPARE(getPaintedSize(image, QColor(127, 0, 0, 127)),
1311 QRect(50, 0, 50, 100));
1312 QCOMPARE(getPaintedSize(image, QColor(0, 0, 127, 127)),
1313 QRect(0, 0, 50, 100));
1316 void tst_QPainter::fillRect2()
1318 QRgb background = 0x0;
1320 QImage img(1, 20, QImage::Format_ARGB32_Premultiplied);
1321 img.fill(background);
1325 QRectF rect(0, 1, 1.2, 18);
1326 p.fillRect(rect, Qt::black);
1330 QCOMPARE(img.pixel(0, 0), background);
1331 QCOMPARE(img.pixel(0, img.height() - 1), background);
1333 QCOMPARE(img.pixel(0, 1), img.pixel(0, 2));
1334 QCOMPARE(img.pixel(0, img.height() - 2), img.pixel(0, img.height() - 3));
1337 void tst_QPainter::fillRect3()
1339 QImage img(1, 1, QImage::Format_ARGB32_Premultiplied);
1340 img.fill(QColor(Qt::black).rgba());
1343 p.setCompositionMode(QPainter::CompositionMode_Source);
1344 p.fillRect(img.rect(), Qt::transparent);
1347 QCOMPARE(img.pixel(0, 0), 0U);
1350 void tst_QPainter::fillRect4()
1352 QImage image(100, 1, QImage::Format_ARGB32_Premultiplied);
1355 QImage expected = image;
1356 expected.fill(0xffffffff);
1360 p.setPen(Qt::NoPen);
1362 for (int i = 0; i < 33; ++i)
1363 p.fillRect(QRectF(3 * i, 0, 3, 1), Qt::white);
1367 QCOMPARE(image, expected);
1370 void tst_QPainter::drawPath_data()
1372 QTest::addColumn<QPainterPath>("path");
1373 QTest::addColumn<QRect>("expectedBounds");
1374 QTest::addColumn<int>("expectedPixels");
1378 p.addRect(2, 2, 10, 10);
1379 QTest::newRow("int-aligned rect") << p << QRect(2, 2, 10, 10) << 10 * 10;
1384 p.addRect(2.25, 2.25, 10, 10);
1385 QTest::newRow("non-aligned rect") << p << QRect(3, 3, 10, 10) << 10 * 10;
1390 p.addRect(2.25, 2.25, 10.5, 10.5);
1391 QTest::newRow("non-aligned rect 2") << p << QRect(3, 3, 10, 10) << 10 * 10;
1396 p.addRect(2.5, 2.5, 10, 10);
1397 QTest::newRow("non-aligned rect 3") << p << QRect(3, 3, 10, 10) << 10 * 10;
1402 p.addRect(2, 2, 10, 10);
1403 p.addRect(4, 4, 6, 6);
1404 QTest::newRow("rect-in-rect") << p << QRect(2, 2, 10, 10) << 10 * 10 - 6 * 6;
1409 p.addRect(2, 2, 10, 10);
1410 p.addRect(4, 4, 6, 6);
1411 p.addRect(6, 6, 2, 2);
1412 QTest::newRow("rect-in-rect-in-rect") << p << QRect(2, 2, 10, 10) << 10 * 10 - 6 * 6 + 2 * 2;
1416 void tst_QPainter::drawPath()
1418 QFETCH(QPainterPath, path);
1419 QFETCH(QRect, expectedBounds);
1420 QFETCH(int, expectedPixels);
1422 const int offset = 2;
1424 QImage image(expectedBounds.width() + 2 * offset, expectedBounds.height() + 2 * offset,
1425 QImage::Format_ARGB32_Premultiplied);
1426 image.fill(QColor(Qt::white).rgb());
1429 p.setPen(Qt::NoPen);
1430 p.setBrush(Qt::black);
1431 p.translate(offset - expectedBounds.left(), offset - expectedBounds.top());
1435 const QRect paintedBounds = getPaintedSize(image, Qt::white);
1437 QCOMPARE(paintedBounds.x(), offset);
1438 QCOMPARE(paintedBounds.y(), offset);
1439 QCOMPARE(paintedBounds.width(), expectedBounds.width());
1440 QCOMPARE(paintedBounds.height(), expectedBounds.height());
1442 if (expectedPixels != -1) {
1443 int paintedPixels = getPaintedPixels(image, Qt::white);
1444 QCOMPARE(paintedPixels, expectedPixels);
1448 void tst_QPainter::drawPath2()
1452 for (int h = 5; h < 200; ++h) {
1453 QPainterPath p1, p2;
1460 const int offset = 2;
1462 QImage image(w + 2 * offset, h + 2 * offset,
1463 QImage::Format_ARGB32_Premultiplied);
1464 image.fill(QColor(Qt::white).rgb());
1467 p.setPen(Qt::NoPen);
1468 p.setBrush(Qt::black);
1469 p.translate(offset, offset);
1473 const int p1Pixels = getPaintedPixels(image, Qt::white);
1475 image.fill(QColor(Qt::white).rgb());
1477 p.setPen(Qt::NoPen);
1478 p.setBrush(Qt::black);
1479 p.translate(offset, offset);
1483 const int p2Pixels = getPaintedPixels(image, Qt::white);
1485 QCOMPARE(p1Pixels + p2Pixels, w * h);
1489 void tst_QPainter::drawPath3()
1491 #if !defined(Q_OS_WINCE)
1492 QImage imgA(400, 400, QImage::Format_RGB32);
1494 QImage imgA(100, 100, QImage::Format_RGB32);
1496 imgA.fill(0xffffff);
1500 for (int y = 0; y < imgA.height(); ++y) {
1501 for (int x = 0; x < imgA.width(); ++x) {
1503 imgA.setPixel(x, y, 0);
1504 path.addRect(x, y, 1, 1);
1510 p.setPen(Qt::NoPen);
1511 p.setBrush(Qt::black);
1516 QVERIFY(imgA == imgB);
1518 imgA.invertPixels();
1519 imgB.fill(0xffffff);
1522 p.setPen(Qt::NoPen);
1523 p.setBrush(Qt::black);
1525 QRectF rect(0, 0, imgA.width(), imgA.height());
1526 path.addRect(rect.adjusted(-10, -10, 10, 10));
1530 QVERIFY(imgA == imgB);
1532 path.setFillRule(Qt::WindingFill);
1533 imgB.fill(0xffffff);
1536 p.setPen(Qt::NoPen);
1537 p.setBrush(Qt::black);
1538 QRect clip = rect.adjusted(10, 10, -10, -10).toRect();
1539 p.setClipRect(clip);
1543 QCOMPARE(getPaintedPixels(imgB, Qt::white), clip.width() * clip.height());
1546 void tst_QPainter::drawEllipse_data()
1548 QTest::addColumn<QSize>("size");
1549 QTest::addColumn<bool>("usePen");
1551 // The current drawEllipse algorithm (drawEllipse_midpoint_i in
1552 // qpaintengine_raster.cpp) draws ellipses that are too wide if the
1553 // ratio between width and hight is too large/small (task 114874). Those
1554 // ratios are therefore currently avoided.
1555 for (int w = 10; w < 128; w += 7) {
1556 for (int h = w/2; h < qMin(2*w, 128); h += 13) {
1557 QString s = QString("%1x%2").arg(w).arg(h);
1558 QTest::newRow(QString("%1 with pen").arg(s).toLatin1()) << QSize(w, h) << true;
1559 QTest::newRow(QString("%1 no pen").arg(s).toLatin1()) << QSize(w, h) << false;
1564 void tst_QPainter::drawEllipse()
1566 QFETCH(QSize, size);
1567 QFETCH(bool, usePen);
1569 const int offset = 10;
1570 QRect rect(QPoint(offset, offset), size);
1572 QImage image(size.width() + 2 * offset, size.height() + 2 * offset,
1573 QImage::Format_ARGB32_Premultiplied);
1574 image.fill(QColor(Qt::white).rgb());
1577 p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen));
1578 p.setBrush(Qt::black);
1579 p.drawEllipse(rect);
1582 QPixmap pixmap = QPixmap::fromImage(image);
1584 const QRect painted = getPaintedSize(pixmap, Qt::white);
1586 QCOMPARE(painted.x(), rect.x());
1587 QCOMPARE(painted.y(), rect.y() + (usePen ? 0 : 1));
1588 QCOMPARE(painted.width(), size.width() + (usePen ? 1 : 0));
1589 QCOMPARE(painted.height(), size.height() + (usePen ? 1 : -1));
1592 void tst_QPainter::drawClippedEllipse_data()
1594 QTest::addColumn<QRect>("rect");
1596 for (int w = 20; w < 128; w += 7) {
1597 for (int h = w/2; h < qMin(2*w, 128); h += 13) {
1598 QString s = QString("%1x%2").arg(w).arg(h);
1599 QTest::newRow(QString("%1 top").arg(s).toLatin1()) << QRect(0, -h/2, w, h);
1600 QTest::newRow(QString("%1 topright").arg(s).toLatin1()) << QRect(w/2, -h/2, w, h);
1601 QTest::newRow(QString("%1 right").arg(s).toLatin1()) << QRect(w/2, 0, w, h);
1602 QTest::newRow(QString("%1 bottomright").arg(s).toLatin1()) << QRect(w/2, h/2, w, h);
1603 QTest::newRow(QString("%1 bottom").arg(s).toLatin1()) << QRect(0, h/2, w, h);
1604 QTest::newRow(QString("%1 bottomleft").arg(s).toLatin1()) << QRect(-w/2, h/2, w, h);
1605 QTest::newRow(QString("%1 left").arg(s).toLatin1()) << QRect(-w/2, 0, w, h);
1606 QTest::newRow(QString("%1 topleft").arg(s).toLatin1()) << QRect(-w/2, -h/2, w, h);
1611 void tst_QPainter::drawClippedEllipse()
1613 QFETCH(QRect, rect);
1614 if (sizeof(qreal) != sizeof(double))
1615 QSKIP("Test only works for qreal==double");
1616 QImage image(rect.width() + 1, rect.height() + 1,
1617 QImage::Format_ARGB32_Premultiplied);
1618 QRect expected = QRect(rect.x(), rect.y(), rect.width()+1, rect.height()+1)
1619 & QRect(0, 0, image.width(), image.height());
1622 image.fill(QColor(Qt::white).rgb());
1624 p.drawEllipse(rect);
1627 QPixmap pixmap = QPixmap::fromImage(image);
1628 const QRect painted = getPaintedSize(pixmap, Qt::white);
1630 QCOMPARE(painted.x(), expected.x());
1631 QCOMPARE(painted.y(), expected.y());
1632 QCOMPARE(painted.width(), expected.width());
1633 QCOMPARE(painted.height(), expected.height());
1637 void tst_QPainter::drawRoundRect()
1639 QFETCH(QRect, rect);
1640 QFETCH(bool, usePen);
1643 if (QTest::currentDataTag() == QByteArray("rect(6, 12, 3, 14) with pen") ||
1644 QTest::currentDataTag() == QByteArray("rect(6, 17, 3, 25) with pen") ||
1645 QTest::currentDataTag() == QByteArray("rect(10, 6, 10, 3) with pen") ||
1646 QTest::currentDataTag() == QByteArray("rect(10, 12, 10, 14) with pen") ||
1647 QTest::currentDataTag() == QByteArray("rect(13, 45, 17, 80) with pen") ||
1648 QTest::currentDataTag() == QByteArray("rect(13, 50, 17, 91) with pen") ||
1649 QTest::currentDataTag() == QByteArray("rect(17, 6, 24, 3) with pen") ||
1650 QTest::currentDataTag() == QByteArray("rect(24, 12, 38, 14) with pen"))
1651 QSKIP("The Mac paint engine is off-by-one on certain rect sizes");
1653 QPixmap pixmap(rect.x() + rect.width() + 10,
1654 rect.y() + rect.height() + 10);
1656 pixmap.fill(Qt::white);
1657 QPainter p(&pixmap);
1658 p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen));
1659 p.setBrush(Qt::black);
1660 p.drawRoundRect(rect);
1663 int increment = usePen ? 1 : 0;
1665 const QRect painted = getPaintedSize(pixmap, Qt::white);
1666 QCOMPARE(painted.width(), rect.width() + increment);
1667 QCOMPARE(painted.height(), rect.height() + increment);
1671 Q_DECLARE_METATYPE(QImage::Format)
1673 void tst_QPainter::qimageFormats_data()
1675 QTest::addColumn<QImage::Format>("format");
1676 QTest::newRow("QImage::Format_RGB32") << QImage::Format_RGB32;
1677 QTest::newRow("QImage::Format_ARGB32") << QImage::Format_ARGB32;
1678 QTest::newRow("QImage::Format_ARGB32_Premultiplied") << QImage::Format_ARGB32_Premultiplied;
1679 QTest::newRow("QImage::Format_RGB16") << QImage::Format_RGB16;
1680 QTest::newRow("Qimage::Format_ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied;
1681 QTest::newRow("Qimage::Format_RGB666") << QImage::Format_RGB666;
1682 QTest::newRow("Qimage::Format_RGB555") << QImage::Format_RGB555;
1683 QTest::newRow("Qimage::Format_ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied;
1684 QTest::newRow("Qimage::Format_RGB888") << QImage::Format_RGB888;
1688 Tests that QPainter can paint on various QImage formats.
1690 void tst_QPainter::qimageFormats()
1692 QFETCH(QImage::Format, format);
1694 const QSize size(100, 100);
1695 QImage image(size, format);
1698 const QColor testColor(Qt::red);
1700 QVERIFY(p.isActive());
1701 p.setBrush(QBrush(testColor));
1702 p.drawRect(QRect(QPoint(0,0), size));
1703 QCOMPARE(image.pixel(50, 50), testColor.rgb());
1706 void tst_QPainter::fillData()
1708 QTest::addColumn<QRect>("rect");
1709 QTest::addColumn<bool>("usePen");
1711 for (int w = 3; w < 50; w += 7) {
1712 for (int h = 3; h < 50; h += 11) {
1715 QTest::newRow(QString("rect(%1, %2, %3, %4) with pen").arg(x).arg(y).arg(w).arg(h).toLatin1())
1716 << QRect(x, y, w, h) << true;
1717 QTest::newRow(QString("rect(%1, %2, %3, %4) no pen").arg(x).arg(y).arg(w).arg(h).toLatin1())
1718 << QRect(x, y, w, h) << false;
1724 Test that drawline works properly after setWindow has been called.
1726 void tst_QPainter::setWindow()
1728 QPixmap pixmap(600, 600);
1729 pixmap.fill(QColor(Qt::white));
1731 QPainter painter(&pixmap);
1732 painter.setWindow(0, 0, 3, 3);
1733 painter.drawLine(1, 1, 2, 2);
1735 const QRect painted = getPaintedSize(pixmap, Qt::white);
1736 QVERIFY(195 < painted.y() && painted.y() < 205); // correct value is around 200
1737 QVERIFY(195 < painted.height() && painted.height() < 205); // correct value is around 200
1740 void tst_QPainter::combinedMatrix()
1745 p.setWindow(0, 0, 1, 1);
1746 p.setViewport(32, 0, 32, 32);
1748 p.translate(0.5, 0.5);
1750 QMatrix cm = p.combinedMatrix();
1752 QPointF pt = QPointF(0, 0) * cm;
1754 QCOMPARE(pt.x(), 48.0);
1755 QCOMPARE(pt.y(), 16.0);
1758 void tst_QPainter::textOnTransparentImage()
1760 bool foundPixel = false;
1761 QImage image(10, 10, QImage::Format_ARGB32_Premultiplied);
1762 image.fill(qRgba(0, 0, 0, 0)); // transparent
1764 QPainter painter(&image);
1765 painter.setPen(QColor(255, 255, 255));
1766 painter.drawText(0, 10, "W");
1768 for (int x = 0; x < image.width(); ++x)
1769 for (int y = 0; y < image.height(); ++y)
1770 if (image.pixel(x, y) != 0)
1772 QVERIFY(foundPixel);
1775 void tst_QPainter::renderHints()
1777 QImage img(1, 1, QImage::Format_RGB32);
1782 p.setRenderHints(QPainter::RenderHints(0xffffffff), false);
1783 QCOMPARE(p.renderHints(), QPainter::RenderHints(0));
1786 p.setRenderHint(QPainter::Antialiasing);
1787 QVERIFY(p.renderHints() & QPainter::Antialiasing);
1789 p.setRenderHint(QPainter::Antialiasing, false);
1790 QVERIFY(!(p.renderHints() & QPainter::Antialiasing));
1793 p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
1794 QVERIFY(p.renderHints() & (QPainter::Antialiasing | QPainter::SmoothPixmapTransform));
1796 p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false);
1797 QVERIFY(!(p.renderHints() & (QPainter::Antialiasing | QPainter::SmoothPixmapTransform)));
1800 int countPixels(const QImage &img, const QRgb &color)
1803 for (int y = 0; y < img.height(); ++y) {
1804 for (int x = 0; x < img.width(); ++x) {
1805 count += ((img.pixel(x, y) & 0xffffff) == color);
1811 template <typename T>
1812 void testClipping(QImage &img)
1815 a.addRect(QRect(2, 2, 4, 4));
1816 b.addRect(QRect(4, 4, 4, 4));
1823 p.setClipPath(b, Qt::IntersectClip);
1825 p.setClipping(false);
1826 p.setPen(Qt::NoPen);
1827 p.setBrush(QColor(0xff0000));
1828 p.drawRect(T(0, 0, 10, 10));
1830 p.setClipping(true);
1831 p.setBrush(QColor(0x00ff00));
1832 p.drawRect(T(0, 0, 10, 10));
1834 QCOMPARE(countPixels(img, 0xff0000), 96);
1835 QCOMPARE(countPixels(img, 0x00ff00), 4);
1838 void tst_QPainter::disableEnableClipping()
1840 QImage img(10, 10, QImage::Format_RGB32);
1842 testClipping<QRectF>(img);
1843 testClipping<QRect>(img);
1846 void tst_QPainter::setClipRect()
1848 QImage img(10, 10, QImage::Format_RGB32);
1849 // simple test to let valgrind check for buffer overflow
1852 p.setClipRect(-10, -10, 100, 100);
1853 p.fillRect(-10, -10, 100, 100, QBrush(QColor(Qt::red)));
1856 // rects with negative width/height
1859 p.setClipRect(QRect(10, 10, -10, 10));
1860 QVERIFY(p.clipRegion().isEmpty());
1861 p.setClipRect(QRect(10, 10, 10, -10));
1862 QVERIFY(p.clipRegion().isEmpty());
1863 p.setClipRect(QRectF(10.5, 10.5, -10.5, 10.5));
1864 QVERIFY(p.clipRegion().isEmpty());
1865 p.setClipRect(QRectF(10.5, 10.5, 10.5, -10.5));
1866 QVERIFY(p.clipRegion().isEmpty());
1871 This tests the two different clipping approaches in QRasterPaintEngine,
1872 one when using a QRegion and one when using a QPainterPath. They should
1875 void tst_QPainter::setEqualClipRegionAndPath_data()
1877 QTest::addColumn<QSize>("deviceSize");
1878 QTest::addColumn<QRegion>("region");
1880 QTest::newRow("empty") << QSize(100, 100) << QRegion();
1881 QTest::newRow("simple rect") << QSize(100, 100)
1882 << QRegion(QRect(5, 5, 10, 10));
1884 QVector<QRect> rects;
1887 rects << QRect(5, 5, 10, 10) << QRect(20, 20, 10, 10);
1888 region.setRects(rects.constData(), rects.size());
1889 QTest::newRow("two rects") << QSize(100, 100) << region;
1892 rects << QRect(5, 5, 10, 10) << QRect(20, 5, 10, 10);
1893 region.setRects(rects.constData(), rects.size());
1894 QTest::newRow("two x-adjacent rects") << QSize(100, 100) << region;
1897 rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100);
1898 region.setRects(rects.constData(), rects.size());
1899 QTest::newRow("two x-adjacent rects 2") << QSize(100, 100) << region;
1902 rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100);
1903 region.setRects(rects.constData(), rects.size());
1904 QTest::newRow("two x-adjacent rects 3") << QSize(50, 50) << region;
1907 rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100);
1908 region.setRects(rects.constData(), rects.size());
1909 QTest::newRow("two x-adjacent rects 4") << QSize(101, 101) << region;
1911 region = QRegion(QRect(0, 0, 200, 200), QRegion::Ellipse);
1913 QTest::newRow("ellipse") << QSize(190, 200) << region;
1915 region ^= QRect(50, 50, 50, 50);
1916 QTest::newRow("ellipse 2") << QSize(200, 200) << region;
1919 void tst_QPainter::setEqualClipRegionAndPath()
1921 QFETCH(QSize, deviceSize);
1922 QFETCH(QRegion, region);
1925 path.addRegion(region);
1927 QImage img1(deviceSize.width(), deviceSize.height(),
1928 QImage::Format_ARGB32);
1929 QImage img2(deviceSize.width(), deviceSize.height(),
1930 QImage::Format_ARGB32);
1931 img1.fill(0x12345678);
1932 img2.fill(0x12345678);
1936 p.setClipRegion(region);
1937 p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red));
1941 p.setClipPath(path);
1942 p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red));
1945 QCOMPARE(img1, img2);
1949 img1.fill(0x12345678);
1950 img2.fill(0x12345678);
1955 p.setClipRegion(region);
1956 p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red));
1961 p.setClipPath(path);
1962 p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red));
1965 QCOMPARE(img1, img2);
1968 img1.fill(0x12345678);
1969 img2.fill(0x12345678);
1971 // simple intersectclip
1972 img1.fill(0x12345678);
1973 img2.fill(0x12345678);
1976 p.setClipRegion(region);
1977 p.setClipRegion(region, Qt::IntersectClip);
1978 p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red));
1982 p.setClipPath(path);
1983 p.setClipPath(path, Qt::IntersectClip);
1984 p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red));
1986 QCOMPARE(img1, img2);
1988 img1.fill(0x12345678);
1989 img2.fill(0x12345678);
1992 p.setClipPath(path);
1993 p.setClipRegion(region, Qt::IntersectClip);
1994 p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red));
1998 p.setClipRegion(region);
1999 p.setClipPath(path, Qt::IntersectClip);
2000 p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red));
2002 QCOMPARE(img1, img2);
2006 void tst_QPainter::clippedFillPath_data()
2008 QTest::addColumn<QSize>("imageSize");
2009 QTest::addColumn<QPainterPath>("path");
2010 QTest::addColumn<QRect>("clipRect");
2011 QTest::addColumn<QBrush>("brush");
2012 QTest::addColumn<QPen>("pen");
2014 QLinearGradient gradient(QPoint(0, 0), QPoint(100, 100));
2015 gradient.setColorAt(0, Qt::red);
2016 gradient.setColorAt(1, Qt::blue);
2019 QPen pen2(QColor(223, 223, 0, 223));
2023 path.addRect(QRect(15, 15, 50, 50));
2024 QTest::newRow("simple rect 0") << QSize(100, 100) << path
2025 << QRect(15, 15, 49, 49)
2026 << QBrush(Qt::NoBrush)
2028 QTest::newRow("simple rect 1") << QSize(100, 100) << path
2029 << QRect(15, 15, 50, 50)
2030 << QBrush(Qt::NoBrush)
2032 QTest::newRow("simple rect 2") << QSize(100, 100) << path
2033 << QRect(15, 15, 51, 51)
2034 << QBrush(Qt::NoBrush)
2036 QTest::newRow("simple rect 3") << QSize(100, 100) << path
2037 << QRect(15, 15, 51, 51)
2038 << QBrush(QColor(Qt::blue))
2040 QTest::newRow("simple rect 4") << QSize(100, 100) << path
2041 << QRect(15, 15, 51, 51)
2045 path = QPainterPath();
2046 path.addEllipse(QRect(15, 15, 50, 50));
2047 QTest::newRow("ellipse 0") << QSize(100, 100) << path
2048 << QRect(15, 15, 49, 49)
2049 << QBrush(Qt::NoBrush)
2051 QTest::newRow("ellipse 1") << QSize(100, 100) << path
2052 << QRect(15, 15, 50, 50)
2053 << QBrush(Qt::NoBrush)
2055 QTest::newRow("ellipse 2") << QSize(100, 100) << path
2056 << QRect(15, 15, 51, 51)
2057 << QBrush(Qt::NoBrush)
2059 QTest::newRow("ellipse 3") << QSize(100, 100) << path
2060 << QRect(15, 15, 51, 51)
2061 << QBrush(QColor(Qt::blue))
2063 QTest::newRow("ellipse 4") << QSize(100, 100) << path
2064 << QRect(15, 15, 51, 51)
2068 path = QPainterPath();
2069 path.addRoundRect(QRect(15, 15, 50, 50), 20);
2070 QTest::newRow("round rect 0") << QSize(100, 100) << path
2071 << QRect(15, 15, 49, 49)
2072 << QBrush(Qt::NoBrush)
2074 QTest::newRow("round rect 1") << QSize(100, 100) << path
2075 << QRect(15, 15, 50, 50)
2076 << QBrush(Qt::NoBrush)
2078 QTest::newRow("round rect 2") << QSize(100, 100) << path
2079 << QRect(15, 15, 51, 51)
2080 << QBrush(Qt::NoBrush)
2082 QTest::newRow("round rect 3") << QSize(100, 100) << path
2083 << QRect(15, 15, 51, 51)
2084 << QBrush(QColor(Qt::blue))
2086 QTest::newRow("round rect 4") << QSize(100, 100) << path
2087 << QRect(15, 15, 51, 51)
2091 path = QPainterPath();
2092 path.moveTo(15, 50);
2093 path.cubicTo(40, 50, 40, 15, 65, 50);
2094 path.lineTo(15, 50);
2095 QTest::newRow("cubic 0") << QSize(100, 100) << path
2096 << QRect(15, 15, 49, 49)
2097 << QBrush(Qt::NoBrush)
2099 QTest::newRow("cubic 1") << QSize(100, 100) << path
2100 << QRect(15, 15, 50, 50)
2101 << QBrush(Qt::NoBrush)
2103 QTest::newRow("cubic 2") << QSize(100, 100) << path
2104 << QRect(15, 15, 51, 51)
2105 << QBrush(Qt::NoBrush)
2107 QTest::newRow("cubic 3") << QSize(100, 100) << path
2108 << QRect(15, 15, 51, 51)
2109 << QBrush(QColor(Qt::blue))
2111 QTest::newRow("cubic 4") << QSize(100, 100) << path
2112 << QRect(15, 15, 51, 51)
2117 void tst_QPainter::clippedFillPath()
2119 QFETCH(QSize, imageSize);
2120 QFETCH(QPainterPath, path);
2121 QFETCH(QRect, clipRect);
2122 QPainterPath clipPath;
2123 clipPath.addRect(clipRect);
2124 QFETCH(QBrush, brush);
2127 const int width = imageSize.width();
2128 const int height = imageSize.height();
2130 QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied);
2131 clippedRect.fill(0x12345678);
2133 QPainter painter(&clippedRect);
2134 painter.setPen(pen);
2135 painter.setBrush(brush);
2136 painter.setClipRect(clipRect);
2137 painter.drawPath(path);
2140 QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied);
2141 clippedPath.fill(0x12345678);
2143 QPainter painter(&clippedPath);
2144 painter.setPen(pen);
2145 painter.setBrush(brush);
2146 painter.setClipPath(clipPath);
2147 painter.drawPath(path);
2150 QCOMPARE(clippedRect, clippedPath);
2152 // repeat with antialiasing
2154 clippedRect.fill(0x12345678);
2156 QPainter painter(&clippedRect);
2157 painter.setRenderHint(QPainter::Antialiasing);
2158 painter.setPen(pen);
2159 painter.setBrush(brush);
2160 painter.setClipRect(clipRect);
2161 painter.drawPath(path);
2164 clippedPath.fill(0x12345678);
2166 QPainter painter(&clippedPath);
2167 painter.setRenderHint(QPainter::Antialiasing);
2168 painter.setPen(pen);
2169 painter.setBrush(brush);
2170 painter.setClipPath(clipPath);
2171 painter.drawPath(path);
2174 QCOMPARE(clippedRect, clippedPath);
2177 void tst_QPainter::clippedLines_data()
2179 QTest::addColumn<QSize>("imageSize");
2180 QTest::addColumn<QLineF>("line");
2181 QTest::addColumn<QRect>("clipRect");
2182 QTest::addColumn<QPen>("pen");
2184 QPen pen2(QColor(223, 223, 0, 223));
2187 QVector<QLineF> lines;
2188 lines << QLineF(15, 15, 65, 65)
2189 << QLineF(14, 14, 66, 66)
2190 << QLineF(16, 16, 64, 64)
2191 << QLineF(65, 65, 15, 15)
2192 << QLineF(66, 66, 14, 14)
2193 << QLineF(64, 64, 14, 14)
2194 << QLineF(15, 50, 15, 64)
2195 << QLineF(15, 50, 15, 65)
2196 << QLineF(15, 50, 15, 66)
2197 << QLineF(15, 50, 64, 50)
2198 << QLineF(15, 50, 65, 50)
2199 << QLineF(15, 50, 66, 50);
2201 foreach (QLineF line, lines) {
2202 QString desc = QString("line (%1, %2, %3, %4) %5").arg(line.x1())
2203 .arg(line.y1()).arg(line.x2()).arg(line.y2());
2204 QTest::newRow(qPrintable(desc.arg(0))) << QSize(100, 100) << line
2205 << QRect(15, 15, 49, 49)
2207 QTest::newRow(qPrintable(desc.arg(1))) << QSize(100, 100) << line
2208 << QRect(15, 15, 50, 50)
2210 QTest::newRow(qPrintable(desc.arg(2))) << QSize(100, 100) << line
2211 << QRect(15, 15, 51, 51)
2213 QTest::newRow(qPrintable(desc.arg(3))) << QSize(100, 100) << line
2214 << QRect(15, 15, 51, 51)
2216 QTest::newRow(qPrintable(desc.arg(4))) << QSize(100, 100) << line
2217 << QRect(15, 15, 51, 51)
2222 void tst_QPainter::clippedLines()
2224 QFETCH(QSize, imageSize);
2225 QFETCH(QLineF, line);
2226 QFETCH(QRect, clipRect);
2227 QPainterPath clipPath;
2228 clipPath.addRect(clipRect);
2231 const int width = imageSize.width();
2232 const int height = imageSize.height();
2234 QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied);
2235 clippedRect.fill(0x12345678);
2237 QPainter painter(&clippedRect);
2238 painter.setPen(pen);
2239 painter.setClipRect(clipRect);
2240 painter.drawLine(line);
2241 painter.drawLine(line.toLine());
2244 QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied);
2245 clippedPath.fill(0x12345678);
2247 QPainter painter(&clippedPath);
2248 painter.setPen(pen);
2249 painter.setClipPath(clipPath);
2250 painter.drawLine(line);
2251 painter.drawLine(line.toLine());
2254 QCOMPARE(clippedRect, clippedPath);
2256 // repeat with antialiasing
2257 clippedRect.fill(0x12345678);
2259 QPainter painter(&clippedRect);
2260 painter.setRenderHint(QPainter::Antialiasing);
2261 painter.setPen(pen);
2262 painter.setClipRect(clipRect);
2263 painter.drawLine(line);
2264 painter.drawLine(line.toLine());
2267 clippedPath.fill(0x12345678);
2269 QPainter painter(&clippedPath);
2270 painter.setRenderHint(QPainter::Antialiasing);
2271 painter.setPen(pen);
2272 painter.setClipPath(clipPath);
2273 painter.drawLine(line);
2274 painter.drawLine(line.toLine());
2277 QCOMPARE(clippedRect, clippedPath);
2280 void tst_QPainter::clippedPolygon_data()
2282 clippedFillPath_data();
2285 void tst_QPainter::clippedPolygon()
2287 QFETCH(QSize, imageSize);
2288 QFETCH(QPainterPath, path);
2289 QPolygonF polygon = path.toFillPolygon();
2290 QFETCH(QRect, clipRect);
2291 QPainterPath clipPath;
2292 clipPath.addRect(clipRect);
2294 QFETCH(QBrush, brush);
2296 const int width = imageSize.width();
2297 const int height = imageSize.height();
2299 QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied);
2300 clippedRect.fill(0x12345678);
2302 QPainter painter(&clippedRect);
2303 painter.setPen(pen);
2304 painter.setBrush(brush);
2305 painter.setClipRect(clipRect);
2306 painter.drawPolygon(polygon);
2307 painter.drawPolygon(polygon.toPolygon());
2310 QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied);
2311 clippedPath.fill(0x12345678);
2313 QPainter painter(&clippedPath);
2314 painter.setPen(pen);
2315 painter.setBrush(brush);
2316 painter.setClipRect(clipRect);
2317 painter.drawPolygon(polygon);
2318 painter.drawPolygon(polygon.toPolygon());
2321 QCOMPARE(clippedRect, clippedPath);
2323 // repeat with antialiasing
2325 clippedRect.fill(0x12345678);
2327 QPainter painter(&clippedRect);
2328 painter.setRenderHint(QPainter::Antialiasing);
2329 painter.setPen(pen);
2330 painter.setBrush(brush);
2331 painter.setClipRect(clipRect);
2332 painter.drawPolygon(polygon);
2333 painter.drawPolygon(polygon.toPolygon());
2336 clippedPath.fill(0x12345678);
2338 QPainter painter(&clippedPath);
2339 painter.setRenderHint(QPainter::Antialiasing);
2340 painter.setPen(pen);
2341 painter.setBrush(brush);
2342 painter.setClipRect(clipRect);
2343 painter.drawPolygon(polygon);
2344 painter.drawPolygon(polygon.toPolygon());
2347 QCOMPARE(clippedRect, clippedPath);
2350 // this just draws some text that should be clipped in the raster
2352 void tst_QPainter::clippedText()
2354 for (char ch = 'A'; ch < 'Z'; ++ch) {
2358 QFontMetrics metrics(f);
2359 QRect textRect = metrics.boundingRect(QChar(ch));
2361 if (textRect.width() <= 8)
2363 if (textRect.height() <= 8)
2366 QRect imageRect = textRect.adjusted(4, 4, -4, -4);
2368 QImage image(imageRect.size(), QImage::Format_ARGB32_Premultiplied);
2370 image.fill(qRgba(255, 255, 255, 255));
2372 QPainter painter(&image);
2374 painter.setPen(Qt::black);
2376 painter.drawText(0, 0, QChar(ch));
2379 image.fill(qRgba(255, 255, 255, 255));
2381 QPainter painter(&image);
2383 painter.setPen(Qt::black);
2385 painter.drawText(-imageRect.topLeft(), QChar(ch));
2388 bool foundPixel = false;
2389 for (int x = 0; x < image.width(); ++x)
2390 for (int y = 0; y < image.height(); ++y)
2391 if (image.pixel(x, y) != 0)
2393 // can't QVERIFY(foundPixel) as sometimes all pixels are clipped
2394 // away. For example for 'O'
2395 // just call /some/ function to prevent the compiler from optimizing
2397 QString::number(foundPixel);
2399 //image.save(QString("debug") + ch + ".xpm");
2402 QVERIFY(true); // reached, don't trigger any valgrind errors
2405 void tst_QPainter::setOpacity_data()
2407 QTest::addColumn<QImage::Format>("destFormat");
2408 QTest::addColumn<QImage::Format>("srcFormat");
2410 QTest::newRow("ARGB32P on ARGB32P") << QImage::Format_ARGB32_Premultiplied
2411 << QImage::Format_ARGB32_Premultiplied;
2413 QTest::newRow("ARGB32 on ARGB32") << QImage::Format_ARGB32
2414 << QImage::Format_ARGB32;
2416 QTest::newRow("RGB32 on RGB32") << QImage::Format_RGB32
2417 << QImage::Format_RGB32;
2419 QTest::newRow("RGB16 on RGB16") << QImage::Format_RGB16
2420 << QImage::Format_RGB16;
2422 QTest::newRow("ARGB8565_Premultiplied on ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied
2423 << QImage::Format_ARGB8565_Premultiplied;
2425 QTest::newRow("RGB555 on RGB555") << QImage::Format_RGB555
2426 << QImage::Format_RGB555;
2428 QTest::newRow("RGB666 on RGB666") << QImage::Format_RGB666
2429 << QImage::Format_RGB666;
2431 QTest::newRow("ARGB8555_Premultiplied on ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied
2432 << QImage::Format_ARGB8555_Premultiplied;
2434 QTest::newRow("RGB888 on RGB888") << QImage::Format_RGB888
2435 << QImage::Format_RGB888;
2437 QTest::newRow("RGB32 on RGB16") << QImage::Format_RGB16
2438 << QImage::Format_RGB32;
2440 QTest::newRow("RGB32 on ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied
2441 << QImage::Format_RGB32;
2443 QTest::newRow("RGB32 on RGB666") << QImage::Format_RGB666
2444 << QImage::Format_RGB32;
2446 QTest::newRow("RGB32 on RGB555") << QImage::Format_RGB555
2447 << QImage::Format_RGB32;
2449 QTest::newRow("RGB32 on ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied
2450 << QImage::Format_RGB32;
2452 QTest::newRow("RGB32 on RGB888") << QImage::Format_RGB888
2453 << QImage::Format_RGB32;
2455 QTest::newRow("RGB16 on RGB32") << QImage::Format_RGB32
2456 << QImage::Format_RGB16;
2458 QTest::newRow("ARGB8565_Premultiplied on RGB32") << QImage::Format_RGB32
2459 << QImage::Format_ARGB8565_Premultiplied;
2461 QTest::newRow("RGB666 on RGB32") << QImage::Format_RGB32
2462 << QImage::Format_RGB666;
2464 QTest::newRow("RGB555 on RGB32") << QImage::Format_RGB32
2465 << QImage::Format_RGB555;
2467 QTest::newRow("ARGB8555_Premultiplied on RGB32") << QImage::Format_RGB32
2468 << QImage::Format_ARGB8555_Premultiplied;
2470 QTest::newRow("RGB888 on RGB32") << QImage::Format_RGB32
2471 << QImage::Format_RGB888;
2473 QTest::newRow("RGB555 on RGB888") << QImage::Format_RGB888
2474 << QImage::Format_RGB555;
2476 QTest::newRow("RGB666 on RGB888") << QImage::Format_RGB888
2477 << QImage::Format_RGB666;
2479 QTest::newRow("RGB444 on RGB444") << QImage::Format_RGB444
2480 << QImage::Format_RGB444;
2483 void tst_QPainter::setOpacity()
2485 QFETCH(QImage::Format, destFormat);
2486 QFETCH(QImage::Format, srcFormat);
2488 const QSize imageSize(12, 12);
2489 const QRect imageRect(QPoint(0, 0), imageSize);
2490 QColor destColor = Qt::black;
2491 QColor srcColor = Qt::white;
2493 QImage dest(imageSize, destFormat);
2494 QImage src(imageSize, srcFormat);
2498 p.fillRect(imageRect, destColor);
2502 p.fillRect(imageRect, srcColor);
2507 p.drawImage(imageRect, src, imageRect);
2510 QImage actual = dest.convertToFormat(QImage::Format_RGB32);
2512 for (int y = 0; y < actual.height(); ++y) {
2513 QRgb *p = (QRgb *)actual.scanLine(y);
2514 for (int x = 0; x < actual.width(); ++x) {
2515 QVERIFY(qAbs(qRed(p[x]) - 127) <= 0xf);
2516 QVERIFY(qAbs(qGreen(p[x]) - 127) <= 0xf);
2517 QVERIFY(qAbs(qBlue(p[x]) - 127) <= 0xf);
2522 void tst_QPainter::drawhelper_blend_untransformed_data()
2527 void tst_QPainter::drawhelper_blend_untransformed()
2529 QFETCH(QImage::Format, destFormat);
2530 QFETCH(QImage::Format, srcFormat);
2532 const int size = 128;
2533 const QSize imageSize(size, size);
2534 const QRect paintRect(1, 0, size - 2, size); // needs alignment and tailing
2536 QColor destColor(127, 127, 127);
2537 QColor srcColor(Qt::white);
2539 QImage dest(imageSize, destFormat);
2540 QImage src(imageSize, srcFormat);
2544 p.fillRect(paintRect, srcColor);
2547 QList<qreal> opacities = (QList<qreal>() << 0.0 << 0.1 << 0.01 << 0.4
2548 << 0.5 << 0.6 << 0.9 << 1.0);
2549 foreach (qreal opacity, opacities) {
2551 p.fillRect(paintRect, destColor);
2553 p.setOpacity(opacity);
2554 p.drawImage(paintRect, src, paintRect);
2557 // sanity check: make sure all pixels are equal
2558 QImage expected(size - 2, size, destFormat);
2560 p.fillRect(0, 0, expected.width(), expected.height(),
2561 QColor(dest.pixel(1, 0)));
2564 const QImage subDest(dest.bits() + dest.depth() / 8,
2565 dest.width() - 2, dest.height(),
2566 dest.bytesPerLine(), dest.format());
2568 if (dest.format() == QImage::Format_ARGB8565_Premultiplied ||
2569 dest.format() == QImage::Format_ARGB8555_Premultiplied) {
2570 // Test skipped due to rounding errors...
2573 QCOMPARE(subDest, expected);
2577 void tst_QPainter::drawhelper_blend_tiled_untransformed_data()
2582 void tst_QPainter::drawhelper_blend_tiled_untransformed()
2584 QFETCH(QImage::Format, destFormat);
2585 QFETCH(QImage::Format, srcFormat);
2587 const int size = 128;
2588 const QSize imageSize(size, size);
2589 const QRect paintRect(1, 0, size - 2, size); // needs alignment and tailing
2591 QColor destColor(127, 127, 127);
2592 QColor srcColor(Qt::white);
2594 QImage dest(imageSize, destFormat);
2595 QImage src(imageSize / 2, srcFormat);
2599 p.fillRect(QRect(QPoint(0, 0), imageSize/ 2), srcColor);
2602 const QBrush brush(src);
2604 QList<qreal> opacities = (QList<qreal>() << 0.0 << 0.1 << 0.01 << 0.4
2605 << 0.5 << 0.6 << 0.9 << 1.0);
2606 foreach (qreal opacity, opacities) {
2608 p.fillRect(paintRect, destColor);
2610 p.setOpacity(opacity);
2611 p.fillRect(paintRect, brush);
2614 // sanity check: make sure all pixels are equal
2615 QImage expected(size - 2, size, destFormat);
2617 p.fillRect(0, 0, expected.width(), expected.height(),
2618 QColor(dest.pixel(1, 0)));
2621 const QImage subDest(dest.bits() + dest.depth() / 8,
2622 dest.width() - 2, dest.height(),
2623 dest.bytesPerLine(), dest.format());
2625 if (dest.format() == QImage::Format_ARGB8565_Premultiplied ||
2626 dest.format() == QImage::Format_ARGB8555_Premultiplied) {
2627 // Skipping test due to rounding errors. Test needs rewrite
2630 QCOMPARE(subDest, expected);
2634 static QPaintEngine::PaintEngineFeatures no_porter_duff()
2636 QPaintEngine::PaintEngineFeatures features = QPaintEngine::AllFeatures;
2637 return features & ~QPaintEngine::PorterDuff;
2640 class DummyPaintEngine : public QPaintEngine, public QPaintDevice
2643 DummyPaintEngine() : QPaintEngine(no_porter_duff()) {}
2644 virtual bool begin(QPaintDevice *) { return true; }
2645 virtual bool end() { return true; }
2647 virtual void updateState(const QPaintEngineState &) {}
2648 virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {}
2650 virtual Type type() const { return User; }
2652 virtual QPaintEngine *paintEngine() const { return (QPaintEngine *)this; }
2654 virtual int metric(PaintDeviceMetric metric) const { Q_UNUSED(metric); return 0; };
2657 static bool success;
2659 void porterDuff_warningChecker(QtMsgType type, const char *msg)
2661 if (type == QtWarningMsg && msg == QLatin1String("QPainter::setCompositionMode: PorterDuff modes not supported on device"))
2665 void tst_QPainter::porterDuff_warning()
2667 QtMsgHandler old = qInstallMsgHandler(porterDuff_warningChecker);
2668 DummyPaintEngine dummy;
2672 p.setCompositionMode(QPainter::CompositionMode_Source);
2676 p.setCompositionMode(QPainter::CompositionMode_SourceOver);
2680 p.setCompositionMode(QPainter::CompositionMode_DestinationOver);
2683 QVERIFY(qInstallMsgHandler(old) == porterDuff_warningChecker);
2689 inline quint24(quint32 v)
2692 data[1] = qGreen(v);
2696 inline operator quint32 ()
2698 return qRgb(data[2], data[1], data[0]);
2701 inline bool operator==(const quint24 &v) const {
2702 return (data[0] == v.data[0] && data[1] == v.data[1] && data[2] == v.data[2]);
2708 void tst_QPainter::drawhelper_blend_color()
2710 QImage dest(32, 32, QImage::Format_ARGB8555_Premultiplied);
2711 dest.fill(0xff000000);
2715 p.fillRect(0, 0, dest.width(), dest.height(), QColor(255, 0, 0, 127));
2718 QImage expected(32, 32, QImage::Format_ARGB8555_Premultiplied);
2719 expected.fill(0xff3c007f);
2721 QCOMPARE(dest.pixel(1, 1), expected.pixel(1, 1));
2722 QCOMPARE(dest, expected);
2725 class ViewportTestWidget : public QWidget
2728 ViewportTestWidget(QWidget *parent = 0) : QWidget(parent), hasPainted(false) {}
2729 QSize sizeHint() const {
2730 return QSize(100, 100);
2737 void paintEvent(QPaintEvent *) {
2740 viewport = p.viewport();
2744 void tst_QPainter::childWidgetViewport()
2747 parent.setAutoFillBackground(true);
2748 parent.resize(200, 200);
2749 ViewportTestWidget child(&parent);
2750 child.setAutoFillBackground(true);
2753 qApp->processEvents();
2755 if (child.hasPainted) {
2756 QCOMPARE(child.viewport, QRect(QPoint(0, 0), child.sizeHint()));
2758 qWarning("Failed to ensure that paintEvent has been run. Could not run test.");
2762 void tst_QPainter::fillRect_objectBoundingModeGradient()
2764 QImage a(10, 10, QImage::Format_ARGB32_Premultiplied);
2768 QLinearGradient g(QPoint(0, 0), QPoint(0, 1));
2769 g.setColorAt(0, Qt::red);
2770 g.setColorAt(1, Qt::blue);
2771 g.setCoordinateMode(QGradient::ObjectBoundingMode);
2774 p.fillRect(QRect(0, 0, a.width(), a.height()), g);
2778 path.addRect(0, 0, a.width(), a.height());
2781 p.fillPath(path, g);
2787 void tst_QPainter::fillRect_stretchToDeviceMode()
2789 QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
2791 QLinearGradient g(QPoint(0, 0), QPoint(0, 1));
2792 g.setCoordinateMode(QGradient::StretchToDeviceMode);
2795 p.fillRect(img.rect(), g);
2798 for (int i = 1; i < img.height(); ++i)
2799 QVERIFY(img.pixel(0, i) != img.pixel(0, i-1));
2802 void tst_QPainter::monoImages()
2804 Qt::GlobalColor colorPairs[][2] = {
2805 { Qt::white, Qt::black },
2806 { Qt::color0, Qt::color1 },
2807 { Qt::red, Qt::blue }
2810 const int numColorPairs = sizeof(colorPairs) / sizeof(QRgb[2]);
2812 QImage transparent(2, 2, QImage::Format_ARGB32_Premultiplied);
2813 transparent.fill(0x0);
2815 for (int i = 1; i < QImage::NImageFormats; ++i) {
2816 for (int j = 0; j < numColorPairs; ++j) {
2817 const QImage::Format format = QImage::Format(i);
2818 if (format == QImage::Format_Indexed8)
2821 QImage img(2, 2, format);
2823 if (img.colorCount() > 0) {
2824 img.setColor(0, QColor(colorPairs[j][0]).rgba());
2825 img.setColor(1, QColor(colorPairs[j][1]).rgba());
2830 p.fillRect(0, 0, 2, 2, colorPairs[j][0]);
2831 p.fillRect(0, 0, 1, 1, colorPairs[j][1]);
2832 p.fillRect(1, 1, 1, 1, colorPairs[j][1]);
2835 QImage original = img;
2838 p.drawImage(0, 0, transparent);
2841 // drawing a transparent image on top of another image
2842 // should not change the image
2843 QCOMPARE(original, img);
2845 if (img.colorCount() == 0)
2848 for (int k = 0; k < 2; ++k) {
2850 p.fillRect(0, 0, 2, 2, colorPairs[j][k]);
2853 QImage argb32p(2, 2, QImage::Format_ARGB32_Premultiplied);
2855 p.fillRect(0, 0, 2, 2, colorPairs[j][k]);
2858 QCOMPARE(argb32p, img.convertToFormat(argb32p.format()));
2860 // drawing argb32p image on mono image
2862 p.drawImage(0, 0, argb32p);
2865 QCOMPARE(argb32p, img.convertToFormat(argb32p.format()));
2867 // drawing mono image on argb32p image
2869 p.drawImage(0, 0, img);
2872 QCOMPARE(argb32p, img.convertToFormat(argb32p.format()));
2878 #if !defined(Q_OS_IRIX) && !defined(Q_OS_AIX) && !defined(Q_CC_MSVC) && !defined(Q_OS_SOLARIS)
2881 static const QString fpeExceptionString(int exception)
2884 if (exception & FE_INEXACT)
2885 return QLatin1String("Inexact result");
2887 if (exception & FE_UNDERFLOW)
2888 return QLatin1String("Underflow");
2889 if (exception & FE_OVERFLOW)
2890 return QLatin1String("Overflow");
2891 if (exception & FE_DIVBYZERO)
2892 return QLatin1String("Divide by zero");
2893 if (exception & FE_INVALID)
2894 return QLatin1String("Invalid operation");
2895 return QLatin1String("No exception");
2898 class FpExceptionChecker
2901 FpExceptionChecker(int exceptionMask)
2902 : m_exceptionMask(exceptionMask)
2904 feclearexcept(m_exceptionMask);
2907 ~FpExceptionChecker()
2909 const int exceptions = fetestexcept(m_exceptionMask);
2910 QVERIFY2(!exceptions, qPrintable(QLatin1String("Floating point exception: ") + fpeExceptionString(exceptions)));
2914 int m_exceptionMask;
2917 void fpe_rasterizeLine_task232012()
2919 FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
2920 QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
2924 p.setBrush(Qt::black);
2925 p.drawRect(QRectF(0, 0, 5, 0));
2926 p.drawRect(QRectF(0, 0, 0, 5));
2929 void fpe_pixmapTransform()
2931 FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
2933 QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
2937 const qreal scaleFactor = 0.001;
2938 const int translateDistance = 1000000;
2941 p.setBrush(QBrush(Qt::red,Qt::Dense6Pattern));
2943 for (int i = 0; i < 2; ++i) {
2944 p.setRenderHint(QPainter::SmoothPixmapTransform, i);
2948 p.translate(translateDistance, 0);
2949 p.drawRect(-translateDistance, 0, 100, 100);
2952 p.scale(scaleFactor, scaleFactor);
2953 p.drawRect(QRectF(0, 0, 1 / scaleFactor, 1 / scaleFactor));
2957 void fpe_zeroLengthLines()
2959 FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
2961 QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
2965 p.setPen(QPen(Qt::black, 3));
2966 p.drawLine(64, 64, 64, 64);
2969 void fpe_divByZero()
2971 FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
2973 QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
2977 p.setRenderHint(QPainter::Antialiasing);
2979 p.drawRect(QRectF(10, 10, 100, 0));
2980 p.drawRect(QRectF(10, 10, 0, 100));
2982 p.drawRect(QRect(10, 10, 100, 0));
2983 p.drawRect(QRect(10, 10, 0, 100));
2985 p.fillRect(QRectF(10, 10, 100, 0), Qt::black);
2986 p.fillRect(QRectF(10, 10, 0, 100), Qt::black);
2988 p.fillRect(QRect(10, 10, 100, 0), Qt::black);
2989 p.fillRect(QRect(10, 10, 0, 100), Qt::black);
2992 void fpe_steepSlopes()
2994 FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
2996 QImage img(1024, 1024, QImage::Format_ARGB32_Premultiplied);
2998 QFETCH(QTransform, transform);
2999 QFETCH(QLineF, line);
3000 QFETCH(bool, antialiased);
3004 p.setPen(QPen(Qt::black, 1));
3005 p.setRenderHint(QPainter::Antialiasing, antialiased);
3006 p.setTransform(transform);
3011 void fpe_radialGradients()
3013 FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
3015 QImage img(21, 21, QImage::Format_ARGB32_Premultiplied);
3018 double m = img.width() * 0.5;
3021 p.setRenderHints(QPainter::Antialiasing);
3022 p.setPen(Qt::NoPen);
3023 p.setBrush(QRadialGradient(m, m, m));
3024 p.drawEllipse(img.rect());
3027 #define FPE_TEST(x) \
3028 void tst_QPainter::x() \
3033 #define FPE_TEST(x) \
3034 void tst_QPainter::x() \
3036 QSKIP("Floating point exception checking (fenv.h) not available"); \
3040 FPE_TEST(fpe_rasterizeLine_task232012)
3041 FPE_TEST(fpe_pixmapTransform)
3042 FPE_TEST(fpe_zeroLengthLines)
3043 FPE_TEST(fpe_divByZero)
3044 FPE_TEST(fpe_steepSlopes)
3045 FPE_TEST(fpe_radialGradients)
3047 void tst_QPainter::fpe_steepSlopes_data()
3049 QTest::addColumn<QTransform>("transform");
3050 QTest::addColumn<QLineF>("line");
3051 QTest::addColumn<bool>("antialiased");
3054 const qreal dsin = 0.000014946676875461832484392500630665523431162000633776187896728515625;
3055 const qreal dcos = 0.9999999998882984630910186751862056553363800048828125;
3057 const QTransform transform = QTransform(QMatrix(dcos, dsin, -dsin, dcos, 64, 64));
3058 const QLineF line(2, 2, 2, 6);
3060 QTest::newRow("task 207147 aa") << transform << line << true;
3061 QTest::newRow("task 207147 no aa") << transform << line << false;
3065 QTransform transform;
3066 transform.rotate(0.0000001);
3067 const QLineF line(5, 5, 10, 5);
3069 QTest::newRow("task 166702 aa") << transform << line << true;
3070 QTest::newRow("task 166702 no aa") << transform << line << false;
3074 const QTransform transform;
3075 const QLineF line(2.5, 2.5, 2.5 + 1/256., 60000.5);
3077 QTest::newRow("steep line aa") << transform << line << true;
3078 QTest::newRow("steep line no aa") << transform << line << false;
3082 const QTransform transform;
3083 const QLineF line(2.5, 2.5, 2.5 + 1/256., 1024);
3085 QTest::newRow("steep line 2 aa") << transform << line << true;
3086 QTest::newRow("steep line 2 no aa") << transform << line << false;
3090 const QTransform transform;
3091 const QLineF line(2.5, 2.5, 2.5 + 1/64., 1024);
3093 QTest::newRow("steep line 3 aa") << transform << line << true;
3094 QTest::newRow("steep line 3 no aa") << transform << line << false;
3100 return rand() / (RAND_MAX + 1.0);
3103 QPointF randInRect(const QRectF &rect)
3105 const qreal x = rect.left() + rect.width() * randf();
3106 const qreal y = rect.top() + rect.height() * randf();
3108 return QPointF(x, y);
3111 void tst_QPainter::rasterizer_asserts()
3113 QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
3115 QRectF middle(QPointF(0, 0), img.size());
3116 QRectF left = middle.translated(-middle.width(), 0);
3117 QRectF right = middle.translated(middle.width(), 0);
3120 img.fill(Qt::white);
3121 p.setCompositionMode(QPainter::CompositionMode_Destination);
3122 for (int i = 0; i < 100000; ++i) {
3124 path.moveTo(randInRect(middle));
3125 path.lineTo(randInRect(left));
3126 path.lineTo(randInRect(right));
3128 p.fillPath(path, Qt::black);
3132 void tst_QPainter::rasterizer_negativeCoords()
3134 QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
3137 QImage original = img;
3141 p.fillRect(0, 0, 70, 50, Qt::black);
3143 // image should not have changed
3144 QCOMPARE(img.pixel(0, 0), 0x0U);
3145 QCOMPARE(img, original);
3148 void tst_QPainter::blendOverFlow_data()
3150 QTest::addColumn<QImage::Format>("format");
3151 QTest::addColumn<int>("width");
3152 QTest::addColumn<int>("height");
3154 QImage::Format format = QImage::Format_ARGB8555_Premultiplied;
3155 QTest::newRow("555,1,1") << format << 1 << 1;
3156 QTest::newRow("555,2,2") << format << 2 << 2;
3157 QTest::newRow("555,10,10") << format << 10 << 10;
3159 format = QImage::Format_ARGB8565_Premultiplied;
3160 QTest::newRow("565,1,1") << format << 1 << 1;
3161 QTest::newRow("565,2,2") << format << 2 << 2;
3162 QTest::newRow("565,10,10") << format << 10 << 10;
3165 void tst_QPainter::blendOverFlow()
3167 QFETCH(QImage::Format, format);
3169 QFETCH(int, height);
3171 QImage dest(width, height, format);
3172 QImage src(width, height, format);
3176 p.fillRect(0, 0, width, height, Qt::green);
3178 QImage expected = dest;
3182 p.setCompositionMode(QPainter::CompositionMode_Source);
3183 p.fillRect(0, 0, width, height, QColor(0, 255, 0, 6));
3188 p.drawImage(0, 0, src);
3191 QCOMPARE(dest.pixel(0, 0), expected.pixel(0, 0));
3192 QCOMPARE(dest, expected);
3195 void tst_QPainter::largeImagePainting_data()
3197 QTest::addColumn<int>("width");
3198 QTest::addColumn<int>("height");
3199 QTest::addColumn<bool>("antialiased");
3201 QTest::newRow("tall") << 1 << 32767 << false;
3202 QTest::newRow("tall aa") << 1 << 32767 << true;
3203 QTest::newRow("wide") << 32767 << 1 << false;
3204 QTest::newRow("wide aa") << 32767 << 1 << true;
3207 void tst_QPainter::largeImagePainting()
3210 path.addRect(0, 0, 1, 1);
3211 path.addRect(2, 0, 1, 1);
3212 path.addRect(0, 2, 1, 1);
3215 QFETCH(int, height);
3216 QFETCH(bool, antialiased);
3218 QImage img(width, height, QImage::Format_ARGB32_Premultiplied);
3222 p.setPen(Qt::NoPen);
3223 p.setBrush(Qt::white);
3225 p.setRenderHint(QPainter::Antialiasing, antialiased);
3227 for (int i = 0; i < img.width(); i += 4) {
3234 for (int i = 4; i < img.height(); i += 4) {
3239 for (int i = 0; i < img.width(); ++i) {
3241 QCOMPARE(img.pixel(i, 0), 0x0U);
3243 QCOMPARE(img.pixel(i, 0), 0xffffffffU);
3246 for (int i = 1; i < img.height(); ++i) {
3248 QCOMPARE(img.pixel(0, i), 0x0U);
3250 QCOMPARE(img.pixel(0, i), 0xffffffffU);
3254 void tst_QPainter::imageScaling_task206785()
3256 QImage src(32, 2, QImage::Format_ARGB32_Premultiplied);
3257 src.fill(0xffffffff);
3259 QImage dst(128, 128, QImage::Format_ARGB32_Premultiplied);
3261 QImage expected(128, 128, QImage::Format_ARGB32_Premultiplied);
3262 expected.fill(0xffffffff);
3264 for (int i = 1; i < 5; ++i) {
3265 qreal scale = i / qreal(5);
3267 dst.fill(0xff000000);
3270 p.scale(dst.width() / qreal(src.width()), scale);
3272 for (int y = 0; y * scale < dst.height(); ++y)
3273 p.drawImage(0, y, src);
3277 QCOMPARE(dst, expected);
3281 #define FOR_EACH_NEIGHBOR_8 for (int dx = -1; dx <= 1; ++dx) for (int dy = -1; dy <= 1; ++dy) if (dx != 0 || dy != 0)
3282 #define FOR_EACH_NEIGHBOR_4 for (int dx = -1; dx <= 1; ++dx) for (int dy = -1; dy <= 1; ++dy) if ((dx == 0) != (dy == 0))
3284 uint qHash(const QPoint &point)
3286 return qHash(qMakePair(point.x(), point.y()));
3289 bool verifyOutlineFillConsistency(const QImage &img, QRgb outside, QRgb inside, QRgb outline)
3291 if (img.pixel(img.width() / 2, img.height() / 2) != inside)
3294 int x = img.width() / 2;
3295 int y = img.height() / 2;
3297 while (img.pixel(++x, y) == inside)
3300 if (img.pixel(x, y) != outline)
3303 QQueue<QPoint> discovered;
3304 discovered.enqueue(QPoint(x, y));
3306 QVector<bool> visited(img.width() * img.height());
3307 visited.fill(false);
3309 while (!discovered.isEmpty()) {
3310 QPoint p = discovered.dequeue();
3311 QRgb pixel = img.pixel(p.x(), p.y());
3313 bool &v = visited[p.y() * img.width() + p.x()];
3318 if (pixel == outline) {
3319 FOR_EACH_NEIGHBOR_8 {
3320 QPoint x(p.x() + dx, p.y() + dy);
3321 discovered.enqueue(x);
3324 FOR_EACH_NEIGHBOR_4 {
3325 if ((dx == 0) == (dy == 0))
3327 QRgb neighbor = img.pixel(p.x() + dx, p.y() + dy);
3328 if ((pixel == inside && neighbor == outside) ||
3329 (pixel == outside && neighbor == inside))
3338 #undef FOR_EACH_NEIGHBOR_8
3339 #undef FOR_EACH_NEIGHBOR_4
3341 void tst_QPainter::outlineFillConsistency()
3343 QSKIP("currently broken...");
3345 QImage dst(256, 256, QImage::Format_ARGB32_Premultiplied);
3348 poly << QPointF(5, -100) << QPointF(-70, 20) << QPointF(95, 25);
3351 QBrush brush(Qt::black);
3353 QRgb background = 0xffffffff;
3354 for (int i = 0; i < 360; ++i) {
3355 dst.fill(background);
3358 p.translate(dst.width() / 2, dst.height() / 2);
3360 QPolygonF copy = poly;
3361 for (int j = 0; j < copy.size(); ++j)
3362 copy[j] = QTransform().rotate(i).map(copy[j]);
3366 p.drawPolygon(copy);
3369 QVERIFY(verifyOutlineFillConsistency(dst, background, brush.color().rgba(), pen.color().rgba()));
3373 void tst_QPainter::drawImage_task217400_data()
3375 QTest::addColumn<QImage::Format>("format");
3377 QTest::newRow("444") << QImage::Format_ARGB4444_Premultiplied;
3378 QTest::newRow("555") << QImage::Format_ARGB8555_Premultiplied;
3379 QTest::newRow("565") << QImage::Format_ARGB8565_Premultiplied;
3380 // QTest::newRow("666") << QImage::Format_ARGB6666_Premultiplied;
3381 QTest::newRow("888p") << QImage::Format_ARGB32_Premultiplied;
3382 QTest::newRow("888") << QImage::Format_ARGB32;
3385 void tst_QPainter::drawImage_task217400()
3387 QFETCH(QImage::Format, format);
3389 const QImage src = QImage(QString(SRCDIR) + "/task217400.png")
3390 .convertToFormat(format);
3391 QVERIFY(!src.isNull());
3393 QImage expected(src.size(), format);
3395 QPainter p(&expected);
3396 p.fillRect(0, 0, expected.width(), expected.height(), Qt::white);
3397 p.drawImage(0, 0, src);
3400 for (int i = 1; i <= 4; ++i) {
3401 QImage dest(src.width() + i, src.height(), format);
3404 p.fillRect(0, 0, dest.width(), dest.height(), Qt::white);
3405 p.drawImage(i, 0, src);
3408 const QImage result = dest.copy(i, 0, src.width(), src.height());
3410 QCOMPARE(result, expected);
3414 void tst_QPainter::drawImage_task258776()
3416 QImage src(16, 16, QImage::Format_RGB888);
3417 QImage dest(33, 33, QImage::Format_RGB888);
3419 dest.fill(0x0000ff);
3421 QPainter painter(&dest);
3422 painter.drawImage(QRectF(0.499, 0.499, 32, 32), src, QRectF(0, 0, 16, 16));
3425 QImage expected(33, 33, QImage::Format_RGB32);
3426 expected.fill(0xff0000);
3428 painter.begin(&expected);
3429 painter.drawImage(QRectF(0, 0, 32, 32), src);
3432 dest = dest.convertToFormat(QImage::Format_RGB32);
3434 dest.save("dest.png");
3435 expected.save("expected.png");
3436 QCOMPARE(dest, expected);
3439 void tst_QPainter::clipRectSaveRestore()
3441 QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
3445 p.setClipRect(QRect(0, 0, 10, 10));
3447 p.setClipRect(QRect(5, 5, 5, 5), Qt::IntersectClip);
3449 p.fillRect(0, 0, 64, 64, Qt::black);
3452 QCOMPARE(img.pixel(0, 0), QColor(Qt::black).rgba());
3455 void tst_QPainter::clippedImage()
3457 QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
3460 QImage src(16, 16, QImage::Format_RGB32);
3461 src.fill(QColor(Qt::red).rgba());
3464 p.setClipRect(QRect(1, 1, 14, 14));
3465 p.drawImage(0, 0, src);
3468 QCOMPARE(img.pixel(0, 0), 0x0U);
3469 QCOMPARE(img.pixel(1, 1), src.pixel(1, 1));
3472 void tst_QPainter::stateResetBetweenQPainters()
3474 QImage img(16, 16, QImage::Format_ARGB32);
3478 p.setCompositionMode(QPainter::CompositionMode_Source);
3479 p.fillRect(0, 0, 16, 16, Qt::red);
3484 p2.fillRect(0, 0, 16, 16, QColor(0, 0, 255, 63));
3487 img.save("foo.png");
3489 QVERIFY(img.pixel(0, 0) != qRgba(0, 0, 255, 63));
3490 QVERIFY(qRed(img.pixel(0, 0)) > 0); // We didn't erase the red channel...
3491 QVERIFY(qBlue(img.pixel(0, 0)) < 255); // We blended the blue channel
3494 void tst_QPainter::drawRect_task215378()
3496 QImage img(11, 11, QImage::Format_ARGB32_Premultiplied);
3497 img.fill(QColor(Qt::white).rgba());
3500 p.setPen(QColor(127, 127, 127, 127));
3501 p.drawRect(0, 0, 10, 10);
3504 QCOMPARE(img.pixel(0, 0), img.pixel(1, 0));
3505 QCOMPARE(img.pixel(0, 0), img.pixel(0, 1));
3506 QVERIFY(img.pixel(0, 0) != img.pixel(1, 1));
3509 void tst_QPainter::drawRect_task247505()
3511 QImage a(10, 10, QImage::Format_ARGB32_Premultiplied);
3516 p.setPen(Qt::NoPen);
3517 p.setBrush(Qt::black);
3518 p.drawRect(QRectF(10, 0, -10, 10));
3521 p.setPen(Qt::NoPen);
3522 p.setBrush(Qt::black);
3523 p.drawRect(QRectF(0, 0, 10, 10));
3529 void tst_QPainter::drawImage_data()
3531 QTest::addColumn<int>("x");
3532 QTest::addColumn<int>("y");
3533 QTest::addColumn<int>("w");
3534 QTest::addColumn<int>("h");
3535 QTest::addColumn<QImage::Format>("srcFormat");
3536 QTest::addColumn<QImage::Format>("dstFormat");
3538 for (int srcFormat = QImage::Format_Mono; srcFormat < QImage::NImageFormats; ++srcFormat) {
3539 for (int dstFormat = QImage::Format_Mono; dstFormat < QImage::NImageFormats; ++dstFormat) {
3540 if (dstFormat == QImage::Format_Indexed8)
3542 for (int odd_x = 0; odd_x <= 1; ++odd_x) {
3543 for (int odd_width = 0; odd_width <= 1; ++odd_width) {
3544 QString description =
3545 QString("srcFormat %1, dstFormat %2, odd x: %3, odd width: %4")
3546 .arg(srcFormat).arg(dstFormat).arg(odd_x).arg(odd_width);
3548 QTest::newRow(qPrintable(description)) << (10 + odd_x) << 10 << (20 + odd_width) << 20
3549 << QImage::Format(srcFormat)
3550 << QImage::Format(dstFormat);
3557 bool verifyImage(const QImage &img, int x, int y, int w, int h, uint background)
3559 int imgWidth = img.width();
3560 int imgHeight = img.height();
3561 for (int i = 0; i < imgHeight; ++i) {
3562 for (int j = 0; j < imgWidth; ++j) {
3563 uint pixel = img.pixel(j, i);
3564 bool outside = j < x || j >= (x + w) || i < y || i >= (y + h);
3565 if (outside != (pixel == background)) {
3566 //printf("%d %d, expected %x, got %x, outside: %d\n", x, y, background, pixel, outside);
3575 void tst_QPainter::drawImage()
3581 QFETCH(QImage::Format, srcFormat);
3582 QFETCH(QImage::Format, dstFormat);
3584 QImage dst(40, 40, QImage::Format_RGB32);
3585 dst.fill(0xffffffff);
3587 dst = dst.convertToFormat(dstFormat);
3588 uint background = dst.pixel(0, 0);
3590 QImage src(w, h, QImage::Format_RGB32);
3591 src.fill(0xff000000);
3592 src = src.convertToFormat(srcFormat);
3595 p.drawImage(x, y, src);
3598 QVERIFY(verifyImage(dst, x, y, w, h, background));
3601 void tst_QPainter::imageCoordinateLimit()
3603 QImage img(64, 40000, QImage::Format_MonoLSB);
3605 p.drawText(10, 36000, QLatin1String("foo"));
3606 p.setPen(QPen(Qt::black, 2));
3607 p.drawLine(10, 0, 60, 40000);
3609 p.setRenderHint(QPainter::Antialiasing);
3610 p.drawLine(10, 0, 60, 40000);
3614 void tst_QPainter::imageBlending_data()
3616 QTest::addColumn<QImage::Format>("sourceFormat");
3617 QTest::addColumn<QImage::Format>("destFormat");
3618 QTest::addColumn<int>("error");
3620 int error_rgb565 = ((1<<3) + (1<<2) + (1<<3));
3621 QTest::newRow("rgb565_on_rgb565") << QImage::Format_RGB16
3622 << QImage::Format_RGB16
3624 QTest::newRow("argb8565_on_rgb565") << QImage::Format_ARGB8565_Premultiplied
3625 << QImage::Format_RGB16
3628 QTest::newRow("rgb32_on_rgb565") << QImage::Format_RGB32
3629 << QImage::Format_RGB16
3632 QTest::newRow("argb32pm_on_rgb565") << QImage::Format_ARGB32_Premultiplied
3633 << QImage::Format_RGB16
3637 int diffColor(quint32 ap, quint32 bp)
3639 int a = qAlpha(ap) - qAlpha(bp);
3640 int r = qRed(ap) - qRed(bp);
3641 int b = qBlue(ap) - qBlue(bp);
3642 int g = qBlue(ap) - qBlue(bp);
3644 return qAbs(a) + qAbs(r) + qAbs(g) + qAbs(b);
3647 // this test assumes premultiplied pixels...
3649 void tst_QPainter::imageBlending()
3651 QFETCH(QImage::Format, sourceFormat);
3652 QFETCH(QImage::Format, destFormat);
3657 QImage orig_dest(6, 6, QImage::Format_ARGB32_Premultiplied);
3659 QPainter p(&orig_dest);
3660 p.fillRect(0, 0, 6, 3, QColor::fromRgbF(1, 0, 0));
3661 p.fillRect(3, 0, 3, 6, QColor::fromRgbF(0, 0, 1, 0.5));
3663 dest = orig_dest.convertToFormat(destFormat);
3665 // An image like this: (r = red, m = magenta, b = light alpha blue, 0 = transparent)
3676 QImage orig_source(6, 6, QImage::Format_ARGB32_Premultiplied);
3677 orig_source.fill(0);
3678 QPainter p(&orig_source);
3679 p.fillRect(1, 1, 4, 4, QColor::fromRgbF(0, 1, 0, 0.5));
3680 p.fillRect(2, 2, 2, 2, QColor::fromRgbF(0, 1, 0));
3682 source = orig_source.convertToFormat(sourceFormat);
3684 // An image like this: (0 = transparent, . = green at 0.5 alpha, g = opaque green.
3694 p.drawImage(0, 0, source);
3705 // the g pixels, always green..
3706 QVERIFY(diffColor(dest.pixel(2, 2), 0xff00ff00) <= error); // g
3708 if (source.hasAlphaChannel()) {
3709 QVERIFY(diffColor(dest.pixel(0, 0), 0xffff0000) <= error); // r
3710 QVERIFY(diffColor(dest.pixel(5, 0), 0xff7f007f) <= error); // m
3711 QVERIFY(diffColor(dest.pixel(1, 1), 0xff7f7f00) <= error); // r.
3712 QVERIFY(diffColor(dest.pixel(4, 1), 0xff3f7f3f) <= error); // m.
3713 if (dest.hasAlphaChannel()) {
3714 QVERIFY(diffColor(dest.pixel(1, 3), 0x7f007f00) <= error); // .
3715 QVERIFY(diffColor(dest.pixel(4, 3), 0x7f007f3f) <= error); // b.
3716 QVERIFY(diffColor(dest.pixel(4, 3), 0x7f007f3f) <= error); // b.
3717 QVERIFY(diffColor(dest.pixel(4, 4), 0x7f00007f) <= error); // b
3718 QVERIFY(diffColor(dest.pixel(4, 0), 0) <= 0); // 0
3721 QVERIFY(diffColor(dest.pixel(0, 0), 0xff000000) <= 0);
3722 QVERIFY(diffColor(dest.pixel(1, 1), 0xff007f00) <= error);
3726 void tst_QPainter::imageBlending_clipped()
3728 QImage src(20, 20, QImage::Format_RGB16);
3730 p.fillRect(src.rect(), Qt::red);
3733 QImage dst(40, 20, QImage::Format_RGB16);
3735 p.fillRect(dst.rect(), Qt::white);
3738 QImage expected = dst;
3741 p.setClipRect(QRect(23, 0, 20, 20));
3743 // should be completely clipped
3744 p.drawImage(QRectF(3, 0, 20, 20), src);
3747 // dst should be left unchanged
3748 QCOMPARE(dst, expected);
3751 void tst_QPainter::paintOnNullPixmap()
3753 QPixmap pix(16, 16);
3756 QPainter p(&textPixmap);
3757 p.drawPixmap(10, 10, pix);
3760 QPixmap textPixmap2(16,16);
3761 p.begin(&textPixmap2);
3765 void tst_QPainter::checkCompositionMode()
3767 QImage refImage(50,50,QImage::Format_ARGB32);
3768 QPainter painter(&refImage);
3769 painter.fillRect(QRect(0,0,50,50),Qt::blue);
3771 QImage testImage(50,50,QImage::Format_ARGB32);
3772 QPainter p(&testImage);
3773 p.fillRect(QRect(0,0,50,50),Qt::red);
3775 p.setCompositionMode(QPainter::CompositionMode_SourceOut);
3777 p.fillRect(QRect(0,0,50,50),Qt::blue);
3779 QCOMPARE(refImage.pixel(20,20),testImage.pixel(20,20));
3782 static QLinearGradient inverseGradient(QLinearGradient g)
3784 QLinearGradient g2 = g;
3786 QGradientStops stops = g.stops();
3788 QGradientStops inverse;
3789 foreach (QGradientStop stop, stops)
3790 inverse << QGradientStop(1 - stop.first, stop.second);
3792 g2.setStops(inverse);
3796 // QWS has limited resolution in the gradient color table
3798 void tst_QPainter::linearGradientSymmetry_data()
3800 QTest::addColumn<QGradientStops>("stops");
3802 if (sizeof(qreal) != sizeof(float)) {
3803 QGradientStops stops;
3804 stops << qMakePair(qreal(0.0), QColor(Qt::blue));
3805 stops << qMakePair(qreal(0.2), QColor(220, 220, 220, 0));
3806 stops << qMakePair(qreal(0.6), QColor(Qt::red));
3807 stops << qMakePair(qreal(0.9), QColor(220, 220, 220, 255));
3808 stops << qMakePair(qreal(1.0), QColor(Qt::black));
3809 QTest::newRow("multiple stops") << stops;
3813 QGradientStops stops;
3814 stops << qMakePair(qreal(0.0), QColor(Qt::blue));
3815 stops << qMakePair(qreal(1.0), QColor(Qt::black));
3816 QTest::newRow("two stops") << stops;
3819 if (sizeof(qreal) != sizeof(float)) {
3820 QGradientStops stops;
3821 stops << qMakePair(qreal(0.3), QColor(Qt::blue));
3822 stops << qMakePair(qreal(0.6), QColor(Qt::black));
3823 QTest::newRow("two stops 2") << stops;
3827 void tst_QPainter::linearGradientSymmetry()
3829 QFETCH(QGradientStops, stops);
3831 QImage a(64, 8, QImage::Format_ARGB32_Premultiplied);
3832 QImage b(64, 8, QImage::Format_ARGB32_Premultiplied);
3837 QLinearGradient gradient(QRectF(b.rect()).topLeft(), QRectF(b.rect()).topRight());
3838 gradient.setStops(stops);
3841 pa.fillRect(a.rect(), gradient);
3845 pb.fillRect(b.rect(), inverseGradient(gradient));
3848 b = b.mirrored(true);
3853 void tst_QPainter::gradientInterpolation()
3855 QImage image(256, 8, QImage::Format_ARGB32_Premultiplied);
3858 QLinearGradient gradient(QRectF(image.rect()).topLeft(), QRectF(image.rect()).topRight());
3859 gradient.setColorAt(0.0, QColor(255, 0, 0, 0));
3860 gradient.setColorAt(1.0, Qt::blue);
3863 painter.begin(&image);
3864 painter.fillRect(image.rect(), gradient);
3867 const QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(3));
3869 for (int i = 0; i < 256; ++i) {
3870 QCOMPARE(qAlpha(line[i]), qBlue(line[i])); // bright blue
3871 QVERIFY(qAbs(qAlpha(line[i]) - i) < 3); // linear alpha
3872 QCOMPARE(qRed(line[i]), 0); // no red component
3873 QCOMPARE(qGreen(line[i]), 0); // no green component
3876 gradient.setInterpolationMode(QGradient::ComponentInterpolation);
3879 painter.begin(&image);
3880 painter.fillRect(image.rect(), gradient);
3883 for (int i = 1; i < 256; ++i) {
3885 QVERIFY(qRed(line[i]) >= qBlue(line[i])); // red is dominant
3887 QVERIFY(qRed(line[i]) <= qBlue(line[i])); // blue is dominant
3889 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
3890 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
3891 QVERIFY(qAbs(qAlpha(line[i]) - i) < 3); // linear alpha
3892 QCOMPARE(qGreen(line[i]), 0); // no green component
3896 void tst_QPainter::drawPolygon()
3898 QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
3900 QPainterPathStroker stroker;
3901 stroker.setWidth(1.5);
3907 QPolygonF poly = stroker.createStroke(path).toFillPolygon();
3909 img.fill(0xffffffff);
3911 p.setRenderHint(QPainter::Antialiasing);
3912 p.setBrush(Qt::red);
3913 p.setPen(Qt::NoPen);
3914 p.drawPolygon(poly);
3915 p.translate(64, 64);
3916 p.drawPolygon(poly);
3919 QImage a = img.copy();
3921 img.fill(0xffffffff);
3923 p.setRenderHint(QPainter::Antialiasing);
3924 p.setBrush(Qt::red);
3925 p.setPen(Qt::NoPen);
3926 p.translate(64, 64);
3927 p.drawPolygon(poly);
3929 p.drawPolygon(poly);
3935 void tst_QPainter::inactivePainter()
3937 // This test succeeds if it doesn't segfault.
3941 QRegion region(QRect(20, 20, 60, 40));
3942 QPolygonF polygon(QVector<QPointF>() << QPointF(0, 0) << QPointF(12, 0) << QPointF(8, 6));
3943 path.addPolygon(polygon);
3949 p.setBackground(QBrush(Qt::blue));
3952 p.setBrush(Qt::red);
3953 p.setBrush(Qt::NoBrush);
3954 p.setBrush(QBrush(Qt::white, Qt::DiagCrossPattern));
3957 p.setBackgroundMode(Qt::OpaqueMode);
3959 p.boundingRect(QRectF(0, 0, 100, 20), Qt::AlignCenter, QLatin1String("Hello, World!"));
3960 p.boundingRect(QRect(0, 0, 100, 20), Qt::AlignCenter, QLatin1String("Hello, World!"));
3963 p.setBrushOrigin(QPointF(12, 34));
3964 p.setBrushOrigin(QPoint(12, 34));
3969 p.setClipPath(path);
3970 p.setClipRect(QRectF(42, 42, 42, 42));
3971 p.setClipRect(QRect(42, 42, 42, 42));
3972 p.setClipRegion(region);
3973 p.setClipping(true);
3976 p.combinedTransform();
3978 p.compositionMode();
3979 p.setCompositionMode(QPainter::CompositionMode_Plus);
3983 p.deviceTransform();
3986 p.setFont(QFont(QLatin1String("Times"), 24));
3991 p.layoutDirection();
3992 p.setLayoutDirection(Qt::RightToLeft);
3998 p.setPen(QPen(Qt::red));
3999 p.setPen(Qt::green);
4000 p.setPen(Qt::NoPen);
4003 p.setRenderHint(QPainter::Antialiasing, true);
4004 p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false);
4013 p.viewTransformEnabled();
4014 p.setViewTransformEnabled(true);
4017 p.setViewport(QRect(10, 10, 620, 460));
4020 p.setWindow(QRect(10, 10, 620, 460));
4023 p.setWorldMatrix(QMatrix().translate(43, 21), true);
4024 p.setWorldMatrixEnabled(true);
4027 p.setTransform(QTransform().translate(12, 34), true);
4030 p.setWorldTransform(QTransform().scale(0.5, 0.5), true);
4033 bool testCompositionMode(int src, int dst, int expected, QPainter::CompositionMode op, qreal opacity = 1.0)
4035 // The test image needs to be large enough to test SIMD code
4036 const QSize imageSize(100, 100);
4038 QImage actual(imageSize, QImage::Format_ARGB32_Premultiplied);
4039 actual.fill(QColor(dst, dst, dst).rgb());
4041 QPainter p(&actual);
4042 p.setCompositionMode(op);
4043 p.setOpacity(opacity);
4044 p.fillRect(QRect(QPoint(), imageSize), QColor(src, src, src));
4047 if (qRed(actual.pixel(0, 0)) != expected) {
4048 qDebug("Fail: mode %d, src[%d] dst [%d] actual [%d] expected [%d]", op,
4049 src, dst, qRed(actual.pixel(0, 0)), expected);
4052 QImage refImage(imageSize, QImage::Format_ARGB32_Premultiplied);
4053 refImage.fill(QColor(expected, expected, expected).rgb());
4054 return actual == refImage;
4058 void tst_QPainter::extendedBlendModes()
4060 QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Plus));
4061 QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Plus));
4062 QVERIFY(testCompositionMode(127, 128, 255, QPainter::CompositionMode_Plus));
4063 QVERIFY(testCompositionMode(127, 0, 127, QPainter::CompositionMode_Plus));
4064 QVERIFY(testCompositionMode( 0, 127, 127, QPainter::CompositionMode_Plus));
4065 QVERIFY(testCompositionMode(255, 0, 255, QPainter::CompositionMode_Plus));
4066 QVERIFY(testCompositionMode( 0, 255, 255, QPainter::CompositionMode_Plus));
4067 QVERIFY(testCompositionMode(128, 128, 255, QPainter::CompositionMode_Plus));
4069 QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Plus, 0.3));
4070 QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Plus, 0.3));
4071 QVERIFY(testCompositionMode(127, 128, 165, QPainter::CompositionMode_Plus, 0.3));
4072 QVERIFY(testCompositionMode(127, 0, 37, QPainter::CompositionMode_Plus, 0.3));
4073 QVERIFY(testCompositionMode( 0, 127, 127, QPainter::CompositionMode_Plus, 0.3));
4074 QVERIFY(testCompositionMode(255, 0, 75, QPainter::CompositionMode_Plus, 0.3));
4075 QVERIFY(testCompositionMode( 0, 255, 255, QPainter::CompositionMode_Plus, 0.3));
4076 QVERIFY(testCompositionMode(128, 128, 166, QPainter::CompositionMode_Plus, 0.3));
4077 QVERIFY(testCompositionMode(186, 200, 255, QPainter::CompositionMode_Plus, 0.3));
4079 QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Multiply));
4080 QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Multiply));
4081 QVERIFY(testCompositionMode(127, 255, 127, QPainter::CompositionMode_Multiply));
4082 QVERIFY(testCompositionMode(255, 127, 127, QPainter::CompositionMode_Multiply));
4083 QVERIFY(testCompositionMode( 63, 255, 63, QPainter::CompositionMode_Multiply));
4084 QVERIFY(testCompositionMode(255, 63, 63, QPainter::CompositionMode_Multiply));
4085 QVERIFY(testCompositionMode(127, 127, 63, QPainter::CompositionMode_Multiply));
4087 QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Screen));
4088 QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Screen));
4089 QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Screen));
4090 QVERIFY(testCompositionMode(255, 63, 255, QPainter::CompositionMode_Screen));
4091 QVERIFY(testCompositionMode( 63, 0, 63, QPainter::CompositionMode_Screen));
4092 QVERIFY(testCompositionMode( 0, 63, 63, QPainter::CompositionMode_Screen));
4093 QVERIFY(testCompositionMode(127, 127, 191, QPainter::CompositionMode_Screen));
4095 QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Overlay));
4096 QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Overlay));
4097 QVERIFY(testCompositionMode( 63, 63, 31, QPainter::CompositionMode_Overlay));
4098 QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Overlay));
4100 QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Darken));
4101 QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Darken));
4102 QVERIFY(testCompositionMode( 63, 63, 63, QPainter::CompositionMode_Darken));
4103 QVERIFY(testCompositionMode( 63, 255, 63, QPainter::CompositionMode_Darken));
4104 QVERIFY(testCompositionMode(255, 63, 63, QPainter::CompositionMode_Darken));
4105 QVERIFY(testCompositionMode( 63, 127, 63, QPainter::CompositionMode_Darken));
4106 QVERIFY(testCompositionMode(127, 63, 63, QPainter::CompositionMode_Darken));
4108 QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Lighten));
4109 QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Lighten));
4110 QVERIFY(testCompositionMode( 63, 63, 63, QPainter::CompositionMode_Lighten));
4111 QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Lighten));
4112 QVERIFY(testCompositionMode(255, 63, 255, QPainter::CompositionMode_Lighten));
4113 QVERIFY(testCompositionMode( 63, 127, 127, QPainter::CompositionMode_Lighten));
4114 QVERIFY(testCompositionMode(127, 63, 127, QPainter::CompositionMode_Lighten));
4116 QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_ColorDodge));
4117 QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_ColorDodge));
4118 QVERIFY(testCompositionMode( 63, 127, 169, QPainter::CompositionMode_ColorDodge));
4119 QVERIFY(testCompositionMode(191, 127, 255, QPainter::CompositionMode_ColorDodge));
4120 QVERIFY(testCompositionMode(127, 191, 255, QPainter::CompositionMode_ColorDodge));
4122 QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_ColorBurn));
4123 QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_ColorBurn));
4124 QVERIFY(testCompositionMode(127, 127, 0, QPainter::CompositionMode_ColorBurn));
4125 QVERIFY(testCompositionMode(128, 128, 2, QPainter::CompositionMode_ColorBurn));
4126 QVERIFY(testCompositionMode(191, 127, 84, QPainter::CompositionMode_ColorBurn));
4128 QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_HardLight));
4129 QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_HardLight));
4130 QVERIFY(testCompositionMode(127, 127, 127, QPainter::CompositionMode_HardLight));
4131 QVERIFY(testCompositionMode( 63, 63, 31, QPainter::CompositionMode_HardLight));
4132 QVERIFY(testCompositionMode(127, 63, 63, QPainter::CompositionMode_HardLight));
4134 QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_SoftLight));
4135 QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_SoftLight));
4136 QVERIFY(testCompositionMode(127, 127, 126, QPainter::CompositionMode_SoftLight));
4137 QVERIFY(testCompositionMode( 63, 63, 39, QPainter::CompositionMode_SoftLight));
4138 QVERIFY(testCompositionMode(127, 63, 62, QPainter::CompositionMode_SoftLight));
4140 QVERIFY(testCompositionMode(255, 255, 0, QPainter::CompositionMode_Difference));
4141 QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Difference));
4142 QVERIFY(testCompositionMode(255, 0, 255, QPainter::CompositionMode_Difference));
4143 QVERIFY(testCompositionMode(127, 127, 0, QPainter::CompositionMode_Difference));
4144 QVERIFY(testCompositionMode(127, 128, 1, QPainter::CompositionMode_Difference));
4145 QVERIFY(testCompositionMode(127, 63, 64, QPainter::CompositionMode_Difference));
4146 QVERIFY(testCompositionMode( 0, 127, 127, QPainter::CompositionMode_Difference));
4148 QVERIFY(testCompositionMode(255, 255, 0, QPainter::CompositionMode_Exclusion));
4149 QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Exclusion));
4150 QVERIFY(testCompositionMode(255, 0, 255, QPainter::CompositionMode_Exclusion));
4151 QVERIFY(testCompositionMode(127, 127, 127, QPainter::CompositionMode_Exclusion));
4152 QVERIFY(testCompositionMode( 63, 127, 127, QPainter::CompositionMode_Exclusion));
4153 QVERIFY(testCompositionMode( 63, 63, 95, QPainter::CompositionMode_Exclusion));
4154 QVERIFY(testCompositionMode(191, 191, 96, QPainter::CompositionMode_Exclusion));
4157 void tst_QPainter::zeroOpacity()
4159 QImage source(1, 1, QImage::Format_ARGB32_Premultiplied);
4160 source.fill(0xffffffff);
4162 QImage target(1, 1, QImage::Format_RGB32);
4163 target.fill(0xff000000);
4165 QPainter p(&target);
4167 p.drawImage(0, 0, source);
4170 QCOMPARE(target.pixel(0, 0), 0xff000000);
4173 void tst_QPainter::clippingBug()
4175 QImage img(32, 32, QImage::Format_ARGB32_Premultiplied);
4178 QImage expected = img;
4179 QPainter p(&expected);
4180 p.fillRect(1, 1, 30, 30, Qt::red);
4184 path.addRect(1, 1, 30, 30);
4185 path.addRect(1, 1, 30, 30);
4186 path.addRect(1, 1, 30, 30);
4189 p.setClipPath(path);
4190 p.fillRect(0, 0, 32, 32, Qt::red);
4193 QCOMPARE(img, expected);
4196 void tst_QPainter::emptyClip()
4198 QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
4200 p.setRenderHints(QPainter::Antialiasing);
4201 p.setClipRect(0, 32, 64, 0);
4202 p.fillRect(0, 0, 64, 64, Qt::white);
4206 path.lineTo(64, 64);
4207 path.lineTo(40, 64);
4208 path.lineTo(40, 80);
4211 p.fillPath(path, Qt::green);
4214 void tst_QPainter::drawImage_1x1()
4216 QImage source(1, 1, QImage::Format_ARGB32_Premultiplied);
4217 source.fill(0xffffffff);
4219 QImage img(32, 32, QImage::Format_ARGB32_Premultiplied);
4220 img.fill(0xff000000);
4222 p.drawImage(QRectF(0.9, 0.9, 32, 32), source);
4225 QImage expected = img;
4226 expected.fill(0xff000000);
4228 p.fillRect(1, 1, 31, 31, Qt::white);
4231 QCOMPARE(img, expected);
4234 void tst_QPainter::taskQT4444_dontOverflowDashOffset()
4240 pen.setStyle(Qt::DashDotLine);
4243 point[0] = QPointF(182.50868749707968,347.78457234212630);
4244 point[1] = QPointF(182.50868749707968,107.22501998401277);
4245 point[2] = QPointF(182.50868749707968,107.22501998401277);
4246 point[3] = QPointF(520.46600762283651,107.22501998401277);
4248 QImage crashImage(QSize(1000, 120), QImage::Format_ARGB32_Premultiplied);
4249 p.begin(&crashImage);
4251 p.drawLines(point, 2);
4254 QVERIFY(true); // Don't crash
4257 void tst_QPainter::painterBegin()
4260 QImage indexed8Image(16, 16, QImage::Format_Indexed8);
4261 QImage rgb32Image(16, 16, QImage::Format_RGB32);
4262 QImage argb32Image(16, 16, QImage::Format_ARGB32_Premultiplied);
4266 // Painting on null image should fail.
4267 QVERIFY(!p.begin(&nullImage));
4269 // Check that the painter is not messed up by using it on another image.
4270 QVERIFY(p.begin(&rgb32Image));
4273 // If painting on indexed8 image fails, the painter state should still be OK.
4274 if (p.begin(&indexed8Image))
4276 QVERIFY(p.begin(&rgb32Image));
4279 // Try opening a painter on the two different images.
4280 QVERIFY(p.begin(&rgb32Image));
4281 QVERIFY(!p.begin(&argb32Image));
4284 // Try opening two painters on the same image.
4285 QVERIFY(p.begin(&rgb32Image));
4287 QVERIFY(!q.begin(&rgb32Image));
4291 // Try ending an inactive painter.
4295 void tst_QPainter::setPenColor(QPainter& p)
4297 p.setPen(Qt::NoPen);
4299 // Setting color, then style
4300 // Should work even though the pen is "NoPen with color", temporarily.
4301 QPen newPen(p.pen());
4302 newPen.setColor(Qt::red);
4303 QCOMPARE(p.pen().style(), newPen.style());
4304 QCOMPARE(p.pen().style(), Qt::NoPen);
4307 QCOMPARE(p.pen().color().name(), QString("#ff0000"));
4309 QPen newPen2(p.pen());
4310 newPen2.setStyle(Qt::SolidLine);
4313 QCOMPARE(p.pen().color().name(), QString("#ff0000"));
4316 void tst_QPainter::setPenColorOnImage()
4318 QImage img(QSize(10, 10), QImage::Format_ARGB32_Premultiplied);
4323 void tst_QPainter::setPenColorOnPixmap()
4325 QPixmap pix(10, 10);
4330 class TestProxy : public QGraphicsProxyWidget
4333 TestProxy() : QGraphicsProxyWidget() {}
4334 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
4336 QGraphicsProxyWidget::paint(painter, option, widget);
4337 deviceTransform = painter->deviceTransform();
4339 QTransform deviceTransform;
4342 class TestWidget : public QWidget
4346 TestWidget() : QWidget(), painted(false) {}
4347 void paintEvent(QPaintEvent *)
4350 deviceTransform = p.deviceTransform();
4351 worldTransform = p.worldTransform();
4354 QTransform deviceTransform;
4355 QTransform worldTransform;
4359 void tst_QPainter::QTBUG5939_attachPainterPrivate()
4361 QWidget *w = new QWidget();
4362 QGraphicsScene *scene = new QGraphicsScene();
4363 QGraphicsView *view = new QGraphicsView(scene, w);
4365 TestProxy *proxy = new TestProxy();
4366 TestWidget *widget = new TestWidget();
4367 proxy->setWidget(widget);
4368 scene->addItem(proxy);
4370 w->resize(scene->sceneRect().size().toSize());
4373 QTRY_VERIFY(widget->painted);
4375 QVERIFY(widget->worldTransform.isIdentity());
4376 QCOMPARE(widget->deviceTransform, proxy->deviceTransform);
4379 void tst_QPainter::clipBoundingRect()
4381 QPixmap pix(500, 500);
4385 // Test a basic rectangle
4386 p.setClipRect(100, 100, 200, 100);
4387 QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
4388 QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200)));
4389 p.setClipRect(120, 120, 20, 20, Qt::IntersectClip);
4390 QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20)));
4391 QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
4393 // Test a basic float rectangle
4394 p.setClipRect(QRectF(100, 100, 200, 100));
4395 QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
4396 QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200)));
4397 p.setClipRect(QRectF(120, 120, 20, 20), Qt::IntersectClip);
4398 QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20)));
4399 QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
4401 // Test a basic path + region
4403 path.addRect(100, 100, 200, 100);
4404 p.setClipPath(path);
4405 QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
4406 QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200)));
4407 p.setClipRegion(QRegion(120, 120, 20, 20), Qt::IntersectClip);
4408 QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20)));
4409 QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
4411 p.setClipRect(0, 0, 500, 500);
4412 p.translate(250, 250);
4413 for (int i=0; i<360; ++i) {
4415 p.setClipRect(-100, -100, 200, 200, Qt::IntersectClip);
4417 QVERIFY(p.clipBoundingRect().contains(QRectF(-100, -100, 200, 200)));
4418 QVERIFY(!p.clipBoundingRect().contains(QRectF(-250, -250, 500, 500)));
4422 //Only Mac/Cocoa supports sub pixel positions in raster engine currently
4424 void tst_QPainter::drawText_subPixelPositionsInRaster_qtbug5053()
4426 QFontMetricsF fm(qApp->font());
4428 QImage baseLine(fm.width(QChar::fromLatin1('e')), fm.height(), QImage::Format_RGB32);
4429 baseLine.fill(Qt::white);
4431 QPainter p(&baseLine);
4432 p.drawText(0, fm.ascent(), QString::fromLatin1("e"));
4435 bool foundDifferentRasterization = false;
4436 for (int i=1; i<12; ++i) {
4437 QImage comparison(baseLine.size(), QImage::Format_RGB32);
4438 comparison.fill(Qt::white);
4441 QPainter p(&comparison);
4442 p.drawText(QPointF(i / 12.0, fm.ascent()), QString::fromLatin1("e"));
4445 if (comparison != baseLine) {
4446 foundDifferentRasterization = true;
4451 QVERIFY(foundDifferentRasterization);
4455 void tst_QPainter::drawPointScaled()
4457 QImage image(32, 32, QImage::Format_RGB32);
4458 image.fill(0xffffffff);
4466 pen.setColor(Qt::red);
4472 QCOMPARE(image.pixel(16, 16), 0xffff0000);
4475 class GradientProducer : public QThread
4481 void GradientProducer::run()
4483 QImage image(1, 1, QImage::Format_RGB32);
4486 for (int i = 0; i < 1000; ++i) {
4488 g.setColorAt(0, QColor(i % 256, 0, 0));
4489 g.setColorAt(1, Qt::white);
4491 p.fillRect(image.rect(), g);
4495 void tst_QPainter::QTBUG14614_gradientCacheRaceCondition()
4497 const int threadCount = 16;
4498 GradientProducer producers[threadCount];
4499 for (int i = 0; i < threadCount; ++i)
4500 producers[i].start();
4501 for (int i = 0; i < threadCount; ++i)
4502 producers[i].wait();
4505 void tst_QPainter::drawTextOpacity()
4507 QImage image(32, 32, QImage::Format_RGB32);
4508 image.fill(0xffffffff);
4511 p.setPen(QColor("#6F6F6F"));
4513 p.drawText(5, 30, QLatin1String("Qt"));
4516 QImage copy = image;
4517 image.fill(0xffffffff);
4520 p.setPen(QColor("#6F6F6F"));
4521 p.drawLine(-10, -10, -1, -1);
4523 p.drawText(5, 30, QLatin1String("Qt"));
4526 QCOMPARE(image, copy);
4529 void tst_QPainter::QTBUG17053_zeroDashPattern()
4531 QImage image(32, 32, QImage::Format_RGB32);
4532 image.fill(0xffffffff);
4534 QImage original = image;
4536 QVector<qreal> pattern;
4537 pattern << qreal(0) << qreal(0);
4540 QPen pen(Qt::black, 2.0);
4541 pen.setDashPattern(pattern);
4544 p.drawLine(0, 0, image.width(), image.height());
4546 QCOMPARE(image, original);
4549 class TextDrawerThread : public QThread
4556 void TextDrawerThread::run()
4558 rendering = QImage(100, 100, QImage::Format_ARGB32_Premultiplied);
4560 QPainter p(&rendering);
4561 p.fillRect(10, 10, 100, 100, Qt::blue);
4562 p.setPen(Qt::green);
4563 p.drawText(20, 20, "some text");
4567 void tst_QPainter::drawTextOutsideGuiThread()
4569 if (!QFontDatabase::supportsThreadedFontRendering())
4570 QSKIP("No threaded font rendering");
4572 QImage referenceRendering(100, 100, QImage::Format_ARGB32_Premultiplied);
4573 referenceRendering.fill(0);
4574 QPainter p(&referenceRendering);
4575 p.fillRect(10, 10, 100, 100, Qt::blue);
4576 p.setPen(Qt::green);
4577 p.drawText(20, 20, "some text");
4584 QCOMPARE(referenceRendering, t.rendering);
4587 QTEST_MAIN(tst_QPainter)
4589 #include "tst_qpainter.moc"