Make QPen default to 1-width non-cosmetic.
[profile/ivi/qtbase.git] / tests / auto / gui / painting / qpainter / tst_qpainter.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44 #include <qpainter.h>
45 #ifndef QT_NO_WIDGETS
46 #include <qdrawutil.h>
47 #include <qapplication.h>
48 #include <qwidget.h>
49 #endif
50 #include <qfontmetrics.h>
51 #include <qbitmap.h>
52 #include <qimage.h>
53 #include <qthread.h>
54 #include <limits.h>
55 #if !defined(Q_OS_WINCE)
56 #ifndef QT_NO_WIDGETS
57 #include <qprinter.h>
58 #endif
59 #include <math.h>
60 #endif
61 #include <qpaintengine.h>
62 #ifndef QT_NO_WIDGETS
63 #include <qdesktopwidget.h>
64 #endif
65 #include <qpixmap.h>
66
67 #include <qpainter.h>
68
69 #ifndef QT_NO_WIDGETS
70 #include <qlabel.h>
71 #endif
72
73 #include <qqueue.h>
74
75 #ifndef QT_NO_WIDGETS
76 #include <qgraphicsview.h>
77 #include <qgraphicsscene.h>
78 #include <qgraphicsproxywidget.h>
79 #include <qlayout.h>
80 #endif
81 #include <qfontdatabase.h>
82
83 Q_DECLARE_METATYPE(QGradientStops)
84 Q_DECLARE_METATYPE(QLine)
85 Q_DECLARE_METATYPE(QRect)
86 Q_DECLARE_METATYPE(QSize)
87 Q_DECLARE_METATYPE(QPoint)
88 Q_DECLARE_METATYPE(QPainterPath)
89
90 class tst_QPainter : public QObject
91 {
92 Q_OBJECT
93
94 public:
95     tst_QPainter();
96     virtual ~tst_QPainter();
97
98
99 public slots:
100     void init();
101     void cleanup();
102     void cleanupTestCase();
103 private slots:
104     void getSetCheck();
105 #ifndef QT_NO_WIDGETS
106     void drawPixmap_comp_data();
107     void drawPixmap_comp();
108 #endif
109     void saveAndRestore_data();
110     void saveAndRestore();
111
112 #ifndef QT_NO_WIDGETS
113     void drawBorderPixmap();
114 #endif
115     void drawPixmapFragments();
116
117     void drawLine_data();
118     void drawLine();
119     void drawLine_clipped();
120     void drawLine_task121143();
121     void drawLine_task216948();
122
123     void drawLine_task190634();
124     void drawLine_task229459();
125     void drawLine_task234891();
126
127     void drawRect_data() { fillData(); }
128     void drawRect();
129     void drawRect2();
130
131     void fillRect();
132     void fillRect2();
133     void fillRect3();
134     void fillRect4();
135
136     void drawEllipse_data();
137     void drawEllipse();
138     void drawClippedEllipse_data();
139     void drawClippedEllipse();
140
141     void drawPath_data();
142     void drawPath();
143     void drawPath2();
144     void drawPath3();
145
146     void drawRoundRect_data() { fillData(); }
147     void drawRoundRect();
148
149     void qimageFormats_data();
150     void qimageFormats();
151     void textOnTransparentImage();
152
153 #ifndef QT_NO_WIDGETS
154     void initFrom();
155 #endif
156
157     void setWindow();
158
159     void combinedMatrix();
160     void renderHints();
161
162     void disableEnableClipping();
163     void setClipRect();
164     void setEqualClipRegionAndPath_data();
165     void setEqualClipRegionAndPath();
166
167     void clipRectSaveRestore();
168
169     void clippedFillPath_data();
170     void clippedFillPath();
171     void clippedLines_data();
172     void clippedLines();
173     void clippedPolygon_data();
174     void clippedPolygon();
175
176     void clippedText();
177
178     void clipBoundingRect();
179
180     void setOpacity_data();
181     void setOpacity();
182
183     void drawhelper_blend_untransformed_data();
184     void drawhelper_blend_untransformed();
185     void drawhelper_blend_tiled_untransformed_data();
186     void drawhelper_blend_tiled_untransformed();
187
188     void porterDuff_warning();
189
190     void drawhelper_blend_color();
191
192 #ifndef QT_NO_WIDGETS
193     void childWidgetViewport();
194 #endif
195
196     void fillRect_objectBoundingModeGradient();
197     void fillRect_stretchToDeviceMode();
198     void monoImages();
199
200     void linearGradientSymmetry_data();
201     void linearGradientSymmetry();
202     void gradientInterpolation();
203
204     void fpe_pixmapTransform();
205     void fpe_zeroLengthLines();
206     void fpe_divByZero();
207
208     void fpe_steepSlopes_data();
209     void fpe_steepSlopes();
210     void fpe_rasterizeLine_task232012();
211
212     void fpe_radialGradients();
213
214     void rasterizer_asserts();
215     void rasterizer_negativeCoords();
216
217     void blendOverFlow_data();
218     void blendOverFlow();
219
220     void largeImagePainting_data();
221     void largeImagePainting();
222
223     void imageScaling_task206785();
224
225     void outlineFillConsistency();
226
227     void drawImage_task217400_data();
228     void drawImage_task217400();
229     void drawImage_1x1();
230     void drawImage_task258776();
231     void drawRect_task215378();
232     void drawRect_task247505();
233
234     void drawText_subPixelPositionsInRaster_qtbug5053();
235
236     void drawImage_data();
237     void drawImage();
238
239     void clippedImage();
240
241     void stateResetBetweenQPainters();
242
243     void imageCoordinateLimit();
244     void imageBlending_data();
245     void imageBlending();
246     void imageBlending_clipped();
247
248     void paintOnNullPixmap();
249     void checkCompositionMode();
250
251     void drawPolygon();
252
253     void inactivePainter();
254
255     void extendedBlendModes();
256
257     void zeroOpacity();
258     void clippingBug();
259     void emptyClip();
260
261     void taskQT4444_dontOverflowDashOffset();
262
263     void painterBegin();
264     void setPenColorOnImage();
265     void setPenColorOnPixmap();
266
267 #ifndef QT_NO_WIDGETS
268     void QTBUG5939_attachPainterPrivate();
269 #endif
270
271     void drawPointScaled();
272
273     void QTBUG14614_gradientCacheRaceCondition();
274     void drawTextOpacity();
275
276     void QTBUG17053_zeroDashPattern();
277
278     void drawTextOutsideGuiThread();
279
280     void drawTextWithComplexBrush();
281     void QTBUG26013_squareCapStroke();
282     void QTBUG25153_drawLine();
283
284 private:
285     void fillData();
286     void setPenColor(QPainter& p);
287     QColor baseColor( int k, int intensity=255 );
288     QImage getResImage( const QString &dir, const QString &addition, const QString &extension );
289     QBitmap getBitmap( const QString &dir, const QString &filename, bool mask );
290 };
291
292 // Testing get/set functions
293 void tst_QPainter::getSetCheck()
294 {
295     QImage img(QSize(10, 10), QImage::Format_ARGB32_Premultiplied);
296     QPainter obj1;
297     obj1.begin(&img);
298     // CompositionMode QPainter::compositionMode()
299     // void QPainter::setCompositionMode(CompositionMode)
300     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceOver));
301     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceOver), obj1.compositionMode());
302     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOver));
303     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOver), obj1.compositionMode());
304     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Clear));
305     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Clear), obj1.compositionMode());
306     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Source));
307     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Source), obj1.compositionMode());
308     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Destination));
309     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Destination), obj1.compositionMode());
310     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceIn));
311     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceIn), obj1.compositionMode());
312     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationIn));
313     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationIn), obj1.compositionMode());
314     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceOut));
315     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceOut), obj1.compositionMode());
316     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOut));
317     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOut), obj1.compositionMode());
318     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceAtop));
319     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceAtop), obj1.compositionMode());
320     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationAtop));
321     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationAtop), obj1.compositionMode());
322     obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Xor));
323     QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Xor), obj1.compositionMode());
324
325     // const QPen & QPainter::pen()
326     // void QPainter::setPen(const QPen &)
327     QPen var3(Qt::red);
328     obj1.setPen(var3);
329     QCOMPARE(var3, obj1.pen());
330     obj1.setPen(QPen());
331     QCOMPARE(QPen(), obj1.pen());
332
333     // const QBrush & QPainter::brush()
334     // void QPainter::setBrush(const QBrush &)
335     QBrush var4(Qt::red);
336     obj1.setBrush(var4);
337     QCOMPARE(var4, obj1.brush());
338     obj1.setBrush(QBrush());
339     QCOMPARE(QBrush(), obj1.brush());
340
341     // const QBrush & QPainter::background()
342     // void QPainter::setBackground(const QBrush &)
343     QBrush var5(Qt::yellow);
344     obj1.setBackground(var5);
345     QCOMPARE(var5, obj1.background());
346     obj1.setBackground(QBrush());
347     QCOMPARE(QBrush(), obj1.background());
348
349     // bool QPainter::matrixEnabled()
350     // void QPainter::setMatrixEnabled(bool)
351     obj1.setMatrixEnabled(false);
352     QCOMPARE(false, obj1.matrixEnabled());
353     obj1.setMatrixEnabled(true);
354     QCOMPARE(true, obj1.matrixEnabled());
355
356     // bool QPainter::viewTransformEnabled()
357     // void QPainter::setViewTransformEnabled(bool)
358     obj1.setViewTransformEnabled(false);
359     QCOMPARE(false, obj1.viewTransformEnabled());
360     obj1.setViewTransformEnabled(true);
361     QCOMPARE(true, obj1.viewTransformEnabled());
362 }
363
364 Q_DECLARE_METATYPE(QPixmap)
365 Q_DECLARE_METATYPE(QPolygon)
366 Q_DECLARE_METATYPE(QBrush)
367 Q_DECLARE_METATYPE(QPen)
368 Q_DECLARE_METATYPE(QFont)
369 Q_DECLARE_METATYPE(QColor)
370 Q_DECLARE_METATYPE(QRegion)
371
372 tst_QPainter::tst_QPainter()
373 {
374     // QtTestCase sets this to false, but this turns off alpha pixmaps on Unix.
375     QGuiApplication::setDesktopSettingsAware(true);
376 }
377
378 tst_QPainter::~tst_QPainter()
379 {
380 }
381
382 void tst_QPainter::init()
383 {
384 }
385
386 void tst_QPainter::cleanup()
387 {
388 }
389
390 void tst_QPainter::cleanupTestCase()
391 {
392     QFile::remove(QLatin1String("dest.png"));
393     QFile::remove(QLatin1String("expected.png"));
394     QFile::remove(QLatin1String("foo.png"));
395 }
396
397 static const char* const maskSource_data[] = {
398 "16 13 6 1",
399 ". c None",
400 "d c #000000",
401 "# c #999999",
402 "c c #cccccc",
403 "b c #ffff00",
404 "a c #ffffff",
405 "...#####........",
406 "..#aaaaa#.......",
407 ".#abcbcba######.",
408 ".#acbcbcaaaaaa#d",
409 ".#abcbcbcbcbcb#d",
410 "#############b#d",
411 "#aaaaaaaaaa##c#d",
412 "#abcbcbcbcbbd##d",
413 ".#abcbcbcbcbcd#d",
414 ".#acbcbcbcbcbd#d",
415 "..#acbcbcbcbb#dd",
416 "..#############d",
417 "...ddddddddddddd"};
418
419 static const char* const maskResult_data[] = {
420 "16 13 6 1",
421 ". c #ff0000",
422 "d c #000000",
423 "# c #999999",
424 "c c #cccccc",
425 "b c #ffff00",
426 "a c #ffffff",
427 "...#####........",
428 "..#aaaaa#.......",
429 ".#abcbcba######.",
430 ".#acbcbcaaaaaa#d",
431 ".#abcbcbcbcbcb#d",
432 "#############b#d",
433 "#aaaaaaaaaa##c#d",
434 "#abcbcbcbcbbd##d",
435 ".#abcbcbcbcbcd#d",
436 ".#acbcbcbcbcbd#d",
437 "..#acbcbcbcbb#dd",
438 "..#############d",
439 "...ddddddddddddd"};
440
441
442 #ifndef QT_NO_WIDGETS
443 void tst_QPainter::drawPixmap_comp_data()
444 {
445     if (qApp->desktop()->depth() < 24)
446         QSKIP("Test only works on 32 bit displays");
447
448     QTest::addColumn<uint>("dest");
449     QTest::addColumn<uint>("source");
450
451     QTest::newRow("0% on 0%, 1")           << 0x00000000u<< 0x00000000u;
452     QTest::newRow("0% on 0%, 2")           << 0x00007fffu << 0x00ff007fu;
453
454     QTest::newRow("50% on a=0%")           << 0x00000000u << 0x7fff0000u;
455     QTest::newRow("50% on a=50%")          << 0x7f000000u << 0x7fff0000u;
456     QTest::newRow("50% on deadbeef")      << 0xdeafbeefu <<  0x7fff0000u;
457     QTest::newRow("deadbeef on a=0%")      << 0x00000000u << 0xdeadbeefu;
458     QTest::newRow("deadbeef on a=50%")     << 0x7f000000u << 0xdeadbeefu;
459     QTest::newRow("50% blue on 50% red")   << 0x7fff0000u << 0x7f0000ffu;
460     QTest::newRow("50% blue on 50% green") << 0x7f00ff00u << 0x7f0000ffu;
461     QTest::newRow("50% red on 50% green")  << 0x7f00ff00u << 0x7fff0000u;
462     QTest::newRow("0% on 50%")             << 0x7fff00ffu << 0x00ffffffu;
463     QTest::newRow("100% on deadbeef")      << 0xdeafbeefu << 0xffabcdefu;
464     QTest::newRow("100% on a=0%")           << 0x00000000u << 0xffabcdefu;
465 }
466
467 QRgb qt_compose_alpha(QRgb source, QRgb dest)
468 {
469     int r1 = qRed(dest), g1 = qGreen(dest), b1 = qBlue(dest), a1 = qAlpha(dest);
470     int r2 = qRed(source), g2 = qGreen(source), b2 = qBlue(source), a2 = qAlpha(source);
471
472     int alpha = qMin(a2 + ((255 - a2) * a1 + 127) / 255, 255);
473     if (alpha == 0)
474         return qRgba(0, 0, 0, 0);
475
476     return qRgba(
477         qMin((r2 * a2 + (255 - a2) * r1 * a1 / 255) / alpha, 255),
478         qMin((g2 * a2 + (255 - a2) * g1 * a1 / 255) / alpha, 255),
479         qMin((b2 * a2 + (255 - a2) * b1 * a1 / 255) / alpha, 255),
480         alpha);
481 }
482
483 /* Tests that drawing masked pixmaps works
484 */
485 void tst_QPainter::drawPixmap_comp()
486 {
487 #ifdef Q_OS_MAC
488     QSKIP("Mac has other ideas about alpha composition");
489 #endif
490     QFETCH(uint, dest);
491     QFETCH(uint, source);
492
493     QRgb expected = qt_compose_alpha(source, dest);
494
495     QColor c1(qRed(dest), qGreen(dest), qBlue(dest), qAlpha(dest));
496     QColor c2(qRed(source), qGreen(source), qBlue(source), qAlpha(source));
497
498     QPixmap destPm(10, 10), srcPm(10, 10);
499     destPm.fill(c1);
500     srcPm.fill(c2);
501
502 #if defined(Q_WS_X11)
503     if (!destPm.x11PictureHandle())
504         QSKIP("Requires XRender support");
505 #endif
506
507     QPainter p(&destPm);
508     p.drawPixmap(0, 0, srcPm);
509     p.end();
510
511     QImage result = destPm.toImage().convertToFormat(QImage::Format_ARGB32);
512     bool different = false;
513     for (int y=0; y<result.height(); ++y)
514         for (int x=0; x<result.width(); ++x) {
515             bool diff;
516             if (qAlpha(expected) == 0) {
517                 diff = qAlpha(result.pixel(x, y)) != 0;
518             } else {
519                 // Compensate for possible roundoff / platform fudge
520                 int off = 1;
521                 QRgb pix = result.pixel(x, y);
522                 diff = (qAbs(qRed(pix) - qRed(expected)) > off)
523                              || (qAbs(qGreen(pix) - qGreen(expected)) > off)
524                              || (qAbs(qBlue(pix) - qBlue(expected)) > off)
525                              || (qAbs(qAlpha(pix) - qAlpha(expected)) > off);
526             }
527             if (diff && !different)
528                 qDebug( "Different at %d,%d pixel [%d,%d,%d,%d] expected [%d,%d,%d,%d]", x, y,
529                         qRed(result.pixel(x, y)), qGreen(result.pixel(x, y)),
530                         qBlue(result.pixel(x, y)), qAlpha(result.pixel(x, y)),
531                         qRed(expected), qGreen(expected), qBlue(expected), qAlpha(expected));
532             different |= diff;
533         }
534
535     QVERIFY(!different);
536 }
537 #endif
538
539 void tst_QPainter::saveAndRestore_data()
540 {
541     QTest::addColumn<QFont>("font");
542     QTest::addColumn<QPen>("pen");
543     QTest::addColumn<QBrush>("brush");
544     QTest::addColumn<QColor>("backgroundColor");
545     QTest::addColumn<int>("backgroundMode");
546     QTest::addColumn<QPoint>("brushOrigin");
547     QTest::addColumn<QRegion>("clipRegion");
548     QTest::addColumn<QRect>("window");
549     QTest::addColumn<QRect>("viewport");
550
551     QPixmap pixmap(1, 1);
552     QPainter p(&pixmap);
553     QFont font = p.font();
554     QPen pen = p.pen();
555     QBrush brush = p.brush();
556     QColor backgroundColor = p.background().color();
557     Qt::BGMode backgroundMode = p.backgroundMode();
558     QPoint brushOrigin = p.brushOrigin();
559     QRegion clipRegion = p.clipRegion();
560     QRect window = p.window();
561     QRect viewport = p.viewport();
562
563     QTest::newRow("Original") << font << pen << brush << backgroundColor << int(backgroundMode)
564             << brushOrigin << clipRegion << window << viewport;
565
566     QFont font2 = font;
567     font2.setPointSize( 24 );
568     QTest::newRow("Modified font.pointSize, brush, backgroundColor, backgroundMode")
569             << font2 << pen << QBrush(Qt::red) << QColor(Qt::blue) << int(Qt::TransparentMode)
570             << brushOrigin << clipRegion << window << viewport;
571
572     font2 = font;
573     font2.setPixelSize( 20 );
574     QTest::newRow("Modified font.pixelSize, brushOrigin, pos")
575             << font2 << pen << brush << backgroundColor << int(backgroundMode)
576             << QPoint( 50, 32 ) << clipRegion << window << viewport;
577
578     QTest::newRow("Modified clipRegion, window, viewport")
579             << font << pen << brush << backgroundColor << int(backgroundMode)
580             << brushOrigin << clipRegion.subtracted(QRect(10,10,50,30))
581             << QRect(-500, -500, 500, 500 ) << QRect( 0, 0, 50, 50 );
582 }
583
584 void tst_QPainter::saveAndRestore()
585 {
586     QFETCH( QFont, font );
587     QFETCH( QPen, pen );
588     QFETCH( QBrush, brush );
589     QFETCH( QColor, backgroundColor );
590     QFETCH( int, backgroundMode );
591     QFETCH( QPoint, brushOrigin );
592     QFETCH( QRegion, clipRegion );
593     QFETCH( QRect, window );
594     QFETCH( QRect, viewport );
595
596     QPixmap pixmap(1, 1);
597     QPainter painter(&pixmap);
598
599     QFont font_org = painter.font();
600     QPen pen_org = painter.pen();
601     QBrush brush_org = painter.brush();
602     QColor backgroundColor_org = painter.background().color();
603     Qt::BGMode backgroundMode_org = painter.backgroundMode();
604     QPoint brushOrigin_org = painter.brushOrigin();
605     QRegion clipRegion_org = painter.clipRegion();
606     QRect window_org = painter.window();
607     QRect viewport_org = painter.viewport();
608
609     painter.save();
610     painter.setFont( font );
611     painter.setPen( QPen(pen) );
612     painter.setBrush( brush );
613     painter.setBackground( backgroundColor );
614     painter.setBackgroundMode( (Qt::BGMode)backgroundMode );
615     painter.setBrushOrigin( brushOrigin );
616     painter.setClipRegion( clipRegion );
617     painter.setWindow( window );
618     painter.setViewport( viewport );
619     painter.restore();
620
621     QCOMPARE( painter.font(), font_org );
622     QCOMPARE( painter.font().pointSize(), font_org.pointSize() );
623     QCOMPARE( painter.font().pixelSize(), font_org.pixelSize() );
624     QCOMPARE( painter.pen(), pen_org );
625     QCOMPARE( painter.brush(), brush_org );
626     QCOMPARE( painter.background().color(), backgroundColor_org );
627     QCOMPARE( painter.backgroundMode(), backgroundMode_org );
628     QCOMPARE( painter.brushOrigin(), brushOrigin_org );
629     QCOMPARE( painter.clipRegion(), clipRegion_org );
630     QCOMPARE( painter.window(), window_org );
631     QCOMPARE( painter.viewport(), viewport_org );
632 }
633
634 /*
635    Helper functions
636 */
637
638 QColor tst_QPainter::baseColor( int k, int intensity )
639 {
640     int r = ( k & 1 ) * intensity;
641     int g = ( (k>>1) & 1 ) * intensity;
642     int b = ( (k>>2) & 1 ) * intensity;
643     return QColor( r, g, b );
644 }
645
646 QImage tst_QPainter::getResImage( const QString &dir, const QString &addition, const QString &extension )
647 {
648     QImage res;
649     QString resFilename  = dir + QString( "/res_%1." ).arg( addition ) + extension;
650     if ( !res.load( resFilename ) ) {
651         QWARN(QString("Could not load result data %s %1").arg(resFilename).toLatin1());
652         return QImage();
653     }
654     return res;
655 }
656
657 QBitmap tst_QPainter::getBitmap( const QString &dir, const QString &filename, bool mask )
658 {
659     QBitmap bm;
660     QString bmFilename = dir + QString( "/%1.xbm" ).arg( filename );
661     if ( !bm.load( bmFilename ) ) {
662         QWARN(QString("Could not load bitmap '%1'").arg(bmFilename).toLatin1());
663         return QBitmap();
664     }
665     if ( mask ) {
666         QBitmap mask;
667         QString maskFilename = dir + QString( "/%1-mask.xbm" ).arg( filename );
668         if ( !mask.load( maskFilename ) ) {
669         QWARN(QString("Could not load mask '%1'").arg(maskFilename).toLatin1());
670         return QBitmap();
671         }
672         bm.setMask( mask );
673     }
674     return bm;
675 }
676
677 static int getPaintedPixels(const QImage &image, const QColor &background)
678 {
679     uint color = background.rgba();
680
681     int pixels = 0;
682
683     for (int y = 0; y < image.height(); ++y)
684         for (int x = 0; x < image.width(); ++x)
685             if (image.pixel(x, y) != color)
686                 ++pixels;
687
688     return pixels;
689 }
690
691 static QRect getPaintedSize(const QImage &image, const QColor &background)
692 {
693     // not the fastest but at least it works..
694     int xmin = image.width() + 1;
695     int xmax = -1;
696     int ymin = image.height() +1;
697     int ymax = -1;
698
699     uint color = background.rgba();
700
701     for ( int y = 0; y < image.height(); ++y ) {
702         for ( int x = 0; x < image.width(); ++x ) {
703             QRgb pixel = image.pixel( x, y );
704             if ( pixel != color && x < xmin )
705                 xmin = x;
706             if ( pixel != color && x > xmax )
707                 xmax = x;
708             if ( pixel != color && y < ymin )
709                 ymin = y;
710             if ( pixel != color && y > ymax )
711                 ymax = y;
712         }
713     }
714
715     return QRect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
716 }
717
718 static QRect getPaintedSize(const QPixmap &pm, const QColor &background)
719 {
720     return getPaintedSize(pm.toImage(), background);
721 }
722
723 #ifndef QT_NO_WIDGETS
724 void tst_QPainter::initFrom()
725 {
726     QWidget *widget = new QWidget();
727     QPalette pal = widget->palette();
728     pal.setColor(QPalette::Foreground, QColor(255, 0, 0));
729     pal.setBrush(QPalette::Background, QColor(0, 255, 0));
730     widget->setPalette(pal);
731
732     QFont font = widget->font();
733     font.setPointSize(26);
734     font.setItalic(true);
735     widget->setFont(font);
736
737     QPixmap pm(100, 100);
738     QPainter p(&pm);
739     p.initFrom(widget);
740
741     QCOMPARE(p.font(), font);
742     QCOMPARE(p.pen().color(), pal.color(QPalette::Foreground));
743     QCOMPARE(p.background(), pal.background());
744
745     delete widget;
746 }
747
748 void tst_QPainter::drawBorderPixmap()
749 {
750     QPixmap src(79,79);
751     src.fill(Qt::transparent);
752
753     QImage pm(200,200,QImage::Format_RGB32);
754     QPainter p(&pm);
755     p.setTransform(QTransform(-1,0,0,-1,173.5,153.5));
756     qDrawBorderPixmap(&p, QRect(0,0,75,105), QMargins(39,39,39,39), src, QRect(0,0,79,79), QMargins(39,39,39,39),
757                        QTileRules(Qt::StretchTile,Qt::StretchTile), 0);
758 }
759 #endif
760
761 void tst_QPainter::drawPixmapFragments()
762 {
763     QPixmap origPixmap(20, 20);
764     QPixmap resPixmap(20, 20);
765     QPainter::PixmapFragment fragments[4] = { {15, 15,  0,  0, 10, 10, 1, 1, 0, 1},
766                                               { 5, 15, 10,  0, 10, 10, 1, 1, 0, 1},
767                                               {15,  5,  0, 10, 10, 10, 1, 1, 0, 1},
768                                               { 5,  5, 10, 10, 10, 10, 1, 1, 0, 1} };
769     {
770         QPainter p(&origPixmap);
771         p.fillRect(0, 0, 10, 10, Qt::red);
772         p.fillRect(10, 0, 10, 10, Qt::green);
773         p.fillRect(0, 10, 10, 10, Qt::blue);
774         p.fillRect(10, 10, 10, 10, Qt::yellow);
775     }
776     {
777         QPainter p(&resPixmap);
778         p.drawPixmapFragments(fragments, 4, origPixmap);
779     }
780
781     QImage origImage = origPixmap.toImage().convertToFormat(QImage::Format_ARGB32);
782     QImage resImage = resPixmap.toImage().convertToFormat(QImage::Format_ARGB32);
783
784     QVERIFY(resImage.size() == resPixmap.size());
785     QVERIFY(resImage.pixel(5, 5) == origImage.pixel(15, 15));
786     QVERIFY(resImage.pixel(5, 15) == origImage.pixel(15, 5));
787     QVERIFY(resImage.pixel(15, 5) == origImage.pixel(5, 15));
788     QVERIFY(resImage.pixel(15, 15) == origImage.pixel(5, 5));
789
790
791     QPainter::PixmapFragment fragment = QPainter::PixmapFragment::create(QPointF(20, 20), QRectF(30, 30, 2, 2));
792     QVERIFY(fragment.x == 20);
793     QVERIFY(fragment.y == 20);
794     QVERIFY(fragment.sourceLeft == 30);
795     QVERIFY(fragment.sourceTop == 30);
796     QVERIFY(fragment.width == 2);
797     QVERIFY(fragment.height == 2);
798     QVERIFY(fragment.scaleX == 1);
799     QVERIFY(fragment.scaleY == 1);
800     QVERIFY(fragment.rotation == 0);
801     QVERIFY(fragment.opacity == 1);
802 }
803
804 void tst_QPainter::drawLine_data()
805 {
806     QTest::addColumn<QLine>("line");
807
808     QTest::newRow("0-45") << QLine(0, 20, 100, 0);
809     QTest::newRow("45-90") << QLine(0, 100, 20, 0);
810     QTest::newRow("90-135") << QLine(20, 100, 0, 0);
811     QTest::newRow("135-180") << QLine(100, 20, 0, 0);
812     QTest::newRow("180-225") << QLine(100, 0, 0, 20);
813     QTest::newRow("225-270") << QLine(20, 0, 0, 100);
814     QTest::newRow("270-315") << QLine(0, 0, 20, 100);
815     QTest::newRow("315-360") << QLine(0, 0, 100, 20);
816 }
817
818 void tst_QPainter::drawLine()
819 {
820     const int offset = 5;
821     const int epsilon = 1; // allow for one pixel difference
822
823     QFETCH(QLine, line);
824
825     QPixmap pixmapUnclipped(qMin(line.x1(), line.x2())
826                             + 2*offset + qAbs(line.dx()),
827                             qMin(line.y1(), line.y2())
828                             + 2*offset + qAbs(line.dy()));
829
830     { // unclipped
831         pixmapUnclipped.fill(Qt::white);
832         QPainter p(&pixmapUnclipped);
833         p.setRenderHint(QPainter::Qt4CompatiblePainting);
834         p.translate(offset, offset);
835         p.setPen(QPen(Qt::black));
836         p.drawLine(line);
837         p.end();
838
839         const QRect painted = getPaintedSize(pixmapUnclipped, Qt::white);
840
841         QLine l = line;
842         l.translate(offset, offset);
843         QVERIFY(qAbs(painted.width() - qAbs(l.dx())) <= epsilon);
844         QVERIFY(qAbs(painted.height() - qAbs(l.dy())) <= epsilon);
845         QVERIFY(qAbs(painted.top() - qMin(l.y1(), l.y2())) <= epsilon);
846         QVERIFY(qAbs(painted.left() - qMin(l.x1(), l.x2())) <= epsilon);
847         QVERIFY(qAbs(painted.bottom() - qMax(l.y1(), l.y2())) <= epsilon);
848         QVERIFY(qAbs(painted.right() - qMax(l.x1(), l.x2())) <= epsilon);
849     }
850
851     QPixmap pixmapClipped(qMin(line.x1(), line.x2())
852                           + 2*offset + qAbs(line.dx()),
853                           qMin(line.y1(), line.y2())
854                           + 2*offset + qAbs(line.dy()));
855     { // clipped
856         const QRect clip = QRect(line.p1(), line.p2()).normalized();
857
858         pixmapClipped.fill(Qt::white);
859         QPainter p(&pixmapClipped);
860         p.setRenderHint(QPainter::Qt4CompatiblePainting);
861         p.translate(offset, offset);
862         p.setClipRect(clip);
863         p.setPen(QPen(Qt::black));
864         p.drawLine(line);
865         p.end();
866     }
867
868     const QImage unclipped = pixmapUnclipped.toImage();
869     const QImage clipped = pixmapClipped.toImage();
870     QCOMPARE(unclipped, clipped);
871 }
872
873 void tst_QPainter::drawLine_clipped()
874 {
875     QImage image(16, 1, QImage::Format_ARGB32_Premultiplied);
876     image.fill(0x0);
877
878     QPainter p(&image);
879     p.setPen(QPen(Qt::black, 10));
880
881     // this should fill the whole image
882     p.drawLine(-1, -1, 17, 1);
883     p.end();
884
885     for (int x = 0; x < 16; ++x)
886         QCOMPARE(image.pixel(x, 0), 0xff000000);
887 }
888
889 void tst_QPainter::drawLine_task121143()
890 {
891     QPen pen(Qt::black);
892
893     QImage image(5, 5, QImage::Format_ARGB32_Premultiplied);
894     image.fill(0xffffffff);
895     QPainter p(&image);
896     p.setPen(pen);
897     p.setRenderHint(QPainter::Qt4CompatiblePainting);
898     p.drawLine(QLine(0, 0+4, 0+4, 0));
899     p.end();
900
901     QImage expected(5, 5, QImage::Format_ARGB32_Premultiplied);
902     expected.fill(0xffffffff);
903     for (int x = 0; x < 5; ++x)
904         expected.setPixel(x, 5-x-1, pen.color().rgb());
905
906     QCOMPARE(image, expected);
907 }
908
909 void tst_QPainter::drawLine_task190634()
910 {
911     QPen pen(Qt::black, 3);
912
913     QImage image(32, 32, QImage::Format_ARGB32_Premultiplied);
914     QPainter p(&image);
915     p.fillRect(0, 0, image.width(), image.height(), Qt::white);
916
917     p.setPen(pen);
918     p.drawLine(QLineF(2, -1.6, 10, -1.6));
919     p.end();
920
921     const uint *data = reinterpret_cast<uint *>(image.bits());
922
923     for (int i = 0; i < image.width() * image.height(); ++i)
924         QCOMPARE(data[i], 0xffffffff);
925
926     p.begin(&image);
927     p.fillRect(0, 0, image.width(), image.height(), Qt::white);
928
929     p.setPen(pen);
930     p.drawLine(QLineF(-1.6, 2, -1.6, 10));
931     p.end();
932
933     data = reinterpret_cast<uint *>(image.bits());
934
935     for (int i = 0; i < image.width() * image.height(); ++i)
936         QCOMPARE(data[i], 0xffffffff);
937
938     p.begin(&image);
939     p.fillRect(0, 0, image.width(), image.height(), Qt::white);
940
941     p.setPen(pen);
942     p.drawLine( QPoint(2,-2), QPoint(3,-5) );
943     p.end();
944
945     data = reinterpret_cast<uint *>(image.bits());
946
947     for (int i = 0; i < image.width() * image.height(); ++i)
948         QCOMPARE(data[i], 0xffffffff);
949 }
950
951 void tst_QPainter::drawLine_task229459()
952 {
953     QImage image(32, 32, QImage::Format_ARGB32_Premultiplied);
954     image.fill(0x0);
955     QPen pen(Qt::black, 64);
956
957     QPainter p(&image);
958     p.setPen(pen);
959     p.drawLine(-8, -8, 10000000, 10000000);
960     p.end();
961
962     QImage expected = image;
963     expected.fill(0xff000000);
964
965     QCOMPARE(image, expected);
966 }
967
968 void tst_QPainter::drawLine_task234891()
969 {
970     QImage img(100, 1000, QImage::Format_ARGB32_Premultiplied);
971     img.fill(0x0);
972     QImage expected = img;
973
974     QPainter p(&img);
975     p.setPen(QPen(QBrush(QColor(255,0,0)), 6));
976     p.drawLine(QPointF(25000,100),QPointF(30000,105));
977
978     p.setPen(QPen(QBrush(QColor(0,255,0)), 6));
979     p.drawLine(QPointF(30000,150),QPointF(35000,155));
980
981     p.setPen(QPen(QBrush(QColor(0,0,255)), 6));
982     p.drawLine(QPointF(65000,200),QPointF(66000,205));
983
984     QCOMPARE(expected, img);
985 }
986
987 void tst_QPainter::drawLine_task216948()
988 {
989     QImage img(1, 10, QImage::Format_ARGB32_Premultiplied);
990     img.fill(0x0);
991
992     QPainter p(&img);
993     QLine line(10, 0, 10, 10);
994     p.translate(-10, 0);
995     p.drawLine(line);
996     p.end();
997
998     for (int i = 0; i < img.height(); ++i)
999         QCOMPARE(img.pixel(0, i), QColor(Qt::black).rgba());
1000 }
1001
1002 void tst_QPainter::drawRect()
1003 {
1004     QFETCH(QRect, rect);
1005     QFETCH(bool, usePen);
1006
1007     QPixmap pixmap(rect.x() + rect.width() + 10,
1008                    rect.y() + rect.height() + 10);
1009     {
1010         pixmap.fill(Qt::white);
1011         QPainter p(&pixmap);
1012         p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen));
1013         p.setBrush(Qt::black);
1014         p.drawRect(rect);
1015         p.end();
1016
1017         int increment = usePen ? 1 : 0;
1018
1019         const QRect painted = getPaintedSize(pixmap, Qt::white);
1020         QCOMPARE(painted.width(), rect.width() + increment);
1021         QCOMPARE(painted.height(), rect.height() + increment);
1022     }
1023 }
1024
1025 void tst_QPainter::drawRect2()
1026 {
1027     QImage image(64, 64, QImage::Format_ARGB32_Premultiplied);
1028     {
1029         image.fill(0xffffffff);
1030
1031         QTransform transform(0.368567, 0, 0, 0, 0.368567, 0, 0.0289, 0.0289, 1);
1032
1033         QPainter p(&image);
1034         p.setRenderHint(QPainter::Qt4CompatiblePainting);
1035         p.setTransform(transform);
1036         p.setBrush(Qt::red);
1037         p.setPen(Qt::NoPen);
1038         p.drawRect(QRect(14, 14, 39, 39));
1039         p.end();
1040
1041         QRect fill = getPaintedSize(image, Qt::white);
1042         image.fill(0xffffffff);
1043
1044         p.begin(&image);
1045         p.setRenderHint(QPainter::Qt4CompatiblePainting);
1046         p.setTransform(transform);
1047         p.drawRect(QRect(14, 14, 39, 39));
1048         p.end();
1049
1050         QRect stroke = getPaintedSize(image, Qt::white);
1051         QCOMPARE(stroke.adjusted(1, 1, 0, 0), fill.adjusted(0, 0, 1, 1));
1052     }
1053 }
1054
1055 void tst_QPainter::fillRect()
1056 {
1057     QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
1058     image.fill(QColor(0, 0, 0, 0).rgba());
1059
1060     QPainter p(&image);
1061
1062     p.fillRect(0, 0, 100, 100, QColor(255, 0, 0, 127));
1063
1064 //    pixmap.save("bla1.png", "PNG");
1065     QCOMPARE(getPaintedSize(image, QColor(0, 0, 0, 0)),
1066              QRect(0, 0, 100, 100));
1067     QCOMPARE(getPaintedSize(image, QColor(127, 0, 0, 127)).isValid(),
1068              QRect().isValid());
1069
1070     p.setCompositionMode(QPainter::CompositionMode_SourceIn);
1071     p.fillRect(50, 0, 50, 100, QColor(0, 0, 255, 255));
1072
1073     QCOMPARE(getPaintedSize(image, QColor(127, 0, 0, 127)),
1074              QRect(50, 0, 50, 100));
1075     QCOMPARE(getPaintedSize(image, QColor(0, 0, 127, 127)),
1076              QRect(0, 0, 50, 100));
1077 }
1078
1079 void tst_QPainter::fillRect2()
1080 {
1081     QRgb background = 0x0;
1082
1083     QImage img(1, 20, QImage::Format_ARGB32_Premultiplied);
1084     img.fill(background);
1085
1086     QPainter p(&img);
1087
1088     QRectF rect(0, 1, 1.2, 18);
1089     p.fillRect(rect, Qt::black);
1090
1091     p.end();
1092
1093     QCOMPARE(img.pixel(0, 0), background);
1094     QCOMPARE(img.pixel(0, img.height() - 1), background);
1095
1096     QCOMPARE(img.pixel(0, 1), img.pixel(0, 2));
1097     QCOMPARE(img.pixel(0, img.height() - 2), img.pixel(0, img.height() - 3));
1098 }
1099
1100 void tst_QPainter::fillRect3()
1101 {
1102     QImage img(1, 1, QImage::Format_ARGB32_Premultiplied);
1103     img.fill(QColor(Qt::black).rgba());
1104
1105     QPainter p(&img);
1106     p.setCompositionMode(QPainter::CompositionMode_Source);
1107     p.fillRect(img.rect(), Qt::transparent);
1108     p.end();
1109
1110     QCOMPARE(img.pixel(0, 0), 0U);
1111 }
1112
1113 void tst_QPainter::fillRect4()
1114 {
1115     QImage image(100, 1, QImage::Format_ARGB32_Premultiplied);
1116     image.fill(0x0);
1117
1118     QImage expected = image;
1119     expected.fill(0xffffffff);
1120
1121     QPainter p(&image);
1122     p.scale(1.1, 1);
1123     p.setPen(Qt::NoPen);
1124
1125     for (int i = 0; i < 33; ++i)
1126         p.fillRect(QRectF(3 * i, 0, 3, 1), Qt::white);
1127
1128     p.end();
1129
1130     QCOMPARE(image, expected);
1131 }
1132
1133 void tst_QPainter::drawPath_data()
1134 {
1135     QTest::addColumn<QPainterPath>("path");
1136     QTest::addColumn<QRect>("expectedBounds");
1137     QTest::addColumn<int>("expectedPixels");
1138
1139     {
1140         QPainterPath p;
1141         p.addRect(2, 2, 10, 10);
1142         QTest::newRow("int-aligned rect") << p << QRect(2, 2, 10, 10) << 10 * 10;
1143     }
1144
1145     {
1146         QPainterPath p;
1147         p.addRect(2.25, 2.25, 10, 10);
1148         QTest::newRow("non-aligned rect") << p << QRect(3, 3, 10, 10) << 10 * 10;
1149     }
1150
1151     {
1152         QPainterPath p;
1153         p.addRect(2.25, 2.25, 10.5, 10.5);
1154         QTest::newRow("non-aligned rect 2") << p << QRect(3, 3, 10, 10) << 10 * 10;
1155     }
1156
1157     {
1158         QPainterPath p;
1159         p.addRect(2.5, 2.5, 10, 10);
1160         QTest::newRow("non-aligned rect 3") << p << QRect(3, 3, 10, 10) << 10 * 10;
1161     }
1162
1163     {
1164         QPainterPath p;
1165         p.addRect(2, 2, 10, 10);
1166         p.addRect(4, 4, 6, 6);
1167         QTest::newRow("rect-in-rect") << p << QRect(2, 2, 10, 10) << 10 * 10 - 6 * 6;
1168     }
1169
1170     {
1171         QPainterPath p;
1172         p.addRect(2, 2, 10, 10);
1173         p.addRect(4, 4, 6, 6);
1174         p.addRect(6, 6, 2, 2);
1175         QTest::newRow("rect-in-rect-in-rect") << p << QRect(2, 2, 10, 10) << 10 * 10 - 6 * 6 + 2 * 2;
1176     }
1177 }
1178
1179 void tst_QPainter::drawPath()
1180 {
1181     QFETCH(QPainterPath, path);
1182     QFETCH(QRect, expectedBounds);
1183     QFETCH(int, expectedPixels);
1184
1185     const int offset = 2;
1186
1187     QImage image(expectedBounds.width() + 2 * offset, expectedBounds.height() + 2 * offset,
1188                  QImage::Format_ARGB32_Premultiplied);
1189     image.fill(QColor(Qt::white).rgb());
1190
1191     QPainter p(&image);
1192     p.setRenderHint(QPainter::Qt4CompatiblePainting);
1193     p.setPen(Qt::NoPen);
1194     p.setBrush(Qt::black);
1195     p.translate(offset - expectedBounds.left(), offset - expectedBounds.top());
1196     p.drawPath(path);
1197     p.end();
1198
1199     const QRect paintedBounds = getPaintedSize(image, Qt::white);
1200
1201     QCOMPARE(paintedBounds.x(), offset);
1202     QCOMPARE(paintedBounds.y(), offset);
1203     QCOMPARE(paintedBounds.width(), expectedBounds.width());
1204     QCOMPARE(paintedBounds.height(), expectedBounds.height());
1205
1206     if (expectedPixels != -1) {
1207         int paintedPixels = getPaintedPixels(image, Qt::white);
1208         QCOMPARE(paintedPixels, expectedPixels);
1209     }
1210 }
1211
1212 void tst_QPainter::drawPath2()
1213 {
1214     const int w = 50;
1215
1216     for (int h = 5; h < 200; ++h) {
1217         QPainterPath p1, p2;
1218         p1.lineTo(w, 0);
1219         p1.lineTo(w, h);
1220
1221         p2.lineTo(w, h);
1222         p2.lineTo(0, h);
1223
1224         const int offset = 2;
1225
1226         QImage image(w + 2 * offset, h + 2 * offset,
1227                      QImage::Format_ARGB32_Premultiplied);
1228         image.fill(QColor(Qt::white).rgb());
1229
1230         QPainter p(&image);
1231         p.setPen(Qt::NoPen);
1232         p.setBrush(Qt::black);
1233         p.translate(offset, offset);
1234         p.drawPath(p1);
1235         p.end();
1236
1237         const int p1Pixels = getPaintedPixels(image, Qt::white);
1238
1239         image.fill(QColor(Qt::white).rgb());
1240         p.begin(&image);
1241         p.setPen(Qt::NoPen);
1242         p.setBrush(Qt::black);
1243         p.translate(offset, offset);
1244         p.drawPath(p2);
1245         p.end();
1246
1247         const int p2Pixels = getPaintedPixels(image, Qt::white);
1248
1249         QCOMPARE(p1Pixels + p2Pixels, w * h);
1250     }
1251 }
1252
1253 void tst_QPainter::drawPath3()
1254 {
1255     QImage imgA(100, 100, QImage::Format_RGB32);
1256     imgA.fill(0xffffff);
1257     QImage imgB = imgA;
1258
1259     QPainterPath path;
1260     for (int y = 0; y < imgA.height(); ++y) {
1261         for (int x = 0; x < imgA.width(); ++x) {
1262             if ((x + y) & 1) {
1263                 imgA.setPixel(x, y, 0);
1264                 path.addRect(x, y, 1, 1);
1265             }
1266         }
1267     }
1268
1269     QPainter p(&imgB);
1270     p.setPen(Qt::NoPen);
1271     p.setBrush(Qt::black);
1272
1273     p.drawPath(path);
1274     p.end();
1275
1276     QVERIFY(imgA == imgB);
1277
1278     imgA.invertPixels();
1279     imgB.fill(0xffffff);
1280
1281     p.begin(&imgB);
1282     p.setPen(Qt::NoPen);
1283     p.setBrush(Qt::black);
1284
1285     QRectF rect(0, 0, imgA.width(), imgA.height());
1286     path.addRect(rect.adjusted(-10, -10, 10, 10));
1287     p.drawPath(path);
1288     p.end();
1289
1290     QVERIFY(imgA == imgB);
1291
1292     path.setFillRule(Qt::WindingFill);
1293     imgB.fill(0xffffff);
1294
1295     p.begin(&imgB);
1296     p.setPen(Qt::NoPen);
1297     p.setBrush(Qt::black);
1298     QRect clip = rect.adjusted(10, 10, -10, -10).toRect();
1299     p.setClipRect(clip);
1300     p.drawPath(path);
1301     p.end();
1302
1303     QCOMPARE(getPaintedPixels(imgB, Qt::white), clip.width() * clip.height());
1304 }
1305
1306 void tst_QPainter::drawEllipse_data()
1307 {
1308     QTest::addColumn<QSize>("size");
1309     QTest::addColumn<bool>("usePen");
1310
1311     // The current drawEllipse algorithm (drawEllipse_midpoint_i in
1312     // qpaintengine_raster.cpp) draws ellipses that are too wide if the
1313     // ratio between width and hight is too large/small (task 114874). Those
1314     // ratios are therefore currently avoided.
1315     for (int w = 10; w < 128; w += 7) {
1316         for (int h = w/2; h < qMin(2*w, 128); h += 13) {
1317             QString s = QString("%1x%2").arg(w).arg(h);
1318             QTest::newRow(QString("%1 with pen").arg(s).toLatin1()) << QSize(w, h) << true;
1319             QTest::newRow(QString("%1 no pen").arg(s).toLatin1()) << QSize(w, h) << false;
1320         }
1321     }
1322 }
1323
1324 void tst_QPainter::drawEllipse()
1325 {
1326     QFETCH(QSize, size);
1327     QFETCH(bool, usePen);
1328
1329     const int offset = 10;
1330     QRect rect(QPoint(offset, offset), size);
1331
1332     QImage image(size.width() + 2 * offset, size.height() + 2 * offset,
1333                  QImage::Format_ARGB32_Premultiplied);
1334     image.fill(QColor(Qt::white).rgb());
1335
1336     QPainter p(&image);
1337     p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen));
1338     p.setBrush(Qt::black);
1339     p.drawEllipse(rect);
1340     p.end();
1341
1342     QPixmap pixmap = QPixmap::fromImage(image);
1343
1344     const QRect painted = getPaintedSize(pixmap, Qt::white);
1345
1346     QCOMPARE(painted.x(), rect.x());
1347     QCOMPARE(painted.y(), rect.y() + (usePen ? 0 : 1));
1348     QCOMPARE(painted.width(), size.width() + (usePen ? 1 : 0));
1349     QCOMPARE(painted.height(), size.height() + (usePen ? 1 : -1));
1350 }
1351
1352 void tst_QPainter::drawClippedEllipse_data()
1353 {
1354     QTest::addColumn<QRect>("rect");
1355
1356     for (int w = 20; w < 128; w += 7) {
1357         for (int h = w/2; h < qMin(2*w, 128); h += 13) {
1358             QString s = QString("%1x%2").arg(w).arg(h);
1359             QTest::newRow(QString("%1 top").arg(s).toLatin1()) << QRect(0, -h/2, w, h);
1360             QTest::newRow(QString("%1 topright").arg(s).toLatin1()) << QRect(w/2, -h/2, w, h);
1361             QTest::newRow(QString("%1 right").arg(s).toLatin1()) << QRect(w/2, 0, w, h);
1362             QTest::newRow(QString("%1 bottomright").arg(s).toLatin1()) << QRect(w/2, h/2, w, h);
1363             QTest::newRow(QString("%1 bottom").arg(s).toLatin1()) << QRect(0, h/2, w, h);
1364             QTest::newRow(QString("%1 bottomleft").arg(s).toLatin1()) << QRect(-w/2, h/2, w, h);
1365             QTest::newRow(QString("%1 left").arg(s).toLatin1()) << QRect(-w/2, 0, w, h);
1366             QTest::newRow(QString("%1 topleft").arg(s).toLatin1()) << QRect(-w/2, -h/2, w, h);
1367         }
1368     }
1369 }
1370
1371 void tst_QPainter::drawClippedEllipse()
1372 {
1373     QFETCH(QRect, rect);
1374     if (sizeof(qreal) != sizeof(double))
1375         QSKIP("Test only works for qreal==double");
1376     QImage image(rect.width() + 1, rect.height() + 1,
1377                  QImage::Format_ARGB32_Premultiplied);
1378     QRect expected = QRect(rect.x(), rect.y(), rect.width()+1, rect.height()+1)
1379                      & QRect(0, 0, image.width(), image.height());
1380
1381
1382     image.fill(QColor(Qt::white).rgb());
1383     QPainter p(&image);
1384     p.drawEllipse(rect);
1385     p.end();
1386
1387     QPixmap pixmap = QPixmap::fromImage(image);
1388     const QRect painted = getPaintedSize(pixmap, Qt::white);
1389
1390     QCOMPARE(painted.x(), expected.x());
1391     QCOMPARE(painted.y(), expected.y());
1392     QCOMPARE(painted.width(), expected.width());
1393     QCOMPARE(painted.height(), expected.height());
1394
1395 }
1396
1397 void tst_QPainter::drawRoundRect()
1398 {
1399     QFETCH(QRect, rect);
1400     QFETCH(bool, usePen);
1401
1402 #ifdef Q_OS_MAC
1403     if (QTest::currentDataTag() == QByteArray("rect(6, 12, 3, 14) with pen") ||
1404         QTest::currentDataTag() == QByteArray("rect(6, 17, 3, 25) with pen") ||
1405         QTest::currentDataTag() == QByteArray("rect(10, 6, 10, 3) with pen") ||
1406         QTest::currentDataTag() == QByteArray("rect(10, 12, 10, 14) with pen") ||
1407         QTest::currentDataTag() == QByteArray("rect(13, 45, 17, 80) with pen") ||
1408         QTest::currentDataTag() == QByteArray("rect(13, 50, 17, 91) with pen") ||
1409         QTest::currentDataTag() == QByteArray("rect(17, 6, 24, 3) with pen") ||
1410         QTest::currentDataTag() == QByteArray("rect(24, 12, 38, 14) with pen"))
1411         QSKIP("The Mac paint engine is off-by-one on certain rect sizes");
1412 #endif
1413     QPixmap pixmap(rect.x() + rect.width() + 10,
1414                    rect.y() + rect.height() + 10);
1415     {
1416         pixmap.fill(Qt::white);
1417         QPainter p(&pixmap);
1418         p.setRenderHint(QPainter::Qt4CompatiblePainting);
1419         p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen));
1420         p.setBrush(Qt::black);
1421         p.drawRoundRect(rect);
1422         p.end();
1423
1424         int increment = usePen ? 1 : 0;
1425
1426         const QRect painted = getPaintedSize(pixmap, Qt::white);
1427         QCOMPARE(painted.width(), rect.width() + increment);
1428         QCOMPARE(painted.height(), rect.height() + increment);
1429     }
1430 }
1431
1432 Q_DECLARE_METATYPE(QImage::Format)
1433
1434 void tst_QPainter::qimageFormats_data()
1435 {
1436     QTest::addColumn<QImage::Format>("format");
1437     QTest::newRow("QImage::Format_RGB32") << QImage::Format_RGB32;
1438     QTest::newRow("QImage::Format_ARGB32") << QImage::Format_ARGB32;
1439     QTest::newRow("QImage::Format_ARGB32_Premultiplied") << QImage::Format_ARGB32_Premultiplied;
1440     QTest::newRow("QImage::Format_RGB16") << QImage::Format_RGB16;
1441     QTest::newRow("Qimage::Format_ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied;
1442     QTest::newRow("Qimage::Format_RGB666") << QImage::Format_RGB666;
1443     QTest::newRow("Qimage::Format_RGB555") << QImage::Format_RGB555;
1444     QTest::newRow("Qimage::Format_ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied;
1445     QTest::newRow("Qimage::Format_RGB888") << QImage::Format_RGB888;
1446 }
1447
1448 /*
1449     Tests that QPainter can paint on various QImage formats.
1450 */
1451 void tst_QPainter::qimageFormats()
1452 {
1453     QFETCH(QImage::Format, format);
1454
1455     const QSize size(100, 100);
1456     QImage image(size, format);
1457     image.fill(0);
1458
1459     const QColor testColor(Qt::red);
1460     QPainter p(&image);
1461     QVERIFY(p.isActive());
1462     p.setBrush(QBrush(testColor));
1463     p.drawRect(QRect(QPoint(0,0), size));
1464     QCOMPARE(image.pixel(50, 50), testColor.rgb());
1465 }
1466
1467 void tst_QPainter::fillData()
1468 {
1469     QTest::addColumn<QRect>("rect");
1470     QTest::addColumn<bool>("usePen");
1471
1472     for (int w = 3; w < 50; w += 7) {
1473         for (int h = 3; h < 50; h += 11) {
1474             int x = w/2 + 5;
1475             int y = h/2 + 5;
1476             QTest::newRow(QString("rect(%1, %2, %3, %4) with pen").arg(x).arg(y).arg(w).arg(h).toLatin1())
1477                 << QRect(x, y, w, h) << true;
1478             QTest::newRow(QString("rect(%1, %2, %3, %4) no pen").arg(x).arg(y).arg(w).arg(h).toLatin1())
1479                 << QRect(x, y, w, h) << false;
1480         }
1481     }
1482 }
1483
1484 /*
1485     Test that drawline works properly after setWindow has been called.
1486 */
1487 void tst_QPainter::setWindow()
1488 {
1489     QPixmap pixmap(600, 600);
1490     pixmap.fill(QColor(Qt::white));
1491
1492     QPainter painter(&pixmap);
1493     painter.setRenderHint(QPainter::Qt4CompatiblePainting);
1494     painter.setWindow(0, 0, 3, 3);
1495     painter.drawLine(1, 1, 2, 2);
1496
1497     const QRect painted = getPaintedSize(pixmap, Qt::white);
1498     QVERIFY(195 < painted.y() && painted.y() < 205); // correct value is around 200
1499     QVERIFY(195 < painted.height() && painted.height() < 205); // correct value is around 200
1500 }
1501
1502 void tst_QPainter::combinedMatrix()
1503 {
1504     QPixmap pm(64, 64);
1505
1506     QPainter p(&pm);
1507     p.setWindow(0, 0, 1, 1);
1508     p.setViewport(32, 0, 32, 32);
1509
1510     p.translate(0.5, 0.5);
1511
1512     QMatrix cm = p.combinedMatrix();
1513
1514     QPointF pt = QPointF(0, 0) * cm;
1515
1516     QCOMPARE(pt.x(), 48.0);
1517     QCOMPARE(pt.y(), 16.0);
1518 }
1519
1520 void tst_QPainter::textOnTransparentImage()
1521 {
1522     bool foundPixel = false;
1523     QImage image(10, 10, QImage::Format_ARGB32_Premultiplied);
1524     image.fill(qRgba(0, 0, 0, 0)); // transparent
1525     {
1526         QPainter painter(&image);
1527         painter.setPen(QColor(255, 255, 255));
1528         painter.drawText(0, 10, "W");
1529     }
1530     for (int x = 0; x < image.width(); ++x)
1531         for (int y = 0; y < image.height(); ++y)
1532             if (image.pixel(x, y) != 0)
1533                 foundPixel = true;
1534     QVERIFY(foundPixel);
1535 }
1536
1537 void tst_QPainter::renderHints()
1538 {
1539     QImage img(1, 1, QImage::Format_RGB32);
1540
1541     QPainter p(&img);
1542
1543     // Turn off all...
1544     p.setRenderHints(QPainter::RenderHints(0xffffffff), false);
1545     QCOMPARE(p.renderHints(), QPainter::RenderHints(0));
1546
1547     // Single set/get
1548     p.setRenderHint(QPainter::Antialiasing);
1549     QVERIFY(p.renderHints() & QPainter::Antialiasing);
1550
1551     p.setRenderHint(QPainter::Antialiasing, false);
1552     QVERIFY(!(p.renderHints() & QPainter::Antialiasing));
1553
1554     // Multi set/get
1555     p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
1556     QVERIFY(p.renderHints() & (QPainter::Antialiasing | QPainter::SmoothPixmapTransform));
1557
1558     p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false);
1559     QVERIFY(!(p.renderHints() & (QPainter::Antialiasing | QPainter::SmoothPixmapTransform)));
1560 }
1561
1562 int countPixels(const QImage &img, const QRgb &color)
1563 {
1564     int count = 0;
1565     for (int y = 0; y < img.height(); ++y) {
1566         for (int x = 0; x < img.width(); ++x) {
1567             count += ((img.pixel(x, y) & 0xffffff) == color);
1568         }
1569     }
1570     return count;
1571 }
1572
1573 template <typename T>
1574 void testClipping(QImage &img)
1575 {
1576     QPainterPath a, b;
1577     a.addRect(QRect(2, 2, 4, 4));
1578     b.addRect(QRect(4, 4, 4, 4));
1579     QPainter p(&img);
1580
1581     p.end();
1582     img.fill(0x0);
1583     p.begin(&img);
1584     p.setClipPath(a);
1585     p.setClipPath(b, Qt::IntersectClip);
1586
1587     p.setClipping(false);
1588     p.setPen(Qt::NoPen);
1589     p.setBrush(QColor(0xff0000));
1590     p.drawRect(T(0, 0, 10, 10));
1591
1592     p.setClipping(true);
1593     p.setBrush(QColor(0x00ff00));
1594     p.drawRect(T(0, 0, 10, 10));
1595
1596     QCOMPARE(countPixels(img, 0xff0000), 96);
1597     QCOMPARE(countPixels(img, 0x00ff00), 4);
1598 }
1599
1600 void tst_QPainter::disableEnableClipping()
1601 {
1602     QImage img(10, 10, QImage::Format_RGB32);
1603
1604     testClipping<QRectF>(img);
1605     testClipping<QRect>(img);
1606 }
1607
1608 void tst_QPainter::setClipRect()
1609 {
1610     QImage img(10, 10, QImage::Format_RGB32);
1611     // simple test to let valgrind check for buffer overflow
1612     {
1613         QPainter p(&img);
1614         p.setClipRect(-10, -10, 100, 100);
1615         p.fillRect(-10, -10, 100, 100, QBrush(QColor(Qt::red)));
1616     }
1617
1618     // rects with negative width/height
1619     {
1620         QPainter p(&img);
1621         p.setClipRect(QRect(10, 10, -10, 10));
1622         QVERIFY(p.clipRegion().isEmpty());
1623         p.setClipRect(QRect(10, 10, 10, -10));
1624         QVERIFY(p.clipRegion().isEmpty());
1625         p.setClipRect(QRectF(10.5, 10.5, -10.5, 10.5));
1626         QVERIFY(p.clipRegion().isEmpty());
1627         p.setClipRect(QRectF(10.5, 10.5, 10.5, -10.5));
1628         QVERIFY(p.clipRegion().isEmpty());
1629     }
1630 }
1631
1632 /*
1633     This tests the two different clipping approaches in QRasterPaintEngine,
1634     one when using a QRegion and one when using a QPainterPath. They should
1635     give equal results.
1636 */
1637 void tst_QPainter::setEqualClipRegionAndPath_data()
1638 {
1639     QTest::addColumn<QSize>("deviceSize");
1640     QTest::addColumn<QRegion>("region");
1641
1642     QTest::newRow("empty") << QSize(100, 100) << QRegion();
1643     QTest::newRow("simple rect") << QSize(100, 100)
1644                                  << QRegion(QRect(5, 5, 10, 10));
1645
1646     QVector<QRect> rects;
1647     QRegion region;
1648
1649     rects << QRect(5, 5, 10, 10) << QRect(20, 20, 10, 10);
1650     region.setRects(rects.constData(), rects.size());
1651     QTest::newRow("two rects") << QSize(100, 100) << region;
1652
1653     rects.clear();
1654     rects << QRect(5, 5, 10, 10) << QRect(20, 5, 10, 10);
1655     region.setRects(rects.constData(), rects.size());
1656     QTest::newRow("two x-adjacent rects") << QSize(100, 100) << region;
1657
1658     rects.clear();
1659     rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100);
1660     region.setRects(rects.constData(), rects.size());
1661     QTest::newRow("two x-adjacent rects 2") << QSize(100, 100) << region;
1662
1663     rects.clear();
1664     rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100);
1665     region.setRects(rects.constData(), rects.size());
1666     QTest::newRow("two x-adjacent rects 3") << QSize(50, 50) << region;
1667
1668     rects.clear();
1669     rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100);
1670     region.setRects(rects.constData(), rects.size());
1671     QTest::newRow("two x-adjacent rects 4") << QSize(101, 101) << region;
1672
1673     region = QRegion(QRect(0, 0, 200, 200), QRegion::Ellipse);
1674
1675     QTest::newRow("ellipse") << QSize(190, 200) << region;
1676
1677     region ^= QRect(50, 50, 50, 50);
1678     QTest::newRow("ellipse 2") << QSize(200, 200) << region;
1679 }
1680
1681 void tst_QPainter::setEqualClipRegionAndPath()
1682 {
1683     QFETCH(QSize, deviceSize);
1684     QFETCH(QRegion, region);
1685
1686     QPainterPath path;
1687     path.addRegion(region);
1688
1689     QImage img1(deviceSize.width(), deviceSize.height(),
1690                 QImage::Format_ARGB32);
1691     QImage img2(deviceSize.width(), deviceSize.height(),
1692                 QImage::Format_ARGB32);
1693     img1.fill(0x12345678);
1694     img2.fill(0x12345678);
1695
1696     {
1697         QPainter p(&img1);
1698         p.setClipRegion(region);
1699         p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red));
1700     }
1701     {
1702         QPainter p(&img2);
1703         p.setClipPath(path);
1704         p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red));
1705     }
1706
1707     QCOMPARE(img1, img2);
1708
1709     // rotated
1710     img1.fill(0x12345678);
1711     img2.fill(0x12345678);
1712
1713     {
1714         QPainter p(&img1);
1715         p.rotate(25);
1716         p.setClipRegion(region);
1717         p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red));
1718     }
1719     {
1720         QPainter p(&img2);
1721         p.rotate(25);
1722         p.setClipPath(path);
1723         p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red));
1724     }
1725
1726     QCOMPARE(img1, img2);
1727
1728     img1.fill(0x12345678);
1729     img2.fill(0x12345678);
1730
1731     // simple intersectclip
1732     img1.fill(0x12345678);
1733     img2.fill(0x12345678);
1734     {
1735         QPainter p(&img1);
1736         p.setClipRegion(region);
1737         p.setClipRegion(region, Qt::IntersectClip);
1738         p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red));
1739     }
1740     {
1741         QPainter p(&img2);
1742         p.setClipPath(path);
1743         p.setClipPath(path, Qt::IntersectClip);
1744         p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red));
1745     }
1746     QCOMPARE(img1, img2);
1747
1748     img1.fill(0x12345678);
1749     img2.fill(0x12345678);
1750     {
1751         QPainter p(&img1);
1752         p.setClipPath(path);
1753         p.setClipRegion(region, Qt::IntersectClip);
1754         p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red));
1755     }
1756     {
1757         QPainter p(&img2);
1758         p.setClipRegion(region);
1759         p.setClipPath(path, Qt::IntersectClip);
1760         p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red));
1761     }
1762     QCOMPARE(img1, img2);
1763
1764 }
1765
1766 void tst_QPainter::clippedFillPath_data()
1767 {
1768     QTest::addColumn<QSize>("imageSize");
1769     QTest::addColumn<QPainterPath>("path");
1770     QTest::addColumn<QRect>("clipRect");
1771     QTest::addColumn<QBrush>("brush");
1772     QTest::addColumn<QPen>("pen");
1773
1774     QLinearGradient gradient(QPoint(0, 0), QPoint(100, 100));
1775     gradient.setColorAt(0, Qt::red);
1776     gradient.setColorAt(1, Qt::blue);
1777
1778
1779     QPen pen2(QColor(223, 223, 0, 223));
1780     pen2.setWidth(2);
1781
1782     QPainterPath path;
1783     path.addRect(QRect(15, 15, 50, 50));
1784     QTest::newRow("simple rect 0") << QSize(100, 100) << path
1785                                    << QRect(15, 15, 49, 49)
1786                                    << QBrush(Qt::NoBrush)
1787                                    << QPen(Qt::black);
1788     QTest::newRow("simple rect 1") << QSize(100, 100) << path
1789                                    << QRect(15, 15, 50, 50)
1790                                    << QBrush(Qt::NoBrush)
1791                                    << QPen(Qt::black);
1792     QTest::newRow("simple rect 2") << QSize(100, 100) << path
1793                                    << QRect(15, 15, 51, 51)
1794                                    << QBrush(Qt::NoBrush)
1795                                    << QPen(Qt::black);
1796     QTest::newRow("simple rect 3") << QSize(100, 100) << path
1797                                    << QRect(15, 15, 51, 51)
1798                                    << QBrush(QColor(Qt::blue))
1799                                    << QPen(Qt::NoPen);
1800     QTest::newRow("simple rect 4") << QSize(100, 100) << path
1801                                    << QRect(15, 15, 51, 51)
1802                                    << QBrush(gradient)
1803                                    << pen2;
1804
1805     path = QPainterPath();
1806     path.addEllipse(QRect(15, 15, 50, 50));
1807     QTest::newRow("ellipse 0") << QSize(100, 100) << path
1808                                << QRect(15, 15, 49, 49)
1809                                << QBrush(Qt::NoBrush)
1810                                << QPen(Qt::black);
1811     QTest::newRow("ellipse 1") << QSize(100, 100) << path
1812                                << QRect(15, 15, 50, 50)
1813                                << QBrush(Qt::NoBrush)
1814                                << QPen(Qt::black);
1815     QTest::newRow("ellipse 2") << QSize(100, 100) << path
1816                                << QRect(15, 15, 51, 51)
1817                                << QBrush(Qt::NoBrush)
1818                                << QPen(Qt::black);
1819     QTest::newRow("ellipse 3") << QSize(100, 100) << path
1820                                << QRect(15, 15, 51, 51)
1821                                << QBrush(QColor(Qt::blue))
1822                                << QPen(Qt::NoPen);
1823     QTest::newRow("ellipse 4") << QSize(100, 100) << path
1824                                << QRect(15, 15, 51, 51)
1825                                << QBrush(gradient)
1826                                << pen2;
1827
1828     path = QPainterPath();
1829     path.addRoundRect(QRect(15, 15, 50, 50), 20);
1830     QTest::newRow("round rect 0") << QSize(100, 100) << path
1831                                   << QRect(15, 15, 49, 49)
1832                                   << QBrush(Qt::NoBrush)
1833                                   << QPen(Qt::black);
1834     QTest::newRow("round rect 1") << QSize(100, 100) << path
1835                                   << QRect(15, 15, 50, 50)
1836                                   << QBrush(Qt::NoBrush)
1837                                   << QPen(Qt::black);
1838     QTest::newRow("round rect 2") << QSize(100, 100) << path
1839                                   << QRect(15, 15, 51, 51)
1840                                   << QBrush(Qt::NoBrush)
1841                                   << QPen(Qt::black);
1842     QTest::newRow("round rect 3") << QSize(100, 100) << path
1843                                   << QRect(15, 15, 51, 51)
1844                                   << QBrush(QColor(Qt::blue))
1845                                   << QPen(Qt::NoPen);
1846     QTest::newRow("round rect 4") << QSize(100, 100) << path
1847                                   << QRect(15, 15, 51, 51)
1848                                   << QBrush(gradient)
1849                                   << pen2;
1850
1851     path = QPainterPath();
1852     path.moveTo(15, 50);
1853     path.cubicTo(40, 50, 40, 15, 65, 50);
1854     path.lineTo(15, 50);
1855     QTest::newRow("cubic 0") << QSize(100, 100) << path
1856                              << QRect(15, 15, 49, 49)
1857                              << QBrush(Qt::NoBrush)
1858                              << QPen(Qt::black);
1859     QTest::newRow("cubic 1") << QSize(100, 100) << path
1860                              << QRect(15, 15, 50, 50)
1861                              << QBrush(Qt::NoBrush)
1862                              << QPen(Qt::black);
1863     QTest::newRow("cubic 2") << QSize(100, 100) << path
1864                              << QRect(15, 15, 51, 51)
1865                              << QBrush(Qt::NoBrush)
1866                              << QPen(Qt::black);
1867     QTest::newRow("cubic 3") << QSize(100, 100) << path
1868                              << QRect(15, 15, 51, 51)
1869                              << QBrush(QColor(Qt::blue))
1870                              << QPen(Qt::NoPen);
1871     QTest::newRow("cubic 4") << QSize(100, 100) << path
1872                              << QRect(15, 15, 51, 51)
1873                              << QBrush(gradient)
1874                              << pen2;
1875 }
1876
1877 void tst_QPainter::clippedFillPath()
1878 {
1879     QFETCH(QSize, imageSize);
1880     QFETCH(QPainterPath, path);
1881     QFETCH(QRect, clipRect);
1882     QPainterPath clipPath;
1883     clipPath.addRect(clipRect);
1884     QFETCH(QBrush, brush);
1885     QFETCH(QPen, pen);
1886
1887     const int width = imageSize.width();
1888     const int height = imageSize.height();
1889
1890     QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied);
1891     clippedRect.fill(0x12345678);
1892     {
1893         QPainter painter(&clippedRect);
1894         painter.setPen(pen);
1895         painter.setBrush(brush);
1896         painter.setClipRect(clipRect);
1897         painter.drawPath(path);
1898     }
1899
1900     QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied);
1901     clippedPath.fill(0x12345678);
1902     {
1903         QPainter painter(&clippedPath);
1904         painter.setPen(pen);
1905         painter.setBrush(brush);
1906         painter.setClipPath(clipPath);
1907         painter.drawPath(path);
1908     }
1909
1910     QCOMPARE(clippedRect, clippedPath);
1911
1912     // repeat with antialiasing
1913
1914     clippedRect.fill(0x12345678);
1915     {
1916         QPainter painter(&clippedRect);
1917         painter.setRenderHint(QPainter::Antialiasing);
1918         painter.setPen(pen);
1919         painter.setBrush(brush);
1920         painter.setClipRect(clipRect);
1921         painter.drawPath(path);
1922     }
1923
1924     clippedPath.fill(0x12345678);
1925     {
1926         QPainter painter(&clippedPath);
1927         painter.setRenderHint(QPainter::Antialiasing);
1928         painter.setPen(pen);
1929         painter.setBrush(brush);
1930         painter.setClipPath(clipPath);
1931         painter.drawPath(path);
1932     }
1933
1934     QCOMPARE(clippedRect, clippedPath);
1935 }
1936
1937 void tst_QPainter::clippedLines_data()
1938 {
1939     QTest::addColumn<QSize>("imageSize");
1940     QTest::addColumn<QLineF>("line");
1941     QTest::addColumn<QRect>("clipRect");
1942     QTest::addColumn<QPen>("pen");
1943
1944     QPen pen2(QColor(223, 223, 0, 223));
1945     pen2.setWidth(2);
1946
1947     QVector<QLineF> lines;
1948     lines << QLineF(15, 15, 65, 65)
1949           << QLineF(14, 14, 66, 66)
1950           << QLineF(16, 16, 64, 64)
1951           << QLineF(65, 65, 15, 15)
1952           << QLineF(66, 66, 14, 14)
1953           << QLineF(64, 64, 14, 14)
1954           << QLineF(15, 50, 15, 64)
1955           << QLineF(15, 50, 15, 65)
1956           << QLineF(15, 50, 15, 66)
1957           << QLineF(15, 50, 64, 50)
1958           << QLineF(15, 50, 65, 50)
1959           << QLineF(15, 50, 66, 50);
1960
1961     foreach (QLineF line, lines) {
1962         QString desc = QString("line (%1, %2, %3, %4) %5").arg(line.x1())
1963                        .arg(line.y1()).arg(line.x2()).arg(line.y2());
1964         QTest::newRow(qPrintable(desc.arg(0))) << QSize(100, 100) << line
1965                                    << QRect(15, 15, 49, 49)
1966                                    << QPen(Qt::black);
1967         QTest::newRow(qPrintable(desc.arg(1))) << QSize(100, 100) << line
1968                                    << QRect(15, 15, 50, 50)
1969                                    << QPen(Qt::black);
1970         QTest::newRow(qPrintable(desc.arg(2))) << QSize(100, 100) << line
1971                                    << QRect(15, 15, 51, 51)
1972                                    << QPen(Qt::black);
1973         QTest::newRow(qPrintable(desc.arg(3))) << QSize(100, 100) << line
1974                                    << QRect(15, 15, 51, 51)
1975                                    << QPen(Qt::NoPen);
1976         QTest::newRow(qPrintable(desc.arg(4))) << QSize(100, 100) << line
1977                                    << QRect(15, 15, 51, 51)
1978                                    << pen2;
1979     }
1980 }
1981
1982 void tst_QPainter::clippedLines()
1983 {
1984     QFETCH(QSize, imageSize);
1985     QFETCH(QLineF, line);
1986     QFETCH(QRect, clipRect);
1987     QPainterPath clipPath;
1988     clipPath.addRect(clipRect);
1989     QFETCH(QPen, pen);
1990
1991     const int width = imageSize.width();
1992     const int height = imageSize.height();
1993
1994     QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied);
1995     clippedRect.fill(0x12345678);
1996     {
1997         QPainter painter(&clippedRect);
1998         painter.setPen(pen);
1999         painter.setClipRect(clipRect);
2000         painter.drawLine(line);
2001         painter.drawLine(line.toLine());
2002     }
2003
2004     QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied);
2005     clippedPath.fill(0x12345678);
2006     {
2007         QPainter painter(&clippedPath);
2008         painter.setPen(pen);
2009         painter.setClipPath(clipPath);
2010         painter.drawLine(line);
2011         painter.drawLine(line.toLine());
2012     }
2013
2014     QCOMPARE(clippedRect, clippedPath);
2015
2016     // repeat with antialiasing
2017     clippedRect.fill(0x12345678);
2018     {
2019         QPainter painter(&clippedRect);
2020         painter.setRenderHint(QPainter::Antialiasing);
2021         painter.setPen(pen);
2022         painter.setClipRect(clipRect);
2023         painter.drawLine(line);
2024         painter.drawLine(line.toLine());
2025     }
2026
2027     clippedPath.fill(0x12345678);
2028     {
2029         QPainter painter(&clippedPath);
2030         painter.setRenderHint(QPainter::Antialiasing);
2031         painter.setPen(pen);
2032         painter.setClipPath(clipPath);
2033         painter.drawLine(line);
2034         painter.drawLine(line.toLine());
2035     }
2036
2037     QCOMPARE(clippedRect, clippedPath);
2038 }
2039
2040 void tst_QPainter::clippedPolygon_data()
2041 {
2042     clippedFillPath_data();
2043 };
2044
2045 void tst_QPainter::clippedPolygon()
2046 {
2047     QFETCH(QSize, imageSize);
2048     QFETCH(QPainterPath, path);
2049     QPolygonF polygon = path.toFillPolygon();
2050     QFETCH(QRect, clipRect);
2051     QPainterPath clipPath;
2052     clipPath.addRect(clipRect);
2053     QFETCH(QPen, pen);
2054     QFETCH(QBrush, brush);
2055
2056     const int width = imageSize.width();
2057     const int height = imageSize.height();
2058
2059     QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied);
2060     clippedRect.fill(0x12345678);
2061     {
2062         QPainter painter(&clippedRect);
2063         painter.setPen(pen);
2064         painter.setBrush(brush);
2065         painter.setClipRect(clipRect);
2066         painter.drawPolygon(polygon);
2067         painter.drawPolygon(polygon.toPolygon());
2068     }
2069
2070     QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied);
2071     clippedPath.fill(0x12345678);
2072     {
2073         QPainter painter(&clippedPath);
2074         painter.setPen(pen);
2075         painter.setBrush(brush);
2076         painter.setClipRect(clipRect);
2077         painter.drawPolygon(polygon);
2078         painter.drawPolygon(polygon.toPolygon());
2079     }
2080
2081     QCOMPARE(clippedRect, clippedPath);
2082
2083     // repeat with antialiasing
2084
2085     clippedRect.fill(0x12345678);
2086     {
2087         QPainter painter(&clippedRect);
2088         painter.setRenderHint(QPainter::Antialiasing);
2089         painter.setPen(pen);
2090         painter.setBrush(brush);
2091         painter.setClipRect(clipRect);
2092         painter.drawPolygon(polygon);
2093         painter.drawPolygon(polygon.toPolygon());
2094     }
2095
2096     clippedPath.fill(0x12345678);
2097     {
2098         QPainter painter(&clippedPath);
2099         painter.setRenderHint(QPainter::Antialiasing);
2100         painter.setPen(pen);
2101         painter.setBrush(brush);
2102         painter.setClipRect(clipRect);
2103         painter.drawPolygon(polygon);
2104         painter.drawPolygon(polygon.toPolygon());
2105     }
2106
2107     QCOMPARE(clippedRect, clippedPath);
2108 }
2109
2110 // this just draws some text that should be clipped in the raster
2111 // paint engine.
2112 void tst_QPainter::clippedText()
2113 {
2114     for (char ch = 'A'; ch < 'Z'; ++ch) {
2115         //qDebug() << ch;
2116         QFont f;
2117         f.setPixelSize(24);
2118         QFontMetrics metrics(f);
2119         QRect textRect = metrics.boundingRect(QChar(ch));
2120
2121         if (textRect.width() <= 8)
2122             continue;
2123         if (textRect.height() <= 8)
2124             continue;
2125
2126         QRect imageRect = textRect.adjusted(4, 4, -4, -4);
2127
2128         QImage image(imageRect.size(), QImage::Format_ARGB32_Premultiplied);
2129
2130         image.fill(qRgba(255, 255, 255, 255));
2131         {
2132             QPainter painter(&image);
2133             painter.setFont(f);
2134             painter.setPen(Qt::black);
2135
2136             painter.drawText(0, 0, QChar(ch));
2137         }
2138
2139         image.fill(qRgba(255, 255, 255, 255));
2140         {
2141             QPainter painter(&image);
2142             painter.setFont(f);
2143             painter.setPen(Qt::black);
2144
2145             painter.drawText(-imageRect.topLeft(), QChar(ch));
2146         }
2147
2148         bool foundPixel = false;
2149         for (int x = 0; x < image.width(); ++x)
2150             for (int y = 0; y < image.height(); ++y)
2151                 if (image.pixel(x, y) != 0)
2152                     foundPixel = true;
2153         // can't QVERIFY(foundPixel) as sometimes all pixels are clipped
2154         // away. For example for 'O'
2155         // just call /some/ function to prevent the compiler from optimizing
2156         // foundPixel away
2157         QString::number(foundPixel);
2158
2159         //image.save(QString("debug") + ch + ".xpm");
2160     }
2161
2162     QVERIFY(true); // reached, don't trigger any valgrind errors
2163 }
2164
2165 void tst_QPainter::setOpacity_data()
2166 {
2167     QTest::addColumn<QImage::Format>("destFormat");
2168     QTest::addColumn<QImage::Format>("srcFormat");
2169
2170     QTest::newRow("ARGB32P on ARGB32P") << QImage::Format_ARGB32_Premultiplied
2171                                         << QImage::Format_ARGB32_Premultiplied;
2172
2173     QTest::newRow("ARGB32 on ARGB32") << QImage::Format_ARGB32
2174                                       << QImage::Format_ARGB32;
2175
2176     QTest::newRow("RGB32 on RGB32") << QImage::Format_RGB32
2177                                     << QImage::Format_RGB32;
2178
2179     QTest::newRow("RGB16 on RGB16") << QImage::Format_RGB16
2180                                     << QImage::Format_RGB16;
2181
2182     QTest::newRow("ARGB8565_Premultiplied on ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied
2183                                                                       << QImage::Format_ARGB8565_Premultiplied;
2184
2185     QTest::newRow("RGB555 on RGB555") << QImage::Format_RGB555
2186                                       << QImage::Format_RGB555;
2187
2188     QTest::newRow("RGB666 on RGB666") << QImage::Format_RGB666
2189                                       << QImage::Format_RGB666;
2190
2191     QTest::newRow("ARGB8555_Premultiplied on ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied
2192                                                                       << QImage::Format_ARGB8555_Premultiplied;
2193
2194     QTest::newRow("RGB888 on RGB888") << QImage::Format_RGB888
2195                                       << QImage::Format_RGB888;
2196
2197     QTest::newRow("RGB32 on RGB16") << QImage::Format_RGB16
2198                                     << QImage::Format_RGB32;
2199
2200     QTest::newRow("RGB32 on ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied
2201                                                      << QImage::Format_RGB32;
2202
2203     QTest::newRow("RGB32 on RGB666") << QImage::Format_RGB666
2204                                      << QImage::Format_RGB32;
2205
2206     QTest::newRow("RGB32 on RGB555") << QImage::Format_RGB555
2207                                      << QImage::Format_RGB32;
2208
2209     QTest::newRow("RGB32 on ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied
2210                                                      << QImage::Format_RGB32;
2211
2212     QTest::newRow("RGB32 on RGB888") << QImage::Format_RGB888
2213                                      << QImage::Format_RGB32;
2214
2215     QTest::newRow("RGB16 on RGB32") << QImage::Format_RGB32
2216                                     << QImage::Format_RGB16;
2217
2218     QTest::newRow("ARGB8565_Premultiplied on RGB32") << QImage::Format_RGB32
2219                                                      << QImage::Format_ARGB8565_Premultiplied;
2220
2221     QTest::newRow("RGB666 on RGB32") << QImage::Format_RGB32
2222                                      << QImage::Format_RGB666;
2223
2224     QTest::newRow("RGB555 on RGB32") << QImage::Format_RGB32
2225                                      << QImage::Format_RGB555;
2226
2227     QTest::newRow("ARGB8555_Premultiplied on RGB32") << QImage::Format_RGB32
2228                                                      << QImage::Format_ARGB8555_Premultiplied;
2229
2230     QTest::newRow("RGB888 on RGB32") << QImage::Format_RGB32
2231                                      << QImage::Format_RGB888;
2232
2233     QTest::newRow("RGB555 on RGB888") << QImage::Format_RGB888
2234                                       << QImage::Format_RGB555;
2235
2236     QTest::newRow("RGB666 on RGB888") << QImage::Format_RGB888
2237                                       << QImage::Format_RGB666;
2238
2239     QTest::newRow("RGB444 on RGB444") << QImage::Format_RGB444
2240                                       << QImage::Format_RGB444;
2241 }
2242
2243 void tst_QPainter::setOpacity()
2244 {
2245     QFETCH(QImage::Format, destFormat);
2246     QFETCH(QImage::Format, srcFormat);
2247
2248     const QSize imageSize(12, 12);
2249     const QRect imageRect(QPoint(0, 0), imageSize);
2250     QColor destColor = Qt::black;
2251     QColor srcColor = Qt::white;
2252
2253     QImage dest(imageSize, destFormat);
2254     QImage src(imageSize, srcFormat);
2255
2256     QPainter p;
2257     p.begin(&dest);
2258     p.fillRect(imageRect, destColor);
2259     p.end();
2260
2261     p.begin(&src);
2262     p.fillRect(imageRect, srcColor);
2263     p.end();
2264
2265     p.begin(&dest);
2266     p.setOpacity(0.5);
2267     p.drawImage(imageRect, src, imageRect);
2268     p.end();
2269
2270     QImage actual = dest.convertToFormat(QImage::Format_RGB32);
2271
2272     for (int y = 0; y < actual.height(); ++y) {
2273         QRgb *p = (QRgb *)actual.scanLine(y);
2274         for (int x = 0; x < actual.width(); ++x) {
2275             QVERIFY(qAbs(qRed(p[x]) - 127) <= 0xf);
2276             QVERIFY(qAbs(qGreen(p[x]) - 127) <= 0xf);
2277             QVERIFY(qAbs(qBlue(p[x]) - 127) <= 0xf);
2278         }
2279     }
2280 }
2281
2282 void tst_QPainter::drawhelper_blend_untransformed_data()
2283 {
2284     setOpacity_data();
2285 }
2286
2287 void tst_QPainter::drawhelper_blend_untransformed()
2288 {
2289     QFETCH(QImage::Format, destFormat);
2290     QFETCH(QImage::Format, srcFormat);
2291
2292     const int size = 128;
2293     const QSize imageSize(size, size);
2294     const QRect paintRect(1, 0, size - 2, size); // needs alignment and tailing
2295
2296     QColor destColor(127, 127, 127);
2297     QColor srcColor(Qt::white);
2298
2299     QImage dest(imageSize, destFormat);
2300     QImage src(imageSize, srcFormat);
2301
2302     QPainter p;
2303     p.begin(&src);
2304     p.fillRect(paintRect, srcColor);
2305     p.end();
2306
2307     QList<qreal> opacities = (QList<qreal>() << 0.0 << 0.1  << 0.01 << 0.4
2308                               << 0.5 << 0.6 << 0.9 << 1.0);
2309     foreach (qreal opacity, opacities) {
2310         p.begin(&dest);
2311         p.fillRect(paintRect, destColor);
2312
2313         p.setOpacity(opacity);
2314         p.drawImage(paintRect, src, paintRect);
2315         p.end();
2316
2317         // sanity check: make sure all pixels are equal
2318         QImage expected(size - 2, size, destFormat);
2319         p.begin(&expected);
2320         p.fillRect(0, 0, expected.width(), expected.height(),
2321                    QColor(dest.pixel(1, 0)));
2322         p.end();
2323
2324         const QImage subDest(dest.bits() + dest.depth() / 8,
2325                              dest.width() - 2, dest.height(),
2326                              dest.bytesPerLine(), dest.format());
2327
2328         if (dest.format() == QImage::Format_ARGB8565_Premultiplied ||
2329             dest.format() == QImage::Format_ARGB8555_Premultiplied) {
2330             // Test skipped due to rounding errors...
2331             continue;
2332         }
2333         QCOMPARE(subDest, expected);
2334     }
2335 }
2336
2337 void tst_QPainter::drawhelper_blend_tiled_untransformed_data()
2338 {
2339     setOpacity_data();
2340 }
2341
2342 void tst_QPainter::drawhelper_blend_tiled_untransformed()
2343 {
2344     QFETCH(QImage::Format, destFormat);
2345     QFETCH(QImage::Format, srcFormat);
2346
2347     const int size = 128;
2348     const QSize imageSize(size, size);
2349     const QRect paintRect(1, 0, size - 2, size); // needs alignment and tailing
2350
2351     QColor destColor(127, 127, 127);
2352     QColor srcColor(Qt::white);
2353
2354     QImage dest(imageSize, destFormat);
2355     QImage src(imageSize / 2, srcFormat);
2356
2357     QPainter p;
2358     p.begin(&src);
2359     p.fillRect(QRect(QPoint(0, 0), imageSize/ 2), srcColor);
2360     p.end();
2361
2362     const QBrush brush(src);
2363
2364     QList<qreal> opacities = (QList<qreal>() << 0.0 << 0.1  << 0.01 << 0.4
2365                               << 0.5 << 0.6 << 0.9 << 1.0);
2366     foreach (qreal opacity, opacities) {
2367         p.begin(&dest);
2368         p.fillRect(paintRect, destColor);
2369
2370         p.setOpacity(opacity);
2371         p.fillRect(paintRect, brush);
2372         p.end();
2373
2374         // sanity check: make sure all pixels are equal
2375         QImage expected(size - 2, size, destFormat);
2376         p.begin(&expected);
2377         p.fillRect(0, 0, expected.width(), expected.height(),
2378                    QColor(dest.pixel(1, 0)));
2379         p.end();
2380
2381         const QImage subDest(dest.bits() + dest.depth() / 8,
2382                              dest.width() - 2, dest.height(),
2383                              dest.bytesPerLine(), dest.format());
2384
2385         if (dest.format() == QImage::Format_ARGB8565_Premultiplied ||
2386             dest.format() == QImage::Format_ARGB8555_Premultiplied) {
2387             // Skipping test due to rounding errors. Test needs rewrite
2388             continue;
2389         }
2390         QCOMPARE(subDest, expected);
2391     }
2392 }
2393
2394 static QPaintEngine::PaintEngineFeatures no_porter_duff()
2395 {
2396     QPaintEngine::PaintEngineFeatures features = QPaintEngine::AllFeatures;
2397     return features & ~QPaintEngine::PorterDuff;
2398 }
2399
2400 class DummyPaintEngine : public QPaintEngine, public QPaintDevice
2401 {
2402 public:
2403     DummyPaintEngine() : QPaintEngine(no_porter_duff()) {}
2404     virtual bool begin(QPaintDevice *) { return true; }
2405     virtual bool end() { return true; }
2406
2407     virtual void updateState(const QPaintEngineState &) {}
2408     virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {}
2409
2410     virtual Type type() const { return User; }
2411
2412     virtual QPaintEngine *paintEngine() const { return (QPaintEngine *)this; }
2413
2414     virtual int metric(PaintDeviceMetric metric) const { Q_UNUSED(metric); return 0; };
2415 };
2416
2417 static bool success;
2418
2419 void porterDuff_warningChecker(QtMsgType type, const QMessageLogContext &, const QString &msg)
2420 {
2421     if (type == QtWarningMsg && msg == QLatin1String("QPainter::setCompositionMode: PorterDuff modes not supported on device"))
2422         success = false;
2423 }
2424
2425 void tst_QPainter::porterDuff_warning()
2426 {
2427     QtMessageHandler old = qInstallMessageHandler(porterDuff_warningChecker);
2428     DummyPaintEngine dummy;
2429     QPainter p(&dummy);
2430
2431     success = true;
2432     p.setCompositionMode(QPainter::CompositionMode_Source);
2433     QVERIFY(success);
2434
2435     success = true;
2436     p.setCompositionMode(QPainter::CompositionMode_SourceOver);
2437     QVERIFY(success);
2438
2439     success = true;
2440     p.setCompositionMode(QPainter::CompositionMode_DestinationOver);
2441     QVERIFY(!success);
2442
2443     QVERIFY(qInstallMessageHandler(old) == porterDuff_warningChecker);
2444 }
2445
2446 class quint24
2447 {
2448 public:
2449     inline quint24(quint32 v)
2450     {
2451         data[0] = qBlue(v);
2452         data[1] = qGreen(v);
2453         data[2] = qRed(v);
2454     }
2455
2456     inline operator quint32 ()
2457     {
2458         return qRgb(data[2], data[1], data[0]);
2459     }
2460
2461     inline bool operator==(const quint24 &v) const {
2462         return (data[0] == v.data[0] && data[1] == v.data[1] && data[2] == v.data[2]);
2463     }
2464
2465     uchar data[3];
2466 } Q_PACKED;
2467
2468 void tst_QPainter::drawhelper_blend_color()
2469 {
2470     QImage dest(32, 32, QImage::Format_ARGB8555_Premultiplied);
2471     dest.fill(0xff000000);
2472
2473     {
2474         QPainter p(&dest);
2475         p.fillRect(0, 0, dest.width(), dest.height(), QColor(255, 0, 0, 127));
2476     }
2477
2478     QImage expected(32, 32, QImage::Format_ARGB8555_Premultiplied);
2479     expected.fill(0xff3c007f);
2480
2481     QCOMPARE(dest.pixel(1, 1), expected.pixel(1, 1));
2482     QCOMPARE(dest, expected);
2483 }
2484
2485 #ifndef QT_NO_WIDGETS
2486 class ViewportTestWidget : public QWidget
2487 {
2488 public:
2489     ViewportTestWidget(QWidget *parent = 0) : QWidget(parent), hasPainted(false) {}
2490     QSize sizeHint() const {
2491         return QSize(100, 100);
2492     }
2493
2494     QRect viewport;
2495     bool hasPainted;
2496
2497 protected:
2498     void paintEvent(QPaintEvent *) {
2499         hasPainted = true;
2500         QPainter p(this);
2501         viewport = p.viewport();
2502     }
2503 };
2504
2505 void tst_QPainter::childWidgetViewport()
2506 {
2507     QWidget parent;
2508     parent.setAutoFillBackground(true);
2509     parent.resize(200, 200);
2510     ViewportTestWidget child(&parent);
2511     child.setAutoFillBackground(true);
2512     parent.show();
2513     parent.update();
2514     qApp->processEvents();
2515
2516     if (child.hasPainted) {
2517         QCOMPARE(child.viewport, QRect(QPoint(0, 0), child.sizeHint()));
2518     } else {
2519         qWarning("Failed to ensure that paintEvent has been run. Could not run test.");
2520     }
2521 }
2522 #endif
2523
2524 void tst_QPainter::fillRect_objectBoundingModeGradient()
2525 {
2526     QImage a(10, 10, QImage::Format_ARGB32_Premultiplied);
2527     a.fill(0x0);
2528     QImage b = a;
2529
2530     QLinearGradient g(QPoint(0, 0), QPoint(0, 1));
2531     g.setColorAt(0, Qt::red);
2532     g.setColorAt(1, Qt::blue);
2533     g.setCoordinateMode(QGradient::ObjectBoundingMode);
2534
2535     QPainter p(&a);
2536     p.fillRect(QRect(0, 0, a.width(), a.height()), g);
2537     p.end();
2538
2539     QPainterPath path;
2540     path.addRect(0, 0, a.width(), a.height());
2541
2542     p.begin(&b);
2543     p.fillPath(path, g);
2544     p.end();
2545
2546     QCOMPARE(a, b);
2547 }
2548
2549 void tst_QPainter::fillRect_stretchToDeviceMode()
2550 {
2551     QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
2552
2553     QLinearGradient g(QPoint(0, 0), QPoint(0, 1));
2554     g.setCoordinateMode(QGradient::StretchToDeviceMode);
2555
2556     QPainter p(&img);
2557     p.fillRect(img.rect(), g);
2558     p.end();
2559
2560     for (int i = 1; i < img.height(); ++i)
2561         QVERIFY(img.pixel(0, i) != img.pixel(0, i-1));
2562 }
2563
2564 void tst_QPainter::monoImages()
2565 {
2566     Qt::GlobalColor colorPairs[][2] = {
2567         { Qt::white, Qt::black },
2568         { Qt::color0, Qt::color1 },
2569         { Qt::red, Qt::blue }
2570     };
2571
2572     const int numColorPairs = sizeof(colorPairs) / sizeof(QRgb[2]);
2573
2574     QImage transparent(2, 2, QImage::Format_ARGB32_Premultiplied);
2575     transparent.fill(0x0);
2576
2577     for (int i = 1; i < QImage::NImageFormats; ++i) {
2578         for (int j = 0; j < numColorPairs; ++j) {
2579             const QImage::Format format = QImage::Format(i);
2580             if (format == QImage::Format_Indexed8)
2581                 continue;
2582
2583             QImage img(2, 2, format);
2584
2585             if (img.colorCount() > 0) {
2586                 img.setColor(0, QColor(colorPairs[j][0]).rgba());
2587                 img.setColor(1, QColor(colorPairs[j][1]).rgba());
2588             }
2589
2590             img.fill(0x0);
2591             QPainter p(&img);
2592             p.fillRect(0, 0, 2, 2, colorPairs[j][0]);
2593             p.fillRect(0, 0, 1, 1, colorPairs[j][1]);
2594             p.fillRect(1, 1, 1, 1, colorPairs[j][1]);
2595             p.end();
2596
2597             QImage original = img;
2598
2599             p.begin(&img);
2600             p.drawImage(0, 0, transparent);
2601             p.end();
2602
2603             // drawing a transparent image on top of another image
2604             // should not change the image
2605             QCOMPARE(original, img);
2606
2607             if (img.colorCount() == 0)
2608                 continue;
2609
2610             for (int k = 0; k < 2; ++k) {
2611                 QPainter p(&img);
2612                 p.fillRect(0, 0, 2, 2, colorPairs[j][k]);
2613                 p.end();
2614
2615                 QImage argb32p(2, 2, QImage::Format_ARGB32_Premultiplied);
2616                 p.begin(&argb32p);
2617                 p.fillRect(0, 0, 2, 2, colorPairs[j][k]);
2618                 p.end();
2619
2620                 QCOMPARE(argb32p, img.convertToFormat(argb32p.format()));
2621
2622                 // drawing argb32p image on mono image
2623                 p.begin(&img);
2624                 p.drawImage(0, 0, argb32p);
2625                 p.end();
2626
2627                 QCOMPARE(argb32p, img.convertToFormat(argb32p.format()));
2628
2629                 // drawing mono image on argb32p image
2630                 p.begin(&argb32p);
2631                 p.drawImage(0, 0, img);
2632                 p.end();
2633
2634                 QCOMPARE(argb32p, img.convertToFormat(argb32p.format()));
2635             }
2636         }
2637     }
2638 }
2639
2640 #if !defined(Q_OS_IRIX) && !defined(Q_OS_AIX) && !defined(Q_CC_MSVC) && !defined(Q_OS_SOLARIS) && !defined(__UCLIBC__)
2641 #include <fenv.h>
2642
2643 static const QString fpeExceptionString(int exception)
2644 {
2645 #ifdef FE_INEXACT
2646     if (exception & FE_INEXACT)
2647         return QLatin1String("Inexact result");
2648 #endif
2649     if (exception & FE_UNDERFLOW)
2650         return QLatin1String("Underflow");
2651     if (exception & FE_OVERFLOW)
2652         return QLatin1String("Overflow");
2653     if (exception & FE_DIVBYZERO)
2654         return QLatin1String("Divide by zero");
2655     if (exception & FE_INVALID)
2656         return QLatin1String("Invalid operation");
2657     return QLatin1String("No exception");
2658 }
2659
2660 class FpExceptionChecker
2661 {
2662 public:
2663     FpExceptionChecker(int exceptionMask)
2664         : m_exceptionMask(exceptionMask)
2665     {
2666         feclearexcept(m_exceptionMask);
2667     }
2668
2669     ~FpExceptionChecker()
2670     {
2671         const int exceptions = fetestexcept(m_exceptionMask);
2672         QVERIFY2(!exceptions, qPrintable(QLatin1String("Floating point exception: ") + fpeExceptionString(exceptions)));
2673     }
2674
2675 private:
2676     int m_exceptionMask;
2677 };
2678
2679 void fpe_rasterizeLine_task232012()
2680 {
2681     FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
2682     QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
2683     img.fill(0x0);
2684     QPainter p(&img);
2685
2686     p.setBrush(Qt::black);
2687     p.drawRect(QRectF(0, 0, 5, 0));
2688     p.drawRect(QRectF(0, 0, 0, 5));
2689 }
2690
2691 void fpe_pixmapTransform()
2692 {
2693     FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
2694
2695     QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
2696
2697     QPainter p(&img);
2698
2699     const qreal scaleFactor = 0.001;
2700     const int translateDistance = 1000000;
2701
2702     p.setPen(Qt::red);
2703     p.setBrush(QBrush(Qt::red,Qt::Dense6Pattern));
2704
2705     for (int i = 0; i < 2; ++i) {
2706         p.setRenderHint(QPainter::SmoothPixmapTransform, i);
2707
2708         p.resetTransform();
2709         p.scale(1.1, 1.1);
2710         p.translate(translateDistance, 0);
2711         p.drawRect(-translateDistance, 0, 100, 100);
2712
2713         p.resetTransform();
2714         p.scale(scaleFactor, scaleFactor);
2715         p.drawRect(QRectF(0, 0, 1 / scaleFactor, 1 / scaleFactor));
2716     }
2717 }
2718
2719 void fpe_zeroLengthLines()
2720 {
2721     FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
2722
2723     QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
2724
2725     QPainter p(&img);
2726
2727     p.setPen(QPen(Qt::black, 3));
2728     p.drawLine(64, 64, 64, 64);
2729 }
2730
2731 void fpe_divByZero()
2732 {
2733     FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
2734
2735     QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
2736
2737     QPainter p(&img);
2738
2739     p.setRenderHint(QPainter::Antialiasing);
2740
2741     p.drawRect(QRectF(10, 10, 100, 0));
2742     p.drawRect(QRectF(10, 10, 0, 100));
2743
2744     p.drawRect(QRect(10, 10, 100, 0));
2745     p.drawRect(QRect(10, 10, 0, 100));
2746
2747     p.fillRect(QRectF(10, 10, 100, 0), Qt::black);
2748     p.fillRect(QRectF(10, 10, 0, 100), Qt::black);
2749
2750     p.fillRect(QRect(10, 10, 100, 0), Qt::black);
2751     p.fillRect(QRect(10, 10, 0, 100), Qt::black);
2752 }
2753
2754 void fpe_steepSlopes()
2755 {
2756     FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
2757
2758     QImage img(1024, 1024, QImage::Format_ARGB32_Premultiplied);
2759
2760     QFETCH(QTransform, transform);
2761     QFETCH(QLineF, line);
2762     QFETCH(bool, antialiased);
2763
2764     QPainter p(&img);
2765
2766     p.setPen(QPen(Qt::black, 1));
2767     p.setRenderHint(QPainter::Antialiasing, antialiased);
2768     p.setTransform(transform);
2769
2770     p.drawLine(line);
2771 }
2772
2773 void fpe_radialGradients()
2774 {
2775     FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
2776
2777     QImage img(21, 21, QImage::Format_ARGB32_Premultiplied);
2778     img.fill(0);
2779
2780     double m = img.width() * 0.5;
2781
2782     QPainter p(&img);
2783     p.setRenderHints(QPainter::Antialiasing);
2784     p.setPen(Qt::NoPen);
2785     p.setBrush(QRadialGradient(m, m, m));
2786     p.drawEllipse(img.rect());
2787 }
2788
2789 #define FPE_TEST(x) \
2790 void tst_QPainter::x() \
2791 { \
2792     ::x(); \
2793 }
2794 #else
2795 #define FPE_TEST(x) \
2796 void tst_QPainter::x() \
2797 { \
2798     QSKIP("Floating point exception checking (fenv.h) not available"); \
2799 }
2800 #endif
2801
2802 FPE_TEST(fpe_rasterizeLine_task232012)
2803 FPE_TEST(fpe_pixmapTransform)
2804 FPE_TEST(fpe_zeroLengthLines)
2805 FPE_TEST(fpe_divByZero)
2806 FPE_TEST(fpe_steepSlopes)
2807 FPE_TEST(fpe_radialGradients)
2808
2809 void tst_QPainter::fpe_steepSlopes_data()
2810 {
2811     QTest::addColumn<QTransform>("transform");
2812     QTest::addColumn<QLineF>("line");
2813     QTest::addColumn<bool>("antialiased");
2814
2815     {
2816         const qreal dsin = 0.000014946676875461832484392500630665523431162000633776187896728515625;
2817         const qreal dcos = 0.9999999998882984630910186751862056553363800048828125;
2818
2819         const QTransform transform = QTransform(QMatrix(dcos, dsin, -dsin, dcos, 64, 64));
2820         const QLineF line(2, 2, 2, 6);
2821
2822         QTest::newRow("task 207147 aa") << transform << line << true;
2823         QTest::newRow("task 207147 no aa") << transform << line << false;
2824     }
2825
2826     {
2827         QTransform transform;
2828         transform.rotate(0.0000001);
2829         const QLineF line(5, 5, 10, 5);
2830
2831         QTest::newRow("task 166702 aa") << transform << line << true;
2832         QTest::newRow("task 166702 no aa") << transform << line << false;
2833     }
2834
2835     {
2836         const QTransform transform;
2837         const QLineF line(2.5, 2.5, 2.5 + 1/256., 60000.5);
2838
2839         QTest::newRow("steep line aa") << transform << line << true;
2840         QTest::newRow("steep line no aa") << transform << line << false;
2841     }
2842
2843     {
2844         const QTransform transform;
2845         const QLineF line(2.5, 2.5, 2.5 + 1/256., 1024);
2846
2847         QTest::newRow("steep line 2 aa") << transform << line << true;
2848         QTest::newRow("steep line 2 no aa") << transform << line << false;
2849     }
2850
2851     {
2852         const QTransform transform;
2853         const QLineF line(2.5, 2.5, 2.5 + 1/64., 1024);
2854
2855         QTest::newRow("steep line 3 aa") << transform << line << true;
2856         QTest::newRow("steep line 3 no aa") << transform << line << false;
2857     }
2858 }
2859
2860 qreal randf()
2861 {
2862     return rand() / (RAND_MAX + 1.0);
2863 }
2864
2865 QPointF randInRect(const QRectF &rect)
2866 {
2867     const qreal x = rect.left() + rect.width() * randf();
2868     const qreal y = rect.top() + rect.height() * randf();
2869
2870     return QPointF(x, y);
2871 }
2872
2873 void tst_QPainter::rasterizer_asserts()
2874 {
2875     QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
2876
2877     QRectF middle(QPointF(0, 0), img.size());
2878     QRectF left = middle.translated(-middle.width(), 0);
2879     QRectF right = middle.translated(middle.width(), 0);
2880
2881     QPainter p(&img);
2882     img.fill(Qt::white);
2883     p.setCompositionMode(QPainter::CompositionMode_Destination);
2884     for (int i = 0; i < 100000; ++i) {
2885         QPainterPath path;
2886         path.moveTo(randInRect(middle));
2887         path.lineTo(randInRect(left));
2888         path.lineTo(randInRect(right));
2889
2890         p.fillPath(path, Qt::black);
2891     }
2892 }
2893
2894 void tst_QPainter::rasterizer_negativeCoords()
2895 {
2896     QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
2897     img.fill(0x0);
2898
2899     QImage original = img;
2900
2901     QPainter p(&img);
2902     p.rotate(90);
2903     p.fillRect(0, 0, 70, 50, Qt::black);
2904
2905     // image should not have changed
2906     QCOMPARE(img.pixel(0, 0), 0x0U);
2907     QCOMPARE(img, original);
2908 }
2909
2910 void tst_QPainter::blendOverFlow_data()
2911 {
2912     QTest::addColumn<QImage::Format>("format");
2913     QTest::addColumn<int>("width");
2914     QTest::addColumn<int>("height");
2915
2916     QImage::Format format = QImage::Format_ARGB8555_Premultiplied;
2917     QTest::newRow("555,1,1") << format << 1 << 1;
2918     QTest::newRow("555,2,2") << format << 2 << 2;
2919     QTest::newRow("555,10,10") << format << 10 << 10;
2920
2921     format = QImage::Format_ARGB8565_Premultiplied;
2922     QTest::newRow("565,1,1") << format << 1 << 1;
2923     QTest::newRow("565,2,2") << format << 2 << 2;
2924     QTest::newRow("565,10,10") << format << 10 << 10;
2925 }
2926
2927 void tst_QPainter::blendOverFlow()
2928 {
2929     QFETCH(QImage::Format, format);
2930     QFETCH(int, width);
2931     QFETCH(int, height);
2932
2933     QImage dest(width, height, format);
2934     QImage src(width, height, format);
2935
2936     {
2937         QPainter p(&dest);
2938         p.fillRect(0, 0, width, height, Qt::green);
2939     }
2940     QImage expected = dest;
2941
2942     {
2943         QPainter p(&src);
2944         p.setCompositionMode(QPainter::CompositionMode_Source);
2945         p.fillRect(0, 0, width, height, QColor(0, 255, 0, 6));
2946     }
2947
2948     {
2949         QPainter p(&dest);
2950         p.drawImage(0, 0, src);
2951     }
2952
2953     QCOMPARE(dest.pixel(0, 0), expected.pixel(0, 0));
2954     QCOMPARE(dest, expected);
2955 }
2956
2957 void tst_QPainter::largeImagePainting_data()
2958 {
2959     QTest::addColumn<int>("width");
2960     QTest::addColumn<int>("height");
2961     QTest::addColumn<bool>("antialiased");
2962
2963     QTest::newRow("tall") << 1 << 32767 << false;
2964     QTest::newRow("tall aa") << 1 << 32767 << true;
2965     QTest::newRow("wide") << 32767 << 1 << false;
2966     QTest::newRow("wide aa") << 32767 << 1 << true;
2967 }
2968
2969 void tst_QPainter::largeImagePainting()
2970 {
2971     QPainterPath path;
2972     path.addRect(0, 0, 1, 1);
2973     path.addRect(2, 0, 1, 1);
2974     path.addRect(0, 2, 1, 1);
2975
2976     QFETCH(int, width);
2977     QFETCH(int, height);
2978     QFETCH(bool, antialiased);
2979
2980     QImage img(width, height, QImage::Format_ARGB32_Premultiplied);
2981     img.fill(0x0);
2982
2983     QPainter p(&img);
2984     p.setPen(Qt::NoPen);
2985     p.setBrush(Qt::white);
2986
2987     p.setRenderHint(QPainter::Antialiasing, antialiased);
2988
2989     for (int i = 0; i < img.width(); i += 4) {
2990         p.drawPath(path);
2991         p.translate(4, 0);
2992     }
2993
2994     p.resetMatrix();
2995
2996     for (int i = 4; i < img.height(); i += 4) {
2997         p.translate(0, 4);
2998         p.drawPath(path);
2999     }
3000
3001     for (int i = 0; i < img.width(); ++i) {
3002         if (i % 2)
3003             QCOMPARE(img.pixel(i, 0), 0x0U);
3004         else
3005             QCOMPARE(img.pixel(i, 0), 0xffffffffU);
3006     }
3007
3008     for (int i = 1; i < img.height(); ++i) {
3009         if (i % 2)
3010             QCOMPARE(img.pixel(0, i), 0x0U);
3011         else
3012             QCOMPARE(img.pixel(0, i), 0xffffffffU);
3013     }
3014 }
3015
3016 void tst_QPainter::imageScaling_task206785()
3017 {
3018     QImage src(32, 2, QImage::Format_ARGB32_Premultiplied);
3019     src.fill(0xffffffff);
3020
3021     QImage dst(128, 128, QImage::Format_ARGB32_Premultiplied);
3022
3023     QImage expected(128, 128, QImage::Format_ARGB32_Premultiplied);
3024     expected.fill(0xffffffff);
3025
3026     for (int i = 1; i < 5; ++i) {
3027         qreal scale = i / qreal(5);
3028
3029         dst.fill(0xff000000);
3030
3031         QPainter p(&dst);
3032         p.scale(dst.width() / qreal(src.width()), scale);
3033
3034         for (int y = 0; y * scale < dst.height(); ++y)
3035             p.drawImage(0, y, src);
3036
3037         p.end();
3038
3039         QCOMPARE(dst, expected);
3040     }
3041 }
3042
3043 #define FOR_EACH_NEIGHBOR_8 for (int dx = -1; dx <= 1; ++dx) for (int dy = -1; dy <= 1; ++dy) if (dx != 0 || dy != 0)
3044 #define FOR_EACH_NEIGHBOR_4 for (int dx = -1; dx <= 1; ++dx) for (int dy = -1; dy <= 1; ++dy) if ((dx == 0) != (dy == 0))
3045
3046 uint qHash(const QPoint &point)
3047 {
3048     return qHash(qMakePair(point.x(), point.y()));
3049 }
3050
3051 bool verifyOutlineFillConsistency(const QImage &img, QRgb outside, QRgb inside, QRgb outline)
3052 {
3053     if (img.pixel(img.width() / 2, img.height() / 2) != inside)
3054         return false;
3055
3056     int x = img.width() / 2;
3057     int y = img.height() / 2;
3058
3059     while (img.pixel(++x, y) == inside)
3060         ;
3061
3062     if (img.pixel(x, y) != outline)
3063         return false;
3064
3065     QQueue<QPoint> discovered;
3066     discovered.enqueue(QPoint(x, y));
3067
3068     QVector<bool> visited(img.width() * img.height());
3069     visited.fill(false);
3070
3071     while (!discovered.isEmpty()) {
3072         QPoint p = discovered.dequeue();
3073         QRgb pixel = img.pixel(p.x(), p.y());
3074
3075         bool &v = visited[p.y() * img.width() + p.x()];
3076         if (v)
3077             continue;
3078         v = true;
3079
3080         if (pixel == outline) {
3081             FOR_EACH_NEIGHBOR_8 {
3082                 QPoint x(p.x() + dx, p.y() + dy);
3083                 discovered.enqueue(x);
3084             }
3085         } else {
3086             FOR_EACH_NEIGHBOR_4 {
3087                 if ((dx == 0) == (dy == 0))
3088                     continue;
3089                 QRgb neighbor = img.pixel(p.x() + dx, p.y() + dy);
3090                 if ((pixel == inside && neighbor == outside) ||
3091                     (pixel == outside && neighbor == inside))
3092                     return false;
3093             }
3094         }
3095     }
3096
3097     return true;
3098 }
3099
3100 #undef FOR_EACH_NEIGHBOR_8
3101 #undef FOR_EACH_NEIGHBOR_4
3102
3103 void tst_QPainter::outlineFillConsistency()
3104 {
3105     QImage dst(256, 256, QImage::Format_ARGB32_Premultiplied);
3106
3107     QPolygonF poly;
3108     poly << QPointF(5, -100) << QPointF(-70, 20) << QPointF(95, 25);
3109
3110     QPen pen(Qt::red);
3111     QBrush brush(Qt::black);
3112
3113     QRgb background = 0xffffffff;
3114     for (int i = 0; i < 360; ++i) {
3115         dst.fill(background);
3116
3117         QPainter p(&dst);
3118         p.translate(dst.width() / 2, dst.height() / 2);
3119
3120         QPolygonF copy = poly;
3121         for (int j = 0; j < copy.size(); ++j)
3122             copy[j] = QTransform().rotate(i).map(copy[j]);
3123
3124         p.setPen(pen);
3125         p.setBrush(brush);
3126         p.drawPolygon(copy);
3127         p.end();
3128
3129         QVERIFY(verifyOutlineFillConsistency(dst, background, brush.color().rgba(), pen.color().rgba()));
3130     }
3131 }
3132
3133 void tst_QPainter::drawImage_task217400_data()
3134 {
3135     QTest::addColumn<QImage::Format>("format");
3136
3137     QTest::newRow("444") << QImage::Format_ARGB4444_Premultiplied;
3138     QTest::newRow("555") << QImage::Format_ARGB8555_Premultiplied;
3139     QTest::newRow("565") << QImage::Format_ARGB8565_Premultiplied;
3140 //    QTest::newRow("666") << QImage::Format_ARGB6666_Premultiplied;
3141     QTest::newRow("888p") << QImage::Format_ARGB32_Premultiplied;
3142     QTest::newRow("888") << QImage::Format_ARGB32;
3143 }
3144
3145 void tst_QPainter::drawImage_task217400()
3146 {
3147     QFETCH(QImage::Format, format);
3148
3149     const QImage src = QImage(QFINDTESTDATA("task217400.png"))
3150                        .convertToFormat(format);
3151     QVERIFY(!src.isNull());
3152
3153     QImage expected(src.size(), format);
3154     {
3155         QPainter p(&expected);
3156         p.fillRect(0, 0, expected.width(), expected.height(), Qt::white);
3157         p.drawImage(0, 0, src);
3158     }
3159
3160     for (int i = 1; i <= 4; ++i) {
3161         QImage dest(src.width() + i, src.height(), format);
3162         {
3163             QPainter p(&dest);
3164             p.fillRect(0, 0, dest.width(), dest.height(), Qt::white);
3165             p.drawImage(i, 0, src);
3166         }
3167
3168         const QImage result = dest.copy(i, 0, src.width(), src.height());
3169
3170         QCOMPARE(result, expected);
3171     }
3172 }
3173
3174 void tst_QPainter::drawImage_task258776()
3175 {
3176     QImage src(16, 16, QImage::Format_RGB888);
3177     QImage dest(33, 33, QImage::Format_RGB888);
3178     src.fill(0x00ff00);
3179     dest.fill(0xff0000);
3180
3181     QPainter painter(&dest);
3182     painter.drawImage(QRectF(0.499, 0.499, 32, 32), src, QRectF(0, 0, 16, 16));
3183     painter.end();
3184
3185     QImage expected(33, 33, QImage::Format_RGB32);
3186     expected.fill(0xff0000);
3187
3188     painter.begin(&expected);
3189     painter.drawImage(QRectF(0, 0, 32, 32), src);
3190     painter.end();
3191
3192     dest = dest.convertToFormat(QImage::Format_RGB32);
3193
3194     dest.save("dest.png");
3195     expected.save("expected.png");
3196     QCOMPARE(dest, expected);
3197 }
3198
3199 void tst_QPainter::clipRectSaveRestore()
3200 {
3201     QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
3202     img.fill(0x0);
3203
3204     QPainter p(&img);
3205     p.setClipRect(QRect(0, 0, 10, 10));
3206     p.save();
3207     p.setClipRect(QRect(5, 5, 5, 5), Qt::IntersectClip);
3208     p.restore();
3209     p.fillRect(0, 0, 64, 64, Qt::black);
3210     p.end();
3211
3212     QCOMPARE(img.pixel(0, 0), QColor(Qt::black).rgba());
3213 }
3214
3215 void tst_QPainter::clippedImage()
3216 {
3217     QImage img(16, 16, QImage::Format_ARGB32_Premultiplied);
3218     img.fill(0x0);
3219
3220     QImage src(16, 16, QImage::Format_RGB32);
3221     src.fill(QColor(Qt::red).rgba());
3222
3223     QPainter p(&img);
3224     p.setClipRect(QRect(1, 1, 14, 14));
3225     p.drawImage(0, 0, src);
3226     p.end();
3227
3228     QCOMPARE(img.pixel(0, 0), 0x0U);
3229     QCOMPARE(img.pixel(1, 1), src.pixel(1, 1));
3230 }
3231
3232 void tst_QPainter::stateResetBetweenQPainters()
3233 {
3234     QImage img(16, 16, QImage::Format_ARGB32);
3235
3236     {
3237         QPainter p(&img);
3238         p.setCompositionMode(QPainter::CompositionMode_Source);
3239         p.fillRect(0, 0, 16, 16, Qt::red);
3240     }
3241
3242     {
3243         QPainter p2(&img);
3244         p2.fillRect(0, 0, 16, 16, QColor(0, 0, 255, 63));
3245     }
3246
3247     img.save("foo.png");
3248
3249     QVERIFY(img.pixel(0, 0) != qRgba(0, 0, 255, 63));
3250     QVERIFY(qRed(img.pixel(0, 0)) > 0); // We didn't erase the red channel...
3251     QVERIFY(qBlue(img.pixel(0, 0)) < 255); // We blended the blue channel
3252 }
3253
3254 void tst_QPainter::drawRect_task215378()
3255 {
3256     QImage img(11, 11, QImage::Format_ARGB32_Premultiplied);
3257     img.fill(QColor(Qt::white).rgba());
3258
3259     QPainter p(&img);
3260     p.setPen(QColor(127, 127, 127, 127));
3261     p.drawRect(0, 0, 10, 10);
3262     p.end();
3263
3264     QCOMPARE(img.pixel(0, 0), img.pixel(1, 0));
3265     QCOMPARE(img.pixel(0, 0), img.pixel(0, 1));
3266     QVERIFY(img.pixel(0, 0) != img.pixel(1, 1));
3267 }
3268
3269 void tst_QPainter::drawRect_task247505()
3270 {
3271     QImage a(10, 10, QImage::Format_ARGB32_Premultiplied);
3272     a.fill(0);
3273     QImage b = a;
3274
3275     QPainter p(&a);
3276     p.setPen(Qt::NoPen);
3277     p.setBrush(Qt::black);
3278     p.drawRect(QRectF(10, 0, -10, 10));
3279     p.end();
3280     p.begin(&b);
3281     p.setPen(Qt::NoPen);
3282     p.setBrush(Qt::black);
3283     p.drawRect(QRectF(0, 0, 10, 10));
3284     p.end();
3285
3286     QCOMPARE(a, b);
3287 }
3288
3289 void tst_QPainter::drawImage_data()
3290 {
3291     QTest::addColumn<int>("x");
3292     QTest::addColumn<int>("y");
3293     QTest::addColumn<int>("w");
3294     QTest::addColumn<int>("h");
3295     QTest::addColumn<QImage::Format>("srcFormat");
3296     QTest::addColumn<QImage::Format>("dstFormat");
3297
3298     for (int srcFormat = QImage::Format_Mono; srcFormat < QImage::NImageFormats; ++srcFormat) {
3299         for (int dstFormat = QImage::Format_Mono; dstFormat < QImage::NImageFormats; ++dstFormat) {
3300             if (dstFormat == QImage::Format_Indexed8)
3301                 continue;
3302             for (int odd_x = 0; odd_x <= 1; ++odd_x) {
3303                 for (int odd_width = 0; odd_width <= 1; ++odd_width) {
3304                     QString description =
3305                         QString("srcFormat %1, dstFormat %2, odd x: %3, odd width: %4")
3306                             .arg(srcFormat).arg(dstFormat).arg(odd_x).arg(odd_width);
3307
3308                     QTest::newRow(qPrintable(description)) << (10 + odd_x) << 10 << (20 + odd_width) << 20
3309                         << QImage::Format(srcFormat)
3310                         << QImage::Format(dstFormat);
3311                 }
3312             }
3313         }
3314     }
3315 }
3316
3317 bool verifyImage(const QImage &img, int x, int y, int w, int h, uint background)
3318 {
3319     int imgWidth = img.width();
3320     int imgHeight = img.height();
3321     for (int i = 0; i < imgHeight; ++i) {
3322         for (int j = 0; j < imgWidth; ++j) {
3323             uint pixel = img.pixel(j, i);
3324             bool outside = j < x || j >= (x + w) || i < y || i >= (y + h);
3325             if (outside != (pixel == background)) {
3326                 //printf("%d %d, expected %x, got %x, outside: %d\n", x, y, background, pixel, outside);
3327                 return false;
3328             }
3329         }
3330     }
3331
3332     return true;
3333 }
3334
3335 void tst_QPainter::drawImage()
3336 {
3337     QFETCH(int, x);
3338     QFETCH(int, y);
3339     QFETCH(int, w);
3340     QFETCH(int, h);
3341     QFETCH(QImage::Format, srcFormat);
3342     QFETCH(QImage::Format, dstFormat);
3343
3344     QImage dst(40, 40, QImage::Format_RGB32);
3345     dst.fill(0xffffffff);
3346
3347     dst = dst.convertToFormat(dstFormat);
3348     uint background = dst.pixel(0, 0);
3349
3350     QImage src(w, h, QImage::Format_RGB32);
3351     src.fill(0xff000000);
3352     src = src.convertToFormat(srcFormat);
3353
3354     QPainter p(&dst);
3355     p.drawImage(x, y, src);
3356     p.end();
3357
3358     QVERIFY(verifyImage(dst, x, y, w, h, background));
3359 }
3360
3361 void tst_QPainter::imageCoordinateLimit()
3362 {
3363     QImage img(64, 40000, QImage::Format_MonoLSB);
3364     QPainter p(&img);
3365     p.drawText(10, 36000, QLatin1String("foo"));
3366     p.setPen(QPen(Qt::black, 2));
3367     p.drawLine(10, 0, 60, 40000);
3368
3369     p.setRenderHint(QPainter::Antialiasing);
3370     p.drawLine(10, 0, 60, 40000);
3371 }
3372
3373
3374 void tst_QPainter::imageBlending_data()
3375 {
3376     QTest::addColumn<QImage::Format>("sourceFormat");
3377     QTest::addColumn<QImage::Format>("destFormat");
3378     QTest::addColumn<int>("error");
3379
3380     int error_rgb565 = ((1<<3) + (1<<2) + (1<<3));
3381     QTest::newRow("rgb565_on_rgb565") << QImage::Format_RGB16
3382                                       << QImage::Format_RGB16
3383                                       << 0;
3384     QTest::newRow("argb8565_on_rgb565") << QImage::Format_ARGB8565_Premultiplied
3385                                         << QImage::Format_RGB16
3386                                         << error_rgb565;
3387
3388     QTest::newRow("rgb32_on_rgb565") << QImage::Format_RGB32
3389                                      << QImage::Format_RGB16
3390                                      << error_rgb565;
3391
3392     QTest::newRow("argb32pm_on_rgb565") << QImage::Format_ARGB32_Premultiplied
3393                                         << QImage::Format_RGB16
3394                                         << error_rgb565;
3395 }
3396
3397 int diffColor(quint32 ap, quint32 bp)
3398 {
3399     int a = qAlpha(ap) - qAlpha(bp);
3400     int r = qRed(ap) - qRed(bp);
3401     int b = qBlue(ap) - qBlue(bp);
3402     int g = qBlue(ap) - qBlue(bp);
3403
3404     return qAbs(a) + qAbs(r) + qAbs(g) + qAbs(b);
3405 }
3406
3407 // this test assumes premultiplied pixels...
3408
3409 void tst_QPainter::imageBlending()
3410 {
3411     QFETCH(QImage::Format, sourceFormat);
3412     QFETCH(QImage::Format, destFormat);
3413     QFETCH(int, error);
3414
3415     QImage dest;
3416     {
3417         QImage orig_dest(6, 6, QImage::Format_ARGB32_Premultiplied);
3418         orig_dest.fill(0);
3419         QPainter p(&orig_dest);
3420         p.fillRect(0, 0, 6, 3, QColor::fromRgbF(1, 0, 0));
3421         p.fillRect(3, 0, 3, 6, QColor::fromRgbF(0, 0, 1, 0.5));
3422         p.end();
3423         dest = orig_dest.convertToFormat(destFormat);
3424
3425         // An image like this: (r = red, m = magenta, b = light alpha blue, 0 = transparent)
3426         // r r r m m m
3427         // r r r m m m
3428         // r r r m m m
3429         // 0 0 0 b b b
3430         // 0 0 0 b b b
3431         // 0 0 0 b b b
3432     }
3433
3434     QImage source;
3435     {
3436         QImage orig_source(6, 6, QImage::Format_ARGB32_Premultiplied);
3437         orig_source.fill(0);
3438         QPainter p(&orig_source);
3439         p.fillRect(1, 1, 4, 4, QColor::fromRgbF(0, 1, 0, 0.5));
3440         p.fillRect(2, 2, 2, 2, QColor::fromRgbF(0, 1, 0));
3441         p.end();
3442         source = orig_source.convertToFormat(sourceFormat);
3443
3444         // An image like this: (0 = transparent, . = green at 0.5 alpha, g = opaque green.
3445         // 0 0 0 0 0 0
3446         // 0 . . . . 0
3447         // 0 . g g . 0
3448         // 0 . g g . 0
3449         // 0 . . . . 0
3450         // 0 0 0 0 0 0
3451     }
3452
3453     QPainter p(&dest);
3454     p.drawImage(0, 0, source);
3455     p.end();
3456
3457     // resulting image:
3458     // r  r  r  m  m  m
3459     // r  r. r. m. m. m
3460     // r  r. g  g  m. m
3461     // 0  .  g  g  b. b
3462     // 0  .  .  b. b. b
3463     // 0  0  0  b  b  b
3464
3465     // the g pixels, always green..
3466     QVERIFY(diffColor(dest.pixel(2, 2), 0xff00ff00) <= error); // g
3467
3468     if (source.hasAlphaChannel()) {
3469         QVERIFY(diffColor(dest.pixel(0, 0), 0xffff0000) <= error); // r
3470         QVERIFY(diffColor(dest.pixel(5, 0), 0xff7f007f) <= error); // m
3471         QVERIFY(diffColor(dest.pixel(1, 1), 0xff7f7f00) <= error); // r.
3472         QVERIFY(diffColor(dest.pixel(4, 1), 0xff3f7f3f) <= error); // m.
3473         if (dest.hasAlphaChannel()) {
3474             QVERIFY(diffColor(dest.pixel(1, 3), 0x7f007f00) <= error); // .
3475             QVERIFY(diffColor(dest.pixel(4, 3), 0x7f007f3f) <= error); // b.
3476             QVERIFY(diffColor(dest.pixel(4, 3), 0x7f007f3f) <= error); // b.
3477             QVERIFY(diffColor(dest.pixel(4, 4), 0x7f00007f) <= error); // b
3478             QVERIFY(diffColor(dest.pixel(4, 0), 0) <= 0); // 0
3479        }
3480     } else {
3481         QVERIFY(diffColor(dest.pixel(0, 0), 0xff000000) <= 0);
3482         QVERIFY(diffColor(dest.pixel(1, 1), 0xff007f00) <= error);
3483     }
3484 }
3485
3486 void tst_QPainter::imageBlending_clipped()
3487 {
3488     QImage src(20, 20, QImage::Format_RGB16);
3489     QPainter p(&src);
3490     p.fillRect(src.rect(), Qt::red);
3491     p.end();
3492
3493     QImage dst(40, 20, QImage::Format_RGB16);
3494     p.begin(&dst);
3495     p.fillRect(dst.rect(), Qt::white);
3496     p.end();
3497
3498     QImage expected = dst;
3499
3500     p.begin(&dst);
3501     p.setClipRect(QRect(23, 0, 20, 20));
3502
3503     // should be completely clipped
3504     p.drawImage(QRectF(3, 0, 20, 20), src);
3505     p.end();
3506
3507     // dst should be left unchanged
3508     QCOMPARE(dst, expected);
3509 }
3510
3511 void tst_QPainter::paintOnNullPixmap()
3512 {
3513     QPixmap pix(16, 16);
3514
3515     QPixmap textPixmap;
3516     QPainter p(&textPixmap);
3517     p.drawPixmap(10, 10, pix);
3518     p.end();
3519
3520     QPixmap textPixmap2(16,16);
3521     p.begin(&textPixmap2);
3522     p.end();
3523 }
3524
3525 void tst_QPainter::checkCompositionMode()
3526 {
3527     QImage refImage(50,50,QImage::Format_ARGB32);
3528     QPainter painter(&refImage);
3529     painter.fillRect(QRect(0,0,50,50),Qt::blue);
3530
3531     QImage testImage(50,50,QImage::Format_ARGB32);
3532     QPainter p(&testImage);
3533     p.fillRect(QRect(0,0,50,50),Qt::red);
3534     p.save();
3535     p.setCompositionMode(QPainter::CompositionMode_SourceOut);
3536     p.restore();
3537     p.fillRect(QRect(0,0,50,50),Qt::blue);
3538
3539     QCOMPARE(refImage.pixel(20,20),testImage.pixel(20,20));
3540 }
3541
3542 static QLinearGradient inverseGradient(QLinearGradient g)
3543 {
3544     QLinearGradient g2 = g;
3545
3546     QGradientStops stops = g.stops();
3547
3548     QGradientStops inverse;
3549     foreach (QGradientStop stop, stops)
3550         inverse << QGradientStop(1 - stop.first, stop.second);
3551
3552     g2.setStops(inverse);
3553     return g2;
3554 }
3555
3556 void tst_QPainter::linearGradientSymmetry_data()
3557 {
3558     QTest::addColumn<QGradientStops>("stops");
3559
3560     if (sizeof(qreal) != sizeof(float)) {
3561         QGradientStops stops;
3562         stops << qMakePair(qreal(0.0), QColor(Qt::blue));
3563         stops << qMakePair(qreal(0.2), QColor(220, 220, 220, 0));
3564         stops << qMakePair(qreal(0.6), QColor(Qt::red));
3565         stops << qMakePair(qreal(0.9), QColor(220, 220, 220, 255));
3566         stops << qMakePair(qreal(1.0), QColor(Qt::black));
3567         QTest::newRow("multiple stops") << stops;
3568     }
3569
3570     {
3571         QGradientStops stops;
3572         stops << qMakePair(qreal(0.0), QColor(Qt::blue));
3573         stops << qMakePair(qreal(1.0), QColor(Qt::black));
3574         QTest::newRow("two stops") << stops;
3575     }
3576
3577     if (sizeof(qreal) != sizeof(float)) {
3578         QGradientStops stops;
3579         stops << qMakePair(qreal(0.3), QColor(Qt::blue));
3580         stops << qMakePair(qreal(0.6), QColor(Qt::black));
3581         QTest::newRow("two stops 2") << stops;
3582     }
3583 }
3584
3585 void tst_QPainter::linearGradientSymmetry()
3586 {
3587     QFETCH(QGradientStops, stops);
3588
3589     QImage a(64, 8, QImage::Format_ARGB32_Premultiplied);
3590     QImage b(64, 8, QImage::Format_ARGB32_Premultiplied);
3591
3592     a.fill(0);
3593     b.fill(0);
3594
3595     QLinearGradient gradient(QRectF(b.rect()).topLeft(), QRectF(b.rect()).topRight());
3596     gradient.setStops(stops);
3597
3598     QPainter pa(&a);
3599     pa.fillRect(a.rect(), gradient);
3600     pa.end();
3601
3602     QPainter pb(&b);
3603     pb.fillRect(b.rect(), inverseGradient(gradient));
3604     pb.end();
3605
3606     b = b.mirrored(true);
3607     QCOMPARE(a, b);
3608 }
3609
3610 void tst_QPainter::gradientInterpolation()
3611 {
3612     QImage image(256, 8, QImage::Format_ARGB32_Premultiplied);
3613     QPainter painter;
3614
3615     QLinearGradient gradient(QRectF(image.rect()).topLeft(), QRectF(image.rect()).topRight());
3616     gradient.setColorAt(0.0, QColor(255, 0, 0, 0));
3617     gradient.setColorAt(1.0, Qt::blue);
3618
3619     image.fill(0);
3620     painter.begin(&image);
3621     painter.fillRect(image.rect(), gradient);
3622     painter.end();
3623
3624     const QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(3));
3625
3626     for (int i = 0; i < 256; ++i) {
3627         QCOMPARE(qAlpha(line[i]), qBlue(line[i])); // bright blue
3628         QVERIFY(qAbs(qAlpha(line[i]) - i) < 3); // linear alpha
3629         QCOMPARE(qRed(line[i]), 0); // no red component
3630         QCOMPARE(qGreen(line[i]), 0); // no green component
3631     }
3632
3633     gradient.setInterpolationMode(QGradient::ComponentInterpolation);
3634
3635     image.fill(0);
3636     painter.begin(&image);
3637     painter.fillRect(image.rect(), gradient);
3638     painter.end();
3639
3640     for (int i = 1; i < 256; ++i) {
3641         if (i < 128) {
3642             QVERIFY(qRed(line[i]) >= qBlue(line[i])); // red is dominant
3643         } else {
3644             QVERIFY(qRed(line[i]) <= qBlue(line[i])); // blue is dominant
3645         }
3646         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
3647         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
3648         QVERIFY(qAbs(qAlpha(line[i]) - i) < 3); // linear alpha
3649         QCOMPARE(qGreen(line[i]), 0); // no green component
3650     }
3651 }
3652
3653 void tst_QPainter::drawPolygon()
3654 {
3655     QImage img(128, 128, QImage::Format_ARGB32_Premultiplied);
3656
3657     QPainterPathStroker stroker;
3658     stroker.setWidth(1.5);
3659
3660     QPainterPath path;
3661     path.moveTo(2, 34);
3662     path.lineTo(34, 2);
3663
3664     QPolygonF poly = stroker.createStroke(path).toFillPolygon();
3665
3666     img.fill(0xffffffff);
3667     QPainter p(&img);
3668     p.setRenderHint(QPainter::Antialiasing);
3669     p.setBrush(Qt::red);
3670     p.setPen(Qt::NoPen);
3671     p.drawPolygon(poly);
3672     p.translate(64, 64);
3673     p.drawPolygon(poly);
3674     p.end();
3675
3676     QImage a = img.copy();
3677
3678     img.fill(0xffffffff);
3679     p.begin(&img);
3680     p.setRenderHint(QPainter::Antialiasing);
3681     p.setBrush(Qt::red);
3682     p.setPen(Qt::NoPen);
3683     p.translate(64, 64);
3684     p.drawPolygon(poly);
3685     p.resetTransform();
3686     p.drawPolygon(poly);
3687     p.end();
3688
3689     QCOMPARE(a, img);
3690 }
3691
3692 void tst_QPainter::inactivePainter()
3693 {
3694     // This test succeeds if it doesn't segfault.
3695
3696     QPainter p;
3697     QPainterPath path;
3698     QRegion region(QRect(20, 20, 60, 40));
3699     QPolygonF polygon(QVector<QPointF>() << QPointF(0, 0) << QPointF(12, 0) << QPointF(8, 6));
3700     path.addPolygon(polygon);
3701
3702     p.save();
3703     p.restore();
3704
3705     p.background();
3706     p.setBackground(QBrush(Qt::blue));
3707
3708     p.brush();
3709     p.setBrush(Qt::red);
3710     p.setBrush(Qt::NoBrush);
3711     p.setBrush(QBrush(Qt::white, Qt::DiagCrossPattern));
3712
3713     p.backgroundMode();
3714     p.setBackgroundMode(Qt::OpaqueMode);
3715
3716     p.boundingRect(QRectF(0, 0, 100, 20), Qt::AlignCenter, QLatin1String("Hello, World!"));
3717     p.boundingRect(QRect(0, 0, 100, 20), Qt::AlignCenter, QLatin1String("Hello, World!"));
3718
3719     p.brushOrigin();
3720     p.setBrushOrigin(QPointF(12, 34));
3721     p.setBrushOrigin(QPoint(12, 34));
3722
3723     p.clipPath();
3724     p.clipRegion();
3725     p.hasClipping();
3726     p.setClipPath(path);
3727     p.setClipRect(QRectF(42, 42, 42, 42));
3728     p.setClipRect(QRect(42, 42, 42, 42));
3729     p.setClipRegion(region);
3730     p.setClipping(true);
3731
3732     p.combinedMatrix();
3733     p.combinedTransform();
3734
3735     p.compositionMode();
3736     p.setCompositionMode(QPainter::CompositionMode_Plus);
3737
3738     p.device();
3739     p.deviceMatrix();
3740     p.deviceTransform();
3741
3742     p.font();
3743     p.setFont(QFont(QLatin1String("Times"), 24));
3744
3745     p.fontInfo();
3746     p.fontMetrics();
3747
3748     p.layoutDirection();
3749     p.setLayoutDirection(Qt::RightToLeft);
3750
3751     p.opacity();
3752     p.setOpacity(0.75);
3753
3754     p.pen();
3755     p.setPen(QPen(Qt::red));
3756     p.setPen(Qt::green);
3757     p.setPen(Qt::NoPen);
3758
3759     p.renderHints();
3760     p.setRenderHint(QPainter::Antialiasing, true);
3761     p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false);
3762
3763     p.resetMatrix();
3764     p.resetTransform();
3765     p.rotate(1);
3766     p.scale(2, 2);
3767     p.shear(-1, 1);
3768     p.translate(3, 14);
3769
3770     p.viewTransformEnabled();
3771     p.setViewTransformEnabled(true);
3772
3773     p.viewport();
3774     p.setViewport(QRect(10, 10, 620, 460));
3775
3776     p.window();
3777     p.setWindow(QRect(10, 10, 620, 460));
3778
3779     p.worldMatrix();
3780     p.setWorldMatrix(QMatrix().translate(43, 21), true);
3781     p.setWorldMatrixEnabled(true);
3782
3783     p.transform();
3784     p.setTransform(QTransform().translate(12, 34), true);
3785
3786     p.worldTransform();
3787     p.setWorldTransform(QTransform().scale(0.5, 0.5), true);
3788 }
3789
3790 bool testCompositionMode(int src, int dst, int expected, QPainter::CompositionMode op, qreal opacity = 1.0)
3791 {
3792     // The test image needs to be large enough to test SIMD code
3793     const QSize imageSize(100, 100);
3794
3795     QImage actual(imageSize, QImage::Format_ARGB32_Premultiplied);
3796     actual.fill(QColor(dst, dst, dst).rgb());
3797
3798     QPainter p(&actual);
3799     p.setCompositionMode(op);
3800     p.setOpacity(opacity);
3801     p.fillRect(QRect(QPoint(), imageSize), QColor(src, src, src));
3802     p.end();
3803
3804     if (qRed(actual.pixel(0, 0)) != expected) {
3805         qDebug("Fail: mode %d, src[%d] dst [%d] actual [%d] expected [%d]", op,
3806                src, dst, qRed(actual.pixel(0, 0)), expected);
3807         return false;
3808     } else {
3809         QImage refImage(imageSize, QImage::Format_ARGB32_Premultiplied);
3810         refImage.fill(QColor(expected, expected, expected).rgb());
3811         return actual == refImage;
3812     }
3813 }
3814
3815 void tst_QPainter::extendedBlendModes()
3816 {
3817     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Plus));
3818     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Plus));
3819     QVERIFY(testCompositionMode(127, 128, 255, QPainter::CompositionMode_Plus));
3820     QVERIFY(testCompositionMode(127,   0, 127, QPainter::CompositionMode_Plus));
3821     QVERIFY(testCompositionMode(  0, 127, 127, QPainter::CompositionMode_Plus));
3822     QVERIFY(testCompositionMode(255,   0, 255, QPainter::CompositionMode_Plus));
3823     QVERIFY(testCompositionMode(  0, 255, 255, QPainter::CompositionMode_Plus));
3824     QVERIFY(testCompositionMode(128, 128, 255, QPainter::CompositionMode_Plus));
3825
3826     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Plus, 0.3));
3827     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Plus, 0.3));
3828     QVERIFY(testCompositionMode(127, 128, 165, QPainter::CompositionMode_Plus, 0.3));
3829     QVERIFY(testCompositionMode(127,   0,  37, QPainter::CompositionMode_Plus, 0.3));
3830     QVERIFY(testCompositionMode(  0, 127, 127, QPainter::CompositionMode_Plus, 0.3));
3831     QVERIFY(testCompositionMode(255,   0,  75, QPainter::CompositionMode_Plus, 0.3));
3832     QVERIFY(testCompositionMode(  0, 255, 255, QPainter::CompositionMode_Plus, 0.3));
3833     QVERIFY(testCompositionMode(128, 128, 166, QPainter::CompositionMode_Plus, 0.3));
3834     QVERIFY(testCompositionMode(186, 200, 255, QPainter::CompositionMode_Plus, 0.3));
3835
3836     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Multiply));
3837     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Multiply));
3838     QVERIFY(testCompositionMode(127, 255, 127, QPainter::CompositionMode_Multiply));
3839     QVERIFY(testCompositionMode(255, 127, 127, QPainter::CompositionMode_Multiply));
3840     QVERIFY(testCompositionMode( 63, 255,  63, QPainter::CompositionMode_Multiply));
3841     QVERIFY(testCompositionMode(255,  63,  63, QPainter::CompositionMode_Multiply));
3842     QVERIFY(testCompositionMode(127, 127,  63, QPainter::CompositionMode_Multiply));
3843
3844     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Screen));
3845     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Screen));
3846     QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Screen));
3847     QVERIFY(testCompositionMode(255,  63, 255, QPainter::CompositionMode_Screen));
3848     QVERIFY(testCompositionMode( 63,   0,  63, QPainter::CompositionMode_Screen));
3849     QVERIFY(testCompositionMode(  0,  63,  63, QPainter::CompositionMode_Screen));
3850     QVERIFY(testCompositionMode(127, 127, 191, QPainter::CompositionMode_Screen));
3851
3852     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Overlay));
3853     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Overlay));
3854     QVERIFY(testCompositionMode( 63,  63,  31, QPainter::CompositionMode_Overlay));
3855     QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Overlay));
3856
3857     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Darken));
3858     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Darken));
3859     QVERIFY(testCompositionMode( 63,  63,  63, QPainter::CompositionMode_Darken));
3860     QVERIFY(testCompositionMode( 63, 255,  63, QPainter::CompositionMode_Darken));
3861     QVERIFY(testCompositionMode(255,  63,  63, QPainter::CompositionMode_Darken));
3862     QVERIFY(testCompositionMode( 63, 127,  63, QPainter::CompositionMode_Darken));
3863     QVERIFY(testCompositionMode(127,  63,  63, QPainter::CompositionMode_Darken));
3864
3865     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Lighten));
3866     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Lighten));
3867     QVERIFY(testCompositionMode( 63,  63,  63, QPainter::CompositionMode_Lighten));
3868     QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Lighten));
3869     QVERIFY(testCompositionMode(255,  63, 255, QPainter::CompositionMode_Lighten));
3870     QVERIFY(testCompositionMode( 63, 127, 127, QPainter::CompositionMode_Lighten));
3871     QVERIFY(testCompositionMode(127,  63, 127, QPainter::CompositionMode_Lighten));
3872
3873     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_ColorDodge));
3874     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_ColorDodge));
3875     QVERIFY(testCompositionMode( 63, 127, 169, QPainter::CompositionMode_ColorDodge));
3876     QVERIFY(testCompositionMode(191, 127, 255, QPainter::CompositionMode_ColorDodge));
3877     QVERIFY(testCompositionMode(127, 191, 255, QPainter::CompositionMode_ColorDodge));
3878
3879     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_ColorBurn));
3880     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_ColorBurn));
3881     QVERIFY(testCompositionMode(127, 127,   0, QPainter::CompositionMode_ColorBurn));
3882     QVERIFY(testCompositionMode(128, 128,   2, QPainter::CompositionMode_ColorBurn));
3883     QVERIFY(testCompositionMode(191, 127,  84, QPainter::CompositionMode_ColorBurn));
3884
3885     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_HardLight));
3886     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_HardLight));
3887     QVERIFY(testCompositionMode(127, 127, 127, QPainter::CompositionMode_HardLight));
3888     QVERIFY(testCompositionMode( 63,  63,  31, QPainter::CompositionMode_HardLight));
3889     QVERIFY(testCompositionMode(127,  63,  63, QPainter::CompositionMode_HardLight));
3890
3891     QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_SoftLight));
3892     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_SoftLight));
3893     QVERIFY(testCompositionMode(127, 127, 126, QPainter::CompositionMode_SoftLight));
3894     QVERIFY(testCompositionMode( 63,  63,  39, QPainter::CompositionMode_SoftLight));
3895     QVERIFY(testCompositionMode(127,  63,  62, QPainter::CompositionMode_SoftLight));
3896
3897     QVERIFY(testCompositionMode(255, 255,   0, QPainter::CompositionMode_Difference));
3898     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Difference));
3899     QVERIFY(testCompositionMode(255,   0, 255, QPainter::CompositionMode_Difference));
3900     QVERIFY(testCompositionMode(127, 127,   0, QPainter::CompositionMode_Difference));
3901     QVERIFY(testCompositionMode(127, 128,   1, QPainter::CompositionMode_Difference));
3902     QVERIFY(testCompositionMode(127,  63,  64, QPainter::CompositionMode_Difference));
3903     QVERIFY(testCompositionMode(  0, 127, 127, QPainter::CompositionMode_Difference));
3904
3905     QVERIFY(testCompositionMode(255, 255,   0, QPainter::CompositionMode_Exclusion));
3906     QVERIFY(testCompositionMode(  0,   0,   0, QPainter::CompositionMode_Exclusion));
3907     QVERIFY(testCompositionMode(255,   0, 255, QPainter::CompositionMode_Exclusion));
3908     QVERIFY(testCompositionMode(127, 127, 127, QPainter::CompositionMode_Exclusion));
3909     QVERIFY(testCompositionMode( 63, 127, 127, QPainter::CompositionMode_Exclusion));
3910     QVERIFY(testCompositionMode( 63,  63,  95, QPainter::CompositionMode_Exclusion));
3911     QVERIFY(testCompositionMode(191, 191,  96, QPainter::CompositionMode_Exclusion));
3912 }
3913
3914 void tst_QPainter::zeroOpacity()
3915 {
3916     QImage source(1, 1, QImage::Format_ARGB32_Premultiplied);
3917     source.fill(0xffffffff);
3918
3919     QImage target(1, 1, QImage::Format_RGB32);
3920     target.fill(0xff000000);
3921
3922     QPainter p(&target);
3923     p.setOpacity(0.0);
3924     p.drawImage(0, 0, source);
3925     p.end();
3926
3927     QCOMPARE(target.pixel(0, 0), 0xff000000);
3928 }
3929
3930 void tst_QPainter::clippingBug()
3931 {
3932     QImage img(32, 32, QImage::Format_ARGB32_Premultiplied);
3933     img.fill(0);
3934
3935     QImage expected = img;
3936     QPainter p(&expected);
3937     p.fillRect(1, 1, 30, 30, Qt::red);
3938     p.end();
3939
3940     QPainterPath path;
3941     path.addRect(1, 1, 30, 30);
3942     path.addRect(1, 1, 30, 30);
3943     path.addRect(1, 1, 30, 30);
3944
3945     p.begin(&img);
3946     p.setClipPath(path);
3947     p.fillRect(0, 0, 32, 32, Qt::red);
3948     p.end();
3949
3950     QCOMPARE(img, expected);
3951 }
3952
3953 void tst_QPainter::emptyClip()
3954 {
3955     QImage img(64, 64, QImage::Format_ARGB32_Premultiplied);
3956     QPainter p(&img);
3957     p.setRenderHints(QPainter::Antialiasing);
3958     p.setClipRect(0, 32, 64, 0);
3959     p.fillRect(0, 0, 64, 64, Qt::white);
3960
3961     QPainterPath path;
3962     path.lineTo(64, 0);
3963     path.lineTo(64, 64);
3964     path.lineTo(40, 64);
3965     path.lineTo(40, 80);
3966     path.lineTo(0, 80);
3967
3968     p.fillPath(path, Qt::green);
3969 }
3970
3971 void tst_QPainter::drawImage_1x1()
3972 {
3973     QImage source(1, 1, QImage::Format_ARGB32_Premultiplied);
3974     source.fill(0xffffffff);
3975
3976     QImage img(32, 32, QImage::Format_ARGB32_Premultiplied);
3977     img.fill(0xff000000);
3978     QPainter p(&img);
3979     p.drawImage(QRectF(0.9, 0.9, 32, 32), source);
3980     p.end();
3981
3982     QImage expected = img;
3983     expected.fill(0xff000000);
3984     p.begin(&expected);
3985     p.fillRect(1, 1, 31, 31, Qt::white);
3986     p.end();
3987
3988     QCOMPARE(img, expected);
3989 }
3990
3991 void tst_QPainter::taskQT4444_dontOverflowDashOffset()
3992 {
3993     QPainter p;
3994
3995     QPen pen;
3996     pen.setWidth(2);
3997     pen.setStyle(Qt::DashDotLine);
3998
3999     QPointF point[4];
4000     point[0] = QPointF(182.50868749707968,347.78457234212630);
4001     point[1] = QPointF(182.50868749707968,107.22501998401277);
4002     point[2] = QPointF(182.50868749707968,107.22501998401277);
4003     point[3] = QPointF(520.46600762283651,107.22501998401277);
4004
4005     QImage crashImage(QSize(1000, 120), QImage::Format_ARGB32_Premultiplied);
4006     p.begin(&crashImage);
4007     p.setPen(pen);
4008     p.drawLines(point, 2);
4009     p.end();
4010
4011     QVERIFY(true); // Don't crash
4012 }
4013
4014 void tst_QPainter::painterBegin()
4015 {
4016     QImage nullImage;
4017     QImage indexed8Image(16, 16, QImage::Format_Indexed8);
4018     QImage rgb32Image(16, 16, QImage::Format_RGB32);
4019     QImage argb32Image(16, 16, QImage::Format_ARGB32_Premultiplied);
4020
4021     QPainter p;
4022
4023     // Painting on null image should fail.
4024     QVERIFY(!p.begin(&nullImage));
4025
4026     // Check that the painter is not messed up by using it on another image.
4027     QVERIFY(p.begin(&rgb32Image));
4028     QVERIFY(p.end());
4029
4030     // If painting on indexed8 image fails, the painter state should still be OK.
4031     if (p.begin(&indexed8Image))
4032         QVERIFY(p.end());
4033     QVERIFY(p.begin(&rgb32Image));
4034     QVERIFY(p.end());
4035
4036     // Try opening a painter on the two different images.
4037     QVERIFY(p.begin(&rgb32Image));
4038     QVERIFY(!p.begin(&argb32Image));
4039     QVERIFY(p.end());
4040
4041     // Try opening two painters on the same image.
4042     QVERIFY(p.begin(&rgb32Image));
4043     QPainter q;
4044     QVERIFY(!q.begin(&rgb32Image));
4045     QVERIFY(!q.end());
4046     QVERIFY(p.end());
4047
4048     // Try ending an inactive painter.
4049     QVERIFY(!p.end());
4050 }
4051
4052 void tst_QPainter::setPenColor(QPainter& p)
4053 {
4054     p.setPen(Qt::NoPen);
4055
4056     // Setting color, then style
4057     // Should work even though the pen is "NoPen with color", temporarily.
4058     QPen newPen(p.pen());
4059     newPen.setColor(Qt::red);
4060     QCOMPARE(p.pen().style(), newPen.style());
4061     QCOMPARE(p.pen().style(), Qt::NoPen);
4062     p.setPen(newPen);
4063
4064     QCOMPARE(p.pen().color().name(), QString("#ff0000"));
4065
4066     QPen newPen2(p.pen());
4067     newPen2.setStyle(Qt::SolidLine);
4068     p.setPen(newPen2);
4069
4070     QCOMPARE(p.pen().color().name(), QString("#ff0000"));
4071 }
4072
4073 void tst_QPainter::setPenColorOnImage()
4074 {
4075     QImage img(QSize(10, 10), QImage::Format_ARGB32_Premultiplied);
4076     QPainter p(&img);
4077     setPenColor(p);
4078 }
4079
4080 void tst_QPainter::setPenColorOnPixmap()
4081 {
4082     QPixmap pix(10, 10);
4083     QPainter p(&pix);
4084     setPenColor(p);
4085 }
4086
4087 #ifndef QT_NO_WIDGETS
4088 class TestProxy : public QGraphicsProxyWidget
4089 {
4090 public:
4091     TestProxy() : QGraphicsProxyWidget() {}
4092     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
4093     {
4094         QGraphicsProxyWidget::paint(painter, option, widget);
4095         deviceTransform = painter->deviceTransform();
4096     }
4097     QTransform deviceTransform;
4098 };
4099
4100 class TestWidget : public QWidget
4101 {
4102 Q_OBJECT
4103 public:
4104     TestWidget() : QWidget(), painted(false) {}
4105     void paintEvent(QPaintEvent *)
4106     {
4107         QPainter p(this);
4108         deviceTransform = p.deviceTransform();
4109         worldTransform = p.worldTransform();
4110         painted = true;
4111     }
4112     QTransform deviceTransform;
4113     QTransform worldTransform;
4114     bool painted;
4115 };
4116
4117 void tst_QPainter::QTBUG5939_attachPainterPrivate()
4118 {
4119     QWidget *w = new QWidget();
4120     QGraphicsScene *scene = new QGraphicsScene();
4121     QGraphicsView *view = new QGraphicsView(scene, w);
4122     view->move(50 ,50);
4123     TestProxy *proxy = new TestProxy();
4124     TestWidget *widget = new TestWidget();
4125     proxy->setWidget(widget);
4126     scene->addItem(proxy);
4127     proxy->rotate(45);
4128     w->resize(scene->sceneRect().size().toSize());
4129
4130     w->show();
4131     QTRY_VERIFY(widget->painted);
4132
4133     QVERIFY(widget->worldTransform.isIdentity());
4134     QCOMPARE(widget->deviceTransform, proxy->deviceTransform);
4135 }
4136 #endif
4137
4138 void tst_QPainter::clipBoundingRect()
4139 {
4140     QPixmap pix(500, 500);
4141
4142     QPainter p(&pix);
4143
4144     // Test a basic rectangle
4145     p.setClipRect(100, 100, 200, 100);
4146     QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
4147     QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200)));
4148     p.setClipRect(120, 120, 20, 20, Qt::IntersectClip);
4149     QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20)));
4150     QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
4151
4152     // Test a basic float rectangle
4153     p.setClipRect(QRectF(100, 100, 200, 100));
4154     QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
4155     QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200)));
4156     p.setClipRect(QRectF(120, 120, 20, 20), Qt::IntersectClip);
4157     QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20)));
4158     QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
4159
4160     // Test a basic path + region
4161     QPainterPath path;
4162     path.addRect(100, 100, 200, 100);
4163     p.setClipPath(path);
4164     QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
4165     QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200)));
4166     p.setClipRegion(QRegion(120, 120, 20, 20), Qt::IntersectClip);
4167     QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20)));
4168     QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
4169
4170     p.setClipRect(0, 0, 500, 500);
4171     p.translate(250, 250);
4172     for (int i=0; i<360; ++i) {
4173         p.rotate(1);
4174         p.setClipRect(-100, -100, 200, 200, Qt::IntersectClip);
4175     }
4176     QVERIFY(p.clipBoundingRect().contains(QRectF(-100, -100, 200, 200)));
4177     QVERIFY(!p.clipBoundingRect().contains(QRectF(-250, -250, 500, 500)));
4178
4179 }
4180
4181 void tst_QPainter::drawText_subPixelPositionsInRaster_qtbug5053()
4182 {
4183 #if !defined(Q_OS_MAC)
4184     QSKIP("Only Mac supports sub pixel positions in raster engine currently");
4185 #endif
4186     QFontMetricsF fm(qApp->font());
4187
4188     QImage baseLine(fm.width(QChar::fromLatin1('e')), fm.height(), QImage::Format_RGB32);
4189     baseLine.fill(Qt::white);
4190     {
4191         QPainter p(&baseLine);
4192         p.setRenderHint(QPainter::Qt4CompatiblePainting);
4193         p.drawText(0, fm.ascent(), QString::fromLatin1("e"));
4194     }
4195
4196     bool foundDifferentRasterization = false;
4197     for (int i=1; i<12; ++i) {
4198         QImage comparison(baseLine.size(), QImage::Format_RGB32);
4199         comparison.fill(Qt::white);
4200
4201         {
4202             QPainter p(&comparison);
4203             p.setRenderHint(QPainter::Qt4CompatiblePainting);
4204             p.drawText(QPointF(i / 12.0, fm.ascent()), QString::fromLatin1("e"));
4205         }
4206
4207         if (comparison != baseLine) {
4208             foundDifferentRasterization = true;
4209             break;
4210         }
4211     }
4212
4213     QVERIFY(foundDifferentRasterization);
4214 }
4215
4216 void tst_QPainter::drawPointScaled()
4217 {
4218     QImage image(32, 32, QImage::Format_RGB32);
4219     image.fill(0xffffffff);
4220
4221     QPainter p(&image);
4222
4223     p.scale(0.1, 0.1);
4224
4225     QPen pen;
4226     pen.setWidth(1000);
4227     pen.setColor(Qt::red);
4228
4229     p.setPen(pen);
4230     p.drawPoint(0, 0);
4231     p.end();
4232
4233     QCOMPARE(image.pixel(16, 16), 0xffff0000);
4234 }
4235
4236 class GradientProducer : public QThread
4237 {
4238 protected:
4239     void run();
4240 };
4241
4242 void GradientProducer::run()
4243 {
4244     QImage image(1, 1, QImage::Format_RGB32);
4245     QPainter p(&image);
4246
4247     for (int i = 0; i < 1000; ++i) {
4248         QLinearGradient g;
4249         g.setColorAt(0, QColor(i % 256, 0, 0));
4250         g.setColorAt(1, Qt::white);
4251
4252         p.fillRect(image.rect(), g);
4253     }
4254 }
4255
4256 void tst_QPainter::QTBUG14614_gradientCacheRaceCondition()
4257 {
4258     const int threadCount = 16;
4259     GradientProducer producers[threadCount];
4260     for (int i = 0; i < threadCount; ++i)
4261         producers[i].start();
4262     for (int i = 0; i < threadCount; ++i)
4263         producers[i].wait();
4264 }
4265
4266 void tst_QPainter::drawTextOpacity()
4267 {
4268     QImage image(32, 32, QImage::Format_RGB32);
4269     image.fill(0xffffffff);
4270
4271     QPainter p(&image);
4272     p.setPen(QColor("#6F6F6F"));
4273     p.setOpacity(0.5);
4274     p.drawText(5, 30, QLatin1String("Qt"));
4275     p.end();
4276
4277     QImage copy = image;
4278     image.fill(0xffffffff);
4279
4280     p.begin(&image);
4281     p.setPen(QColor("#6F6F6F"));
4282     p.drawLine(-10, -10, -1, -1);
4283     p.setOpacity(0.5);
4284     p.drawText(5, 30, QLatin1String("Qt"));
4285     p.end();
4286
4287     QCOMPARE(image, copy);
4288 }
4289
4290 void tst_QPainter::QTBUG17053_zeroDashPattern()
4291 {
4292     QImage image(32, 32, QImage::Format_RGB32);
4293     image.fill(0xffffffff);
4294
4295     QImage original = image;
4296
4297     QVector<qreal> pattern;
4298     pattern << qreal(0) << qreal(0);
4299
4300     QPainter p(&image);
4301     QPen pen(Qt::black, 2.0);
4302     pen.setDashPattern(pattern);
4303
4304     p.setPen(pen);
4305     p.drawLine(0, 0, image.width(), image.height());
4306
4307     QCOMPARE(image, original);
4308 }
4309
4310 class TextDrawerThread : public QThread
4311 {
4312 public:
4313     void run();
4314     QImage rendering;
4315 };
4316
4317 void TextDrawerThread::run()
4318 {
4319     rendering = QImage(100, 100, QImage::Format_ARGB32_Premultiplied);
4320     rendering.fill(0);
4321     QPainter p(&rendering);
4322     p.fillRect(10, 10, 100, 100, Qt::blue);
4323     p.setPen(Qt::green);
4324     p.drawText(20, 20, "some text");
4325     p.end();
4326 }
4327
4328 void tst_QPainter::drawTextOutsideGuiThread()
4329 {
4330     if (!QFontDatabase::supportsThreadedFontRendering())
4331         QSKIP("No threaded font rendering");
4332
4333     QImage referenceRendering(100, 100, QImage::Format_ARGB32_Premultiplied);
4334     referenceRendering.fill(0);
4335     QPainter p(&referenceRendering);
4336     p.fillRect(10, 10, 100, 100, Qt::blue);
4337     p.setPen(Qt::green);
4338     p.drawText(20, 20, "some text");
4339     p.end();
4340
4341     TextDrawerThread t;
4342     t.start();
4343     t.wait();
4344
4345     QCOMPARE(referenceRendering, t.rendering);
4346 }
4347
4348 void tst_QPainter::drawTextWithComplexBrush()
4349 {
4350     QImage texture(10, 10, QImage::Format_ARGB32_Premultiplied);
4351     texture.fill(Qt::red);
4352
4353     QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
4354     image.fill(Qt::white);
4355     QPainter p(&image);
4356     QFont f = p.font();
4357     f.setPixelSize(70);
4358     p.setFont(f);
4359
4360     QBrush brush(Qt::white);
4361     brush.setTextureImage(texture);
4362     p.setPen(QPen(brush, 2));
4363
4364     p.drawText(10, 10, "Hello World");
4365
4366     int paintedPixels = getPaintedPixels(image, Qt::white);
4367     QVERIFY(paintedPixels > 0);
4368 }
4369
4370 void tst_QPainter::QTBUG26013_squareCapStroke()
4371 {
4372     QImage image(4, 4, QImage::Format_RGB32);
4373
4374     QPainter p(&image);
4375     p.setPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::SquareCap));
4376
4377     for (int i = 0; i < 3; ++i) {
4378         qreal d = i / 3.0;
4379
4380         image.fill(0xffffffff);
4381
4382         p.drawLine(QLineF(0, d, 0, d + 2));
4383         p.drawLine(QLineF(1, d, 3, d));
4384
4385         // ensure that a horizontal line and a vertical line with square cap round up (downwards) at the same time
4386         QCOMPARE(image.pixel(0, 0), image.pixel(1, 0));
4387
4388         image.fill(0xffffffff);
4389
4390         p.drawLine(QLineF(d, 0, d + 2, 0));
4391         p.drawLine(QLineF(d, 1, d, 3));
4392
4393         // ensure that a vertical line and a horizontal line with square cap round up (to the right) at the same time
4394         QCOMPARE(image.pixel(0, 0), image.pixel(0, 1));
4395     }
4396 }
4397
4398 void tst_QPainter::QTBUG25153_drawLine()
4399 {
4400     QImage image(2, 2, QImage::Format_RGB32);
4401
4402     QVector<Qt::PenCapStyle> styles;
4403     styles << Qt::FlatCap << Qt::SquareCap << Qt::RoundCap;
4404
4405     foreach (Qt::PenCapStyle style, styles) {
4406         image.fill(0xffffffff);
4407         QPainter p(&image);
4408         p.setPen(QPen(Qt::black, 0, Qt::SolidLine, style));
4409         p.drawLine(QLineF(0, 0, 0, 0));
4410         p.end();
4411
4412         QCOMPARE(image.pixel(0, 0), 0xff000000);
4413         QCOMPARE(image.pixel(0, 1), 0xffffffff);
4414         QCOMPARE(image.pixel(1, 0), 0xffffffff);
4415     }
4416 }
4417
4418 QTEST_MAIN(tst_QPainter)
4419
4420 #include "tst_qpainter.moc"