summaryrefslogtreecommitdiffstats
path: root/tests/benchmarks/gui/painting
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit38be0d13830efd2d98281c645c3a60afe05ffece (patch)
tree6ea73f3ec77f7d153333779883e8120f82820abe /tests/benchmarks/gui/painting
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'tests/benchmarks/gui/painting')
-rw-r--r--tests/benchmarks/gui/painting/painting.pro7
-rw-r--r--tests/benchmarks/gui/painting/qpainter/qpainter.pro5
-rw-r--r--tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp1666
-rw-r--r--tests/benchmarks/gui/painting/qregion/main.cpp139
-rw-r--r--tests/benchmarks/gui/painting/qregion/qregion.pro10
-rw-r--r--tests/benchmarks/gui/painting/qtbench/benchmarktests.h841
-rw-r--r--tests/benchmarks/gui/painting/qtbench/qtbench.pro6
-rw-r--r--tests/benchmarks/gui/painting/qtbench/tst_qtbench.cpp254
-rw-r--r--tests/benchmarks/gui/painting/qtracebench/qtracebench.pro10
-rw-r--r--tests/benchmarks/gui/painting/qtracebench/qtracebench.qrc10
-rw-r--r--tests/benchmarks/gui/painting/qtracebench/traces/basicdrawing.tracebin0 -> 366739 bytes
-rw-r--r--tests/benchmarks/gui/painting/qtracebench/traces/creator.tracebin0 -> 541031 bytes
-rw-r--r--tests/benchmarks/gui/painting/qtracebench/traces/qmlphoneconcept.tracebin0 -> 337439 bytes
-rw-r--r--tests/benchmarks/gui/painting/qtracebench/traces/qmlsamegame.tracebin0 -> 246423 bytes
-rw-r--r--tests/benchmarks/gui/painting/qtracebench/traces/textedit.tracebin0 -> 60042 bytes
-rw-r--r--tests/benchmarks/gui/painting/qtracebench/traces/webkit.tracebin0 -> 451391 bytes
-rw-r--r--tests/benchmarks/gui/painting/qtracebench/tst_qtracebench.cpp262
-rw-r--r--tests/benchmarks/gui/painting/qtransform/qtransform.pro6
-rw-r--r--tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp592
19 files changed, 3808 insertions, 0 deletions
diff --git a/tests/benchmarks/gui/painting/painting.pro b/tests/benchmarks/gui/painting/painting.pro
new file mode 100644
index 0000000000..76c26c1627
--- /dev/null
+++ b/tests/benchmarks/gui/painting/painting.pro
@@ -0,0 +1,7 @@
+TEMPLATE = subdirs
+SUBDIRS = \
+ qpainter \
+ qregion \
+ qtransform \
+ qtracebench \
+ qtbench
diff --git a/tests/benchmarks/gui/painting/qpainter/qpainter.pro b/tests/benchmarks/gui/painting/qpainter/qpainter.pro
new file mode 100644
index 0000000000..6603abafea
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qpainter/qpainter.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+TEMPLATE = app
+TARGET = tst_bench_qpainter
+
+SOURCES += tst_qpainter.cpp
diff --git a/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp b/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp
new file mode 100644
index 0000000000..2d33825e5c
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp
@@ -0,0 +1,1666 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QPainter>
+#include <QPixmap>
+#include <QDialog>
+#include <QImage>
+#include <QPaintEngine>
+#include <math.h>
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#include <private/qpixmap_raster_p.h>
+
+Q_DECLARE_METATYPE(QLine)
+Q_DECLARE_METATYPE(QRect)
+Q_DECLARE_METATYPE(QSize)
+Q_DECLARE_METATYPE(QPoint)
+Q_DECLARE_METATYPE(QPainterPath)
+Q_DECLARE_METATYPE(QPainter::RenderHint)
+Q_DECLARE_METATYPE(QPainter::CompositionMode)
+Q_DECLARE_METATYPE(QImage::Format)
+
+enum PrimitiveType {
+ Primitive_Int_DiagLine,
+ Primitive_Int_VerLine,
+ Primitive_Int_HorLine,
+ Primitive_Int_Rect,
+ Primitive_Int_Ellipse,
+ Primitive_Int_Pie,
+ Primitive_Int_Arc,
+ Primitive_Int_Chord,
+ Primitive_Int_TriPoly,
+ Primitive_Int_RectPoly,
+ Primitive_Int_2RectPoly,
+
+ Primitive_Float_DiagLine,
+ Primitive_Float_VerLine,
+ Primitive_Float_HorLine,
+ Primitive_Float_Rect,
+ Primitive_Float_Ellipse,
+ Primitive_Float_Pie,
+ Primitive_Float_Arc,
+ Primitive_Float_Chord,
+ Primitive_Float_TriPoly,
+ Primitive_Float_RectPoly,
+ Primitive_Float_2RectPoly,
+
+ Primitive_Float_TriPath,
+ Primitive_Float_RectPath,
+ Primitive_Float_2RectPath,
+ Primitive_Float_EllipsePath,
+ Primitive_Last_Primitive
+
+};
+
+
+enum StateChanges {
+ ChangePen = 0x0001,
+ ChangeBrush = 0x0002,
+ ChangeClip = 0x0004,
+ ChangeTransform = 0x0008
+};
+
+
+struct PrimitiveSet {
+ QRect i_rect;
+ QLine i_line_diag;
+ QLine i_line_ver;
+ QLine i_line_hor;
+ QPolygon i_poly_tri;
+ QPolygon i_poly_2rects;
+ QPolygon i_poly_rect;
+
+ QRectF f_rect;
+ QLineF f_line_diag;
+ QLineF f_line_ver;
+ QLineF f_line_hor;
+ QPolygonF f_poly_tri;
+ QPolygonF f_poly_2rects;
+ QPolygonF f_poly_rect;
+
+ QPainterPath f_path_tri;
+ QPainterPath f_path_2rects;
+ QPainterPath f_path_rect;
+ QPainterPath f_path_ellipse;
+};
+
+
+QPixmap rasterPixmap(int width, int height)
+{
+ QPixmapData *data =
+ new QRasterPixmapData(QPixmapData::PixmapType);
+
+ data->resize(width, height);
+
+ return QPixmap(data);
+}
+
+QPixmap rasterPixmap(const QSize &size)
+{
+ return rasterPixmap(size.width(), size.height());
+}
+
+QPixmap rasterPixmap(const QImage &image)
+{
+ QPixmapData *data =
+ new QRasterPixmapData(QPixmapData::PixmapType);
+
+ data->fromImage(image, Qt::AutoColor);
+
+ return QPixmap(data);
+}
+
+
+class tst_QPainter : public QObject
+{
+ Q_OBJECT
+
+ public:
+ tst_QPainter()
+ {
+ setupBrushes();
+ createPrimitives();
+ m_surface = surface();
+ }
+
+private slots:
+ void beginAndEnd();
+
+ void saveRestore_data();
+ void saveRestore();
+
+ void drawLine_data();
+ void drawLine();
+ void drawLine_clipped_data();
+ void drawLine_clipped();
+ void drawLine_antialiased_clipped_data();
+ void drawLine_antialiased_clipped();
+
+ void drawPixmap_data();
+ void drawPixmap();
+
+ void drawImage_data();
+ void drawImage();
+
+ void drawTiledPixmap_data();
+ void drawTiledPixmap();
+
+ void compositionModes_data();
+ void compositionModes();
+
+ void fillPrimitives_10_data() { drawPrimitives_data_helper(false); }
+ void fillPrimitives_100_data() { drawPrimitives_data_helper(false); }
+ void fillPrimitives_1000_data() { drawPrimitives_data_helper(false); }
+ void fillPrimitives_10();
+ void fillPrimitives_100();
+ void fillPrimitives_1000();
+
+ void strokePrimitives_10_data() { drawPrimitives_data_helper(true); }
+ void strokePrimitives_100_data() { drawPrimitives_data_helper(true); }
+ void strokePrimitives_1000_data() { drawPrimitives_data_helper(true); }
+ void strokePrimitives_10();
+ void strokePrimitives_100();
+ void strokePrimitives_1000();
+
+ void drawText_data();
+ void drawText();
+
+ void clipAndFill_data();
+ void clipAndFill();
+
+ void drawRoundedRect();
+ void drawScaledRoundedRect();
+ void drawTransformedRoundedRect();
+
+ void drawScaledAntialiasedRoundedRect_data();
+ void drawTransformedAntialiasedRoundedRect_data();
+ void drawAntialiasedRoundedRect();
+ void drawScaledAntialiasedRoundedRect();
+ void drawTransformedAntialiasedRoundedRect();
+
+ void drawScaledImageRoundedRect_data();
+ void drawTransformedImageRoundedRect_data();
+ void drawImageRoundedRect();
+ void drawScaledImageRoundedRect();
+ void drawTransformedImageRoundedRect();
+
+ void drawScaledBorderPixmapRoundedRect_data();
+ void drawTransformedBorderPixmapRoundedRect_data();
+ void drawBorderPixmapRoundedRect();
+ void drawScaledBorderPixmapRoundedRect();
+ void drawTransformedBorderPixmapRoundedRect();
+
+ void drawTransformedTransparentImage_data();
+ void drawTransformedSemiTransparentImage_data();
+ void drawTransformedFilledImage_data();
+ void drawTransformedTransparentImage();
+ void drawTransformedSemiTransparentImage();
+ void drawTransformedFilledImage();
+
+private:
+ void setupBrushes();
+ void createPrimitives();
+
+ void drawPrimitives_data_helper(bool fancypens);
+ void fillPrimitives_helper(QPainter *painter, PrimitiveType type, PrimitiveSet *s);
+
+ QTransform transformForAngle(qreal angle);
+
+ QPaintDevice *surface()
+ {
+ m_pixmap = rasterPixmap(1024, 1024);
+ return &m_pixmap;
+ }
+
+
+ QMap<QString, QPen> m_pens;
+ QMap<QString, QBrush> m_brushes;
+
+ PrimitiveSet m_primitives_10;
+ PrimitiveSet m_primitives_100;
+ PrimitiveSet m_primitives_1000;
+
+ QPixmap m_pixmap;
+ QPaintDevice *m_surface;
+ QPainter m_painter;
+
+};
+
+void tst_QPainter::createPrimitives()
+{
+ for (int i=0; i<3; ++i) {
+ PrimitiveSet *ps;
+ int size;
+ switch (i) {
+ case 0:
+ ps = &m_primitives_10;
+ size = 10;
+ break;
+ case 1:
+ ps = &m_primitives_100;
+ size = 100;
+ break;
+ case 2:
+ ps = &m_primitives_1000;
+ size = 1000;
+ break;
+ }
+
+ ps->f_rect = QRectF(0, 0, size, size);
+ ps->f_line_diag = QLineF(0, 0, size, size);
+ ps->f_line_ver = QLineF(10, 0, 10, size);
+ ps->f_line_hor = QLineF(0, 10, size, 10);
+ ps->f_poly_rect = QPolygonF() << QPointF(0, 0)
+ << QPointF(size, 0)
+ << QPointF(size, size)
+ << QPointF(0, size);
+ ps->f_poly_2rects = QPolygonF() << QPointF(0, 0)
+ << QPointF(size * 0.75, 0)
+ << QPointF(size * 0.75, size * 0.75)
+ << QPointF(size * 0.25, size * 0.75)
+ << QPointF(size * 0.25, size * 0.25)
+ << QPointF(size, size * 0.25)
+ << QPointF(size, size)
+ << QPointF(0, size);
+ ps->f_poly_tri = QPolygonF() << QPointF(size / 2.0, 0)
+ << QPointF(0, size)
+ << QPointF(size, size);
+
+ ps->f_path_tri.addPolygon(ps->f_poly_tri);
+ ps->f_path_rect.addRect(ps->f_rect);
+ ps->f_path_2rects.addPolygon(ps->f_poly_2rects);
+ ps->f_path_ellipse.addEllipse(ps->f_rect);
+
+ ps->i_rect = ps->f_rect.toRect();
+ ps->i_line_diag = ps->f_line_diag.toLine();
+ ps->i_line_hor = ps->f_line_hor.toLine();
+ ps->i_line_ver = ps->f_line_ver.toLine();
+ ps->i_poly_tri = ps->f_poly_tri.toPolygon();
+ ps->i_poly_rect = ps->f_poly_rect.toPolygon();
+ ps->i_poly_2rects = ps->f_poly_2rects.toPolygon();
+ }
+}
+
+void tst_QPainter::drawLine_data()
+{
+ QTest::addColumn<QLine>("line");
+ QTest::addColumn<QPen>("pen");
+
+ QVector<QPen> pens;
+ pens << QPen(Qt::black)
+ << QPen(Qt::black, 0, Qt::DashDotLine)
+ << QPen(Qt::black, 4)
+ << QPen(Qt::black, 4, Qt::DashDotLine)
+ << QPen(QColor(255, 0, 0, 200))
+ << QPen(QColor(255, 0, 0, 200), 0, Qt::DashDotLine)
+ << QPen(QColor(255, 0, 0, 200), 4)
+ << QPen(QColor(255, 0, 0, 200), 4, Qt::DashDotLine);
+
+ QStringList penNames;
+ penNames << "black-0"
+ << "black-0-dashdot"
+ << "black-4"
+ << "black-4-dashdot"
+ << "alpha-0"
+ << "alpha-0-dashdot"
+ << "alpha-4"
+ << "alpha-4-dashdot";
+
+ int i = 0;
+ foreach (QPen pen, pens) {
+ const QString s = QString(QLatin1String("%1:%2")).arg(penNames[i]);
+ QTest::newRow(qPrintable(s.arg("horizontal")))
+ << QLine(0, 20, 100, 20) << pen;
+ QTest::newRow(qPrintable(s.arg("vertical:")))
+ << QLine(20, 0, 20, 100) << pen;
+ QTest::newRow(qPrintable(s.arg("0-45:")))
+ << QLine(0, 20, 100, 0) << pen;
+ QTest::newRow(qPrintable(s.arg("45-90:")))
+ << QLine(0, 100, 20, 0) << pen;
+ QTest::newRow(qPrintable(s.arg("90-135:")))
+ << QLine(20, 100, 0, 0) << pen;
+ QTest::newRow(qPrintable(s.arg("135-180:")))
+ << QLine(100, 20, 0, 0) << pen;
+ QTest::newRow(qPrintable(s.arg("180-225:")))
+ << QLine(100, 0, 0, 20) << pen;
+ QTest::newRow(qPrintable(s.arg("225-270:")))
+ << QLine(20, 0, 0, 100) << pen;
+ QTest::newRow(qPrintable(s.arg("270-315:")))
+ << QLine(0, 0, 20, 100) << pen;
+ QTest::newRow(qPrintable(s.arg("315-360:")))
+ << QLine(0, 0, 100, 20) << pen;
+ ++i;
+ }
+}
+
+void tst_QPainter::setupBrushes()
+{
+ // Solid brushes...
+ m_brushes["black-brush"] = QBrush(Qt::black);
+ m_brushes["white-brush"] = QBrush(Qt::white);
+ m_brushes["transparent-brush"] = QBrush(QColor(255, 255, 255, 0));
+ m_brushes["alpha1-brush"] = QBrush(QColor(255, 255, 255, 100));
+ m_brushes["alpha2-brush"] = QBrush(QColor(255, 255, 255, 200));
+
+
+ // Patterns
+ m_brushes["dense1-brush"] = QBrush(Qt::Dense1Pattern);
+ m_brushes["dense2-brush"] = QBrush(Qt::Dense2Pattern);
+ m_brushes["dense3-brush"] = QBrush(Qt::Dense3Pattern);
+ m_brushes["dense4-brush"] = QBrush(Qt::Dense4Pattern);
+ m_brushes["dense5-brush"] = QBrush(Qt::Dense5Pattern);
+ m_brushes["dense6-brush"] = QBrush(Qt::Dense6Pattern);
+ m_brushes["dense7-brush"] = QBrush(Qt::Dense7Pattern);
+ m_brushes["hor-brush"] = QBrush(Qt::HorPattern);
+ m_brushes["ver-brush"] = QBrush(Qt::VerPattern);
+ m_brushes["cross-brush"] = QBrush(Qt::CrossPattern);
+ m_brushes["bdiag-brush"] = QBrush(Qt::BDiagPattern);
+ m_brushes["fdiag-brush"] = QBrush(Qt::FDiagPattern);
+ m_brushes["diagcross-brush"] = QBrush(Qt::DiagCrossPattern);
+
+ // Gradients
+ QGradientStops gradient_white_black;
+ gradient_white_black << QPair<qreal, QColor>(0, QColor(Qt::white));
+ gradient_white_black << QPair<qreal, QColor>(1, QColor(Qt::black));
+
+ QGradientStops gradient_white_black10;
+ for (int i=0; i<10; ++i) {
+ gradient_white_black10 << QPair<qreal, QColor>(i/10.0, QColor(Qt::white));
+ gradient_white_black10 << QPair<qreal, QColor>(i/10.0+0.05, QColor(Qt::black));
+ }
+
+ QGradientStops gradient_white_alpha;
+ gradient_white_alpha << QPair<qreal, QColor>(0, QColor(Qt::white));
+ gradient_white_alpha << QPair<qreal, QColor>(0, QColor(Qt::transparent));
+
+ QGradientStops gradient_white_alpha10;
+ for (int i=0; i<10; ++i) {
+ gradient_white_alpha10 << QPair<qreal, QColor>(i/10.0, QColor(Qt::white));
+ gradient_white_alpha10 << QPair<qreal, QColor>(i/10.0+0.05, QColor(Qt::black));
+ }
+
+
+ for (int j=0; j<4; ++j) {
+ QLinearGradient lg;
+ lg.setStart(0, 0);
+
+ QRadialGradient rg;
+ QConicalGradient cg;
+
+ QGradientStops stops;
+ if (j == 0) stops = gradient_white_black;
+ else if (j == 1) stops = gradient_white_black10;
+ else if (j == 2) stops = gradient_white_alpha;
+ else if (j == 3) stops = gradient_white_alpha10;
+ lg.setStops(stops);
+ rg.setStops(stops);
+ cg.setStops(stops);
+
+ for (int i=0; i<6; ++i) {
+ lg.setSpread((QGradient::Spread) (i % 3));
+ lg.setCoordinateMode((QGradient::CoordinateMode) (j / 3));
+
+ QString name = QString::fromLatin1("-%1%2")
+ .arg(lg.spread())
+ .arg(lg.coordinateMode());
+
+ lg.setFinalStop(100, 0);
+ m_brushes["hor-lingrad-w/b-brush" + name] = QBrush(lg);
+
+ lg.setFinalStop(0, 100);
+ m_brushes["ver-lingrad-w/b-brush" + name] = QBrush(lg);
+
+ lg.setFinalStop(100, 100);
+ m_brushes["diag-lingrad-w/b-brush" + name] = QBrush(lg);
+
+ rg.setRadius(100);
+ rg.setCenter(0, 0);
+ rg.setFocalPoint(50, 50);
+ m_brushes["radgrad-brush" + name] = QBrush(rg);
+
+ cg.setCenter(0, 0);
+ cg.setAngle(40);
+ m_brushes["congrad-brush" + name] = QBrush(cg);
+ }
+ }
+
+ // Set up pens...
+
+
+// m_pens["black-pen"] = QPen(Qt::black);
+// m_pens["white-pen"] = QPen(Qt::white);
+// m_pens["transparent-pen"] = QPen(QColor(255, 255, 255, 0));
+// m_pens["translucent1-pen"] = QPen(QColor(255, 255, 255, 100));
+// m_pens["translucent2-pen"] = QPen(QColor(255, 255, 255, 200));
+
+
+
+}
+
+
+// void QPainter_Primitives::fillRect_data() {
+
+// QTest::addColumn<QBrush>("brush");
+// QTest::addColumn<QSize>("size");
+
+// for (QMap<QString, QBrush>::const_iterator it = m_brushes.constBegin();
+// it != m_brushes.constEnd(); ++it) {
+// for (int w=2; w<1025; w*=2) {
+// for (int h=2; h<1025; h*=2) {
+// QTest::newRow(QString("brush=%1; size=[%2,%3]").arg(it.key()).arg(w).arg(h).toAscii().data())
+// << *it << QSize(w, h);
+// }
+// }
+// }
+// }
+
+
+
+
+
+// void QPainter_Primitives::fillRect()
+// {
+// QFETCH(QBrush, brush);
+// QFETCH(QSize, size);
+
+// QImage img(1024, 1024, QImage::Format_ARGB32_Premultiplied);
+// QPainter p(&img);
+// p.setPen(Qt::NoPen);
+// p.setBrush(brush);
+// QRect rect(QPoint(0, 0), size);
+// QBENCHMARK {
+// p.drawRect(rect);
+// }
+// }
+
+
+
+
+void tst_QPainter::beginAndEnd()
+{
+ QPixmap pixmap = rasterPixmap(100, 100);
+
+ QBENCHMARK {
+ QPainter p;
+ p.begin(&pixmap);
+ p.end();
+ }
+}
+
+void tst_QPainter::drawLine()
+{
+ QFETCH(QLine, line);
+ QFETCH(QPen, pen);
+
+ const int offset = 5;
+ QPixmap pixmapUnclipped =
+ rasterPixmap(qMin(line.x1(), line.x2())
+ + 2*offset + qAbs(line.dx()),
+ qMin(line.y1(), line.y2())
+ + 2*offset + qAbs(line.dy()));
+ pixmapUnclipped.fill(Qt::white);
+
+ QPainter p(&pixmapUnclipped);
+ p.translate(offset, offset);
+ p.setPen(pen);
+ p.paintEngine()->syncState();
+
+ QBENCHMARK {
+ p.drawLine(line);
+ }
+
+ p.end();
+
+}
+
+void tst_QPainter::drawLine_clipped_data()
+{
+ drawLine_data();
+}
+
+void tst_QPainter::drawLine_clipped()
+{
+ QFETCH(QLine, line);
+ QFETCH(QPen, pen);
+
+ const int offset = 5;
+ QPixmap pixmapClipped
+ = rasterPixmap(qMin(line.x1(), line.x2())
+ + 2*offset + qAbs(line.dx()),
+ qMin(line.y1(), line.y2())
+ + 2*offset + qAbs(line.dy()));
+
+ const QRect clip = QRect(line.p1(), line.p2()).normalized();
+
+ pixmapClipped.fill(Qt::white);
+ QPainter p(&pixmapClipped);
+ p.translate(offset, offset);
+ p.setClipRect(clip);
+ p.setPen(pen);
+ p.paintEngine()->syncState();
+
+ QBENCHMARK {
+ p.drawLine(line);
+ }
+
+ p.end();
+}
+
+
+void tst_QPainter::drawLine_antialiased_clipped_data()
+{
+ drawLine_data();
+}
+
+
+void tst_QPainter::drawLine_antialiased_clipped()
+{
+ QFETCH(QLine, line);
+ QFETCH(QPen, pen);
+
+ const int offset = 5;
+ QPixmap pixmapClipped
+ = rasterPixmap(qMin(line.x1(), line.x2())
+ + 2*offset + qAbs(line.dx()),
+ qMin(line.y1(), line.y2())
+ + 2*offset + qAbs(line.dy()));
+
+ const QRect clip = QRect(line.p1(), line.p2()).normalized();
+
+ pixmapClipped.fill(Qt::white);
+ QPainter p(&pixmapClipped);
+ p.setRenderHint(QPainter::Antialiasing);
+ p.translate(offset, offset);
+ p.setClipRect(clip);
+ p.setPen(pen);
+ p.paintEngine()->syncState();
+
+ QBENCHMARK {
+ p.drawLine(line);
+ }
+
+ p.end();
+}
+
+void tst_QPainter::drawPixmap_data()
+{
+ QTest::addColumn<QImage::Format>("sourceFormat");
+ QTest::addColumn<QImage::Format>("targetFormat");
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<int>("type"); // 0 = circle, 1 = diag line, 2 = solid rect, 3 = alpharect
+
+ QList<QSize> sizes;
+ sizes << QSize(1, 1)
+ << QSize(10, 10)
+ << QSize(100, 100)
+ << QSize(1000, 1000);
+
+ const char *typeNames[] = {
+ "circle",
+ "line",
+ "solidrect",
+ "alpharect"
+ };
+
+ const char *formatNames[] = {
+ "Invalid",
+ "Mono",
+ "MonoLSB",
+ "Indexed8",
+ "RGB32",
+ "ARGB32",
+ "ARGB32_pm",
+ "RGB16",
+ "ARGB8565_pm",
+ "RGB666",
+ "ARGB6666_pm",
+ "RGB555",
+ "ARGB8555_pm",
+ "RGB888",
+ "RGB444",
+ "ARGB4444_pm"
+ };
+
+ for (int tar=4; tar<QImage::NImageFormats; ++tar) {
+ for (int src=4; src<QImage::NImageFormats; ++src) {
+
+ // skip the low-priority formats to keep resultset manageable...
+ if (tar == QImage::Format_RGB444 || src == QImage::Format_RGB444
+ || tar == QImage::Format_RGB555 || src == QImage::Format_RGB555
+ || tar == QImage::Format_RGB666 || src == QImage::Format_RGB666
+ || tar == QImage::Format_RGB888 || src == QImage::Format_RGB888
+ || tar == QImage::Format_ARGB4444_Premultiplied
+ || src == QImage::Format_ARGB4444_Premultiplied
+ || tar == QImage::Format_ARGB6666_Premultiplied
+ || src == QImage::Format_ARGB6666_Premultiplied)
+ continue;
+
+ foreach (const QSize &s, sizes) {
+ for (int type=0; type<=3; ++type) {
+ QString name = QString::fromLatin1("%1 on %2, (%3x%4), %5")
+ .arg(formatNames[src])
+ .arg(formatNames[tar])
+ .arg(s.width()).arg(s.height())
+ .arg(typeNames[type]);
+ QTest::newRow(name.toLatin1()) << (QImage::Format) src
+ << (QImage::Format) tar
+ << s
+ << type;
+ }
+ }
+ }
+ }
+}
+
+static QImage createImage(int type, const QSize &size) {
+ QImage base(size, QImage::Format_ARGB32_Premultiplied);
+ base.fill(0);
+ QPainter p(&base);
+ p.setRenderHint(QPainter::Antialiasing);
+ switch (type) {
+ case 0: // ellipse
+ p.setBrush(Qt::red);
+ p.drawEllipse(0, 0, size.width(), size.height());
+ break;
+ case 1: // line
+ p.drawLine(0, 0, size.width(), size.height());
+ break;
+ case 2:
+ p.fillRect(0, 0, size.width(), size.height(), Qt::red);
+ break;
+ case 3:
+ p.fillRect(0, 0, size.width(), size.height(), QColor(0, 255, 0, 127));
+ break;
+ }
+ p.end();
+ return base;
+}
+
+
+void tst_QPainter::drawPixmap()
+{
+ QFETCH(QImage::Format, sourceFormat);
+ QFETCH(QImage::Format, targetFormat);
+ QFETCH(QSize, size);
+ QFETCH(int, type);
+
+ QImage sourceImage = createImage(type, size).convertToFormat(sourceFormat);
+ QImage targetImage(size, targetFormat);
+
+ QPixmap sourcePixmap = rasterPixmap(sourceImage);
+ QPixmap targetPixmap = rasterPixmap(targetImage);
+
+ QPainter p(&targetPixmap);
+
+ QBENCHMARK {
+ p.drawPixmap(0, 0, sourcePixmap);
+ }
+}
+
+void tst_QPainter::drawImage_data()
+{
+ drawPixmap_data();
+}
+
+
+void tst_QPainter::drawImage()
+{
+ QFETCH(QImage::Format, sourceFormat);
+ QFETCH(QImage::Format, targetFormat);
+ QFETCH(QSize, size);
+ QFETCH(int, type);
+
+ QImage sourceImage = createImage(type, size).convertToFormat(sourceFormat);
+ QImage targetImage(size, targetFormat);
+
+ QPainter p(&targetImage);
+ QBENCHMARK {
+ p.drawImage(0, 0, sourceImage);
+ }
+}
+
+
+void tst_QPainter::compositionModes_data()
+{
+ QTest::addColumn<QPainter::CompositionMode>("mode");
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QColor>("color");
+
+ const int n = QPainter::RasterOp_SourceAndNotDestination;
+ for (int i = 0; i <= n; ++i) {
+ QString title("%1:%2");
+ QTest::newRow(qPrintable(title.arg(i).arg("10x10:opaque")))
+ << (QPainter::CompositionMode)(i)
+ << QSize(10, 10) << QColor(255, 0, 0);
+ QTest::newRow(qPrintable(title.arg(i).arg("10x10:!opaque")))
+ << (QPainter::CompositionMode)(i)
+ << QSize(10, 10) << QColor(127, 127, 127, 127);
+ QTest::newRow(qPrintable(title.arg(i).arg("300x300:opaque")))
+ << (QPainter::CompositionMode)(i)
+ << QSize(300, 300) << QColor(255, 0, 0);
+ QTest::newRow(qPrintable(title.arg(i).arg("300x300:!opaque")))
+ << (QPainter::CompositionMode)(i)
+ << QSize(300, 300) << QColor(127, 127, 127, 127);
+ }
+}
+
+void tst_QPainter::compositionModes()
+{
+ QFETCH(QPainter::CompositionMode, mode);
+ QFETCH(QSize, size);
+ QFETCH(QColor, color);
+
+ QPixmap src = rasterPixmap(size);
+ src.fill(color);
+
+ QPixmap dest = rasterPixmap(size);
+ if (mode < QPainter::RasterOp_SourceOrDestination)
+ color.setAlpha(127); // porter-duff needs an alpha channel
+ dest.fill(color);
+
+ QPainter p(&dest);
+ p.setCompositionMode(mode);
+
+ QBENCHMARK {
+ p.drawPixmap(0, 0, src);
+ }
+}
+
+void tst_QPainter::drawTiledPixmap_data()
+{
+ QTest::addColumn<QSize>("srcSize");
+ QTest::addColumn<QSize>("dstSize");
+ QTest::addColumn<QTransform>("transform");
+ QTest::addColumn<QColor>("color");
+ QTest::addColumn<QPainter::RenderHint>("renderHint");
+
+ QTest::newRow("10x10=>20x20")
+ << QSize(10, 10) << QSize(20, 20) << (QTransform())
+ << QColor(Qt::black) << QPainter::RenderHint(0);
+ QTest::newRow("10x10=>20x20, smooth")
+ << QSize(10, 10) << QSize(20, 20) << (QTransform())
+ << QColor(Qt::black) << QPainter::SmoothPixmapTransform;
+ QTest::newRow("10x10=>20x20, !opaque")
+ << QSize(10, 10) << QSize(20, 20) << (QTransform())
+ << QColor(127, 127, 127, 127) << QPainter::RenderHint(0);
+ QTest::newRow("10x10=>20x20, !opaque, smooth")
+ << QSize(10, 10) << QSize(20, 20) << (QTransform())
+ << QColor(127, 127, 127, 127) << QPainter::SmoothPixmapTransform;
+
+ QTest::newRow("10x10=>20x20, rotate(30)")
+ << QSize(10, 10) << QSize(20, 20) << (QTransform().rotate(30))
+ << QColor(Qt::black) << QPainter::RenderHint(0);
+ QTest::newRow("10x10=>20x20, rotate(30), smooth")
+ << QSize(10, 10) << QSize(20, 20) << (QTransform().rotate(30))
+ << QColor(Qt::black) << QPainter::SmoothPixmapTransform;
+ QTest::newRow("10x10=>20x20, rotate(30), !opaque")
+ << QSize(10, 10) << QSize(20, 20) << (QTransform().rotate(30))
+ << QColor(127, 127, 127, 127) << QPainter::RenderHint(0);
+ QTest::newRow("10x10=>20x20, rotate(30), !opaque, smooth")
+ << QSize(10, 10) << QSize(20, 20) << (QTransform().rotate(30))
+ << QColor(127, 127, 127, 127) << QPainter::SmoothPixmapTransform;
+
+ QTest::newRow("100x100=>200x200")
+ << QSize(100, 100) << QSize(200, 200) << (QTransform())
+ << QColor(Qt::black) << QPainter::RenderHint(0);
+ QTest::newRow("100x100=>200x200, smooth")
+ << QSize(100, 100) << QSize(200, 200) << (QTransform())
+ << QColor(Qt::black) << QPainter::SmoothPixmapTransform;
+ QTest::newRow("100x100=>200x200, !opaque")
+ << QSize(100, 100) << QSize(200, 200) << (QTransform())
+ << QColor(127, 127, 127, 127) << QPainter::RenderHint(0);
+ QTest::newRow("100x100=>200x200, !opaque, smooth")
+ << QSize(100, 100) << QSize(200, 200) << (QTransform())
+ << QColor(127, 127, 127, 127) << QPainter::SmoothPixmapTransform;
+
+ QTest::newRow("100x100=>200x200, rotate(30)")
+ << QSize(100, 100) << QSize(200, 200) << (QTransform().rotate(30))
+ << QColor(Qt::black) << QPainter::RenderHint(0);
+ QTest::newRow("100x100=>200x200, rotate(30), smooth")
+ << QSize(100, 100) << QSize(200, 200) << (QTransform().rotate(30))
+ << QColor(Qt::black) << QPainter::SmoothPixmapTransform;
+ QTest::newRow("100x100=>200x200, rotate(30), !opaque")
+ << QSize(100, 100) << QSize(200, 200) << (QTransform().rotate(30))
+ << QColor(127, 127, 127, 127) << QPainter::RenderHint(0);
+ QTest::newRow("100x100=>200x200, rotate(30), !opaque, smooth")
+ << QSize(100, 100) << QSize(200, 200) << (QTransform().rotate(30))
+ << QColor(127, 127, 127, 127) << QPainter::SmoothPixmapTransform;
+}
+
+void tst_QPainter::drawTiledPixmap()
+{
+ QFETCH(QSize, srcSize);
+ QFETCH(QSize, dstSize);
+ QFETCH(QTransform, transform);
+ QFETCH(QColor, color);
+ QFETCH(QPainter::RenderHint, renderHint);
+
+ QPixmap src = rasterPixmap(srcSize);
+ src.fill(color);
+
+ const QRect dstRect = transform.mapRect(QRect(QPoint(), dstSize));
+ QPixmap dst = rasterPixmap(dstRect.right() + 5, dstRect.bottom() + 5);
+ QPainter p(&dst);
+ p.setTransform(transform);
+ p.setRenderHint(renderHint);
+
+ QBENCHMARK {
+ p.drawTiledPixmap(QRect(QPoint(), dstSize), src);
+ }
+}
+
+void tst_QPainter::fillPrimitives_helper(QPainter *p, PrimitiveType type, PrimitiveSet *s)
+{
+ p->paintEngine()->syncState();
+
+ switch (type) {
+ case Primitive_Int_DiagLine: QBENCHMARK { p->drawLine(s->i_line_diag); } break;
+ case Primitive_Int_VerLine: QBENCHMARK { p->drawLine(s->i_line_ver); } break;
+ case Primitive_Int_HorLine: QBENCHMARK { p->drawLine(s->i_line_hor); } break;
+ case Primitive_Int_Rect: QBENCHMARK { p->drawRect(s->i_rect); } break;
+ case Primitive_Int_Ellipse: QBENCHMARK { p->drawEllipse(s->i_rect); } break;
+ case Primitive_Int_Pie: QBENCHMARK { p->drawPie(s->i_rect, 45*16, 270*16); } break;
+ case Primitive_Int_Arc: QBENCHMARK { p->drawArc(s->i_rect, 45*16, 270*16); } break;
+ case Primitive_Int_Chord: QBENCHMARK { p->drawChord(s->i_rect, 45*16, 270*16); } break;
+ case Primitive_Int_TriPoly: QBENCHMARK { p->drawPolygon(s->i_poly_tri); } break;
+ case Primitive_Int_RectPoly: QBENCHMARK { p->drawPolygon(s->i_poly_rect); } break;
+ case Primitive_Int_2RectPoly: QBENCHMARK { p->drawPolygon(s->i_poly_2rects); } break;
+
+ case Primitive_Float_DiagLine: QBENCHMARK { p->drawLine(s->f_line_diag); } break;
+ case Primitive_Float_VerLine: QBENCHMARK { p->drawLine(s->f_line_ver); } break;
+ case Primitive_Float_HorLine: QBENCHMARK { p->drawLine(s->f_line_hor); } break;
+ case Primitive_Float_Rect: QBENCHMARK { p->drawRect(s->f_rect); } break;
+ case Primitive_Float_Ellipse: QBENCHMARK { p->drawEllipse(s->f_rect); } break;
+ case Primitive_Float_Pie: QBENCHMARK { p->drawPie(s->f_rect, 45*16, 270*16); } break;
+ case Primitive_Float_Arc: QBENCHMARK { p->drawArc(s->f_rect, 45*16, 270*16); } break;
+ case Primitive_Float_Chord: QBENCHMARK { p->drawChord(s->f_rect, 45*16, 270*16); } break;
+ case Primitive_Float_TriPoly: QBENCHMARK { p->drawPolygon(s->f_poly_tri); } break;
+ case Primitive_Float_RectPoly: QBENCHMARK { p->drawPolygon(s->f_poly_rect); } break;
+ case Primitive_Float_2RectPoly: QBENCHMARK { p->drawPolygon(s->f_poly_2rects); } break;
+
+ case Primitive_Float_TriPath: QBENCHMARK { p->drawPath(s->f_path_tri); } break;
+ case Primitive_Float_RectPath: QBENCHMARK { p->drawPath(s->f_path_rect); } break;
+ case Primitive_Float_2RectPath: QBENCHMARK { p->drawPath(s->f_path_2rects); } break;
+ case Primitive_Float_EllipsePath: QBENCHMARK { p->drawPath(s->f_path_ellipse); } break;
+ }
+}
+
+void tst_QPainter::drawPrimitives_data_helper(bool fancypens)
+{
+ QTest::addColumn<int>("type");
+ QTest::addColumn<bool>("aa");
+ QTest::addColumn<bool>("dash");
+ QTest::addColumn<int>("width");
+
+ const char * const names[] = {
+ "IDLine",
+ "IVLine",
+ "IHLine",
+ "IRect",
+ "IElli",
+ "IPie",
+ "IArc",
+ "IChord",
+ "ITriPol",
+ "IRectPol",
+ "I2RectPol",
+ "FDLine",
+ "FVLine",
+ "FHLine",
+ "FRect",
+ "FElli",
+ "FPie",
+ "FArc",
+ "FChord",
+ "FTriPol",
+ "FRectPol",
+ "F2RectPol",
+ "FTriPa",
+ "FRectPa",
+ "F2RectPa",
+ "FElliPa"
+ };
+
+ if (fancypens) {
+ for (int dash=0; dash<2; ++dash) {
+ for (int width=0; width<=4; width+=4) {
+ for (int aa=0; aa<2; ++aa) {
+ for (int type=0; type<Primitive_Last_Primitive; ++type) {
+ QString name = QString::fromLatin1(names[type]);
+
+ if (aa) name += " aa";
+ if (dash) name += " dotted";
+ if (width) name += QString::fromLatin1(" width=%1").arg(width);
+
+ QTest::newRow(name.toLatin1()) << type << (bool) aa << (bool) dash << width;
+ }
+ }
+ }
+ }
+ } else {
+ for (int aa=0; aa<2; ++aa) {
+ for (int type=0; type<Primitive_Last_Primitive; ++type) {
+ QString name = QString::fromLatin1(names[type]);
+ if (aa) name += " aa";
+ QTest::newRow(name.toLatin1()) << type << (bool) aa;
+ }
+ }
+ }
+}
+
+
+void tst_QPainter::fillPrimitives_10()
+{
+ QFETCH(int, type);
+ QFETCH(bool, aa);
+ QPainter p(m_surface);
+ p.setPen(Qt::NoPen);
+ p.setBrush(Qt::red);
+ p.setRenderHint(QPainter::Antialiasing, aa);
+ fillPrimitives_helper(&p, (PrimitiveType) type, &m_primitives_10);
+}
+
+
+void tst_QPainter::fillPrimitives_100()
+{
+ QFETCH(int, type);
+ QFETCH(bool, aa);
+ QPainter p(m_surface);
+ p.setPen(Qt::NoPen);
+ p.setBrush(Qt::red);
+ p.setRenderHint(QPainter::Antialiasing, aa);
+ fillPrimitives_helper(&p, (PrimitiveType) type, &m_primitives_100);
+}
+
+
+void tst_QPainter::fillPrimitives_1000()
+{
+ QFETCH(int, type);
+ QFETCH(bool, aa);
+ QPainter p(m_surface);
+ p.setPen(Qt::NoPen);
+ p.setBrush(Qt::red);
+ p.setRenderHint(QPainter::Antialiasing, aa);
+ fillPrimitives_helper(&p, (PrimitiveType) type, &m_primitives_1000);
+}
+
+void tst_QPainter::strokePrimitives_10()
+{
+ QFETCH(int, type);
+ QFETCH(bool, aa);
+ QFETCH(bool, dash);
+ QFETCH(int, width);
+ QPainter p(m_surface);
+ p.setPen(QPen(Qt::red, width, dash ? Qt::DashLine : Qt::SolidLine));
+ p.setBrush(Qt::NoBrush);
+ p.setRenderHint(QPainter::Antialiasing, aa);
+ fillPrimitives_helper(&p, (PrimitiveType) type, &m_primitives_10);
+}
+
+void tst_QPainter::strokePrimitives_100()
+{
+ QFETCH(int, type);
+ QFETCH(bool, aa);
+ QFETCH(bool, dash);
+ QFETCH(int, width);
+ QPainter p(m_surface);
+ p.setPen(QPen(Qt::red, width, dash ? Qt::DashLine : Qt::SolidLine));
+ p.setBrush(Qt::NoBrush);
+ p.setRenderHint(QPainter::Antialiasing, aa);
+ fillPrimitives_helper(&p, (PrimitiveType) type, &m_primitives_100);
+}
+
+void tst_QPainter::strokePrimitives_1000()
+{
+ QFETCH(int, type);
+ QFETCH(bool, aa);
+ QFETCH(bool, dash);
+ QFETCH(int, width);
+ QPainter p(m_surface);
+ p.setPen(QPen(Qt::red, width, dash ? Qt::DashLine : Qt::SolidLine));
+ p.setBrush(Qt::NoBrush);
+ p.setRenderHint(QPainter::Antialiasing, aa);
+ fillPrimitives_helper(&p, (PrimitiveType) type, &m_primitives_1000);
+}
+
+void tst_QPainter::drawText_data()
+{
+ QTest::addColumn<QString>("text");
+
+ QTest::newRow("a") << QString::fromLatin1("a");
+ QTest::newRow("ab") << QString::fromLatin1("ab");
+ QTest::newRow("abc") << QString::fromLatin1("abc");
+ QTest::newRow("abcd") << QString::fromLatin1("abcd");
+ QTest::newRow("abcde") << QString::fromLatin1("abcde");
+ QTest::newRow("abcdef") << QString::fromLatin1("abcdef");
+ QTest::newRow("abcdefg") << QString::fromLatin1("abcdefg");
+}
+
+void tst_QPainter::drawText()
+{
+ QFETCH(QString, text);
+
+ QPainter p(m_surface);
+
+ QBENCHMARK {
+ p.drawText(QPointF(5, 5), text);
+ }
+}
+
+void tst_QPainter::saveRestore_data()
+{
+ QTest::addColumn<int>("change");
+
+ for (int i=0; i<16; ++i) {
+ QString change = "change=";
+ if (i == 0) change += " none";
+ if (i & ChangePen) change += " pen";
+ if (i & ChangeBrush) change += " brush";
+ if (i & ChangeClip) change += " clip";
+ if (i & ChangeTransform) change += " xform";
+
+ QTest::newRow(change.toLatin1()) << i;
+ }
+}
+
+void tst_QPainter::saveRestore()
+{
+ QFETCH(int, change);
+
+ QPen pen(Qt::blue);
+ QBrush brush(Qt::green);
+ QRect r(100, 100, 100, 20);
+
+ QPainter p(m_surface);
+
+ p.setPen(Qt::NoPen);
+ p.setBrush(Qt::NoBrush);
+
+ QBENCHMARK {
+ p.save();
+ if (change & ChangePen) { p.setPen(pen); p.setPen(Qt::NoPen); }
+ if (change & ChangeBrush) { p.setBrush(brush); p.setBrush(Qt::NoBrush); }
+ if (change & ChangeClip) p.setClipRect(r);
+ if (change & ChangeTransform) { p.scale(3, 5); p.scale(1/3.0, 1/5.0); }
+ p.drawRect(0, 0, 1, 1);
+ p.restore();
+ };
+}
+
+enum ClipType {
+ RectClipType,
+ RectPathClipType,
+ RectRegionClipType,
+ RegionClipType,
+ PathClipType
+};
+
+void tst_QPainter::clipAndFill_data()
+{
+ QTest::addColumn<int>("type");
+
+ QTest::newRow("rect") << (int) RectClipType;
+ QTest::newRow("rectpath") << (int) RectPathClipType;
+ QTest::newRow("rectregion") << (int) RectRegionClipType;
+ QTest::newRow("ellipseRegion") << (int) RegionClipType;
+ QTest::newRow("ellipsePath") << (int) PathClipType;
+}
+
+
+void tst_QPainter::clipAndFill()
+{
+ QFETCH(int, type);
+
+ QRegion region;
+ QPainterPath path;
+ QRectF rect;
+
+ switch (type) {
+ case RectClipType:
+ rect = QRectF(100, 100, 100, 100);
+ break;
+ case RectPathClipType:
+ path.addRect(100, 100, 100, 100);
+ break;
+ case RectRegionClipType:
+ region = QRegion(100, 100, 100, 100);
+ break;
+ case RegionClipType:
+ region = QRegion(100, 100, 100, 100, QRegion::Ellipse);
+ break;
+ case PathClipType:
+ path.addEllipse(100, 100, 100, 100);
+ break;
+ }
+
+ QPainter p(m_surface);
+
+ p.setPen(Qt::NoPen);
+ p.setBrush(Qt::red);
+
+ QBENCHMARK {
+ if (type == RectClipType)
+ p.setClipRect(rect);
+ else if (type == RectPathClipType || type == PathClipType)
+ p.setClipPath(path);
+ else
+ p.setClipRegion(region);
+ p.drawRect(110, 110, 10, 10);
+ }
+}
+
+QTransform tst_QPainter::transformForAngle(qreal angle)
+{
+ const qreal inv_dist_to_plane = 1. / 1024.;
+
+ QTransform transform;
+
+ QTransform rotTrans;
+ rotTrans.translate(-40, 0);
+ QTransform rotTrans2;
+ rotTrans2.translate(40, 0);
+
+ qreal rad = angle * 2. * M_PI / 360.;
+ qreal c = ::cos(rad);
+ qreal s = ::sin(rad);
+
+ qreal x = 0;
+ qreal y = 80;
+ qreal z = 0;
+
+ qreal len = x * x + y * y + z * z;
+ if (len != 1.) {
+ len = ::sqrt(len);
+ x /= len;
+ y /= len;
+ z /= len;
+ }
+
+ QTransform rot(x*x*(1-c)+c, x*y*(1-c)-z*s, x*z*(1-c)+y*s*inv_dist_to_plane,
+ y*x*(1-c)+z*s, y*y*(1-c)+c, y*z*(1-c)-x*s*inv_dist_to_plane,
+ 0, 0, 1);
+
+ transform *= rotTrans;
+ transform *= rot;
+ transform *= rotTrans2;
+
+ return transform;
+}
+
+void tst_QPainter::drawRoundedRect()
+{
+ QImage surface(100, 100, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ p.setPen(QPen(Qt::black, 1));
+ p.setBrush(Qt::red);
+
+ QBENCHMARK {
+ p.drawRoundedRect(QRectF(.5, .5, 80, 80), 10, 10);
+ }
+}
+
+void tst_QPainter::drawScaledRoundedRect()
+{
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ p.setPen(QPen(Qt::black, 1));
+ p.setBrush(Qt::red);
+ p.scale(3, 3);
+
+ QBENCHMARK {
+ p.drawRoundedRect(10, 10, 80, 80, 10, 10);
+ }
+}
+
+void tst_QPainter::drawTransformedRoundedRect()
+{
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ p.setPen(QPen(Qt::black, 1));
+ p.setBrush(Qt::red);
+
+ QBENCHMARK {
+ p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953));
+ p.drawRoundedRect(100, 100, 80, 80, 10, 10);
+ }
+}
+
+void tst_QPainter::drawAntialiasedRoundedRect()
+{
+ QImage surface(100, 100, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.setPen(QPen(Qt::black, 1));
+ p.setBrush(Qt::red);
+
+ QBENCHMARK {
+ p.drawRoundedRect(QRectF(.5, .5, 80, 80), 10, 10);
+ }
+}
+
+void tst_QPainter::drawScaledAntialiasedRoundedRect_data()
+{
+ QTest::addColumn<float>("scale");
+
+ for (float i = 0; i < 3; i += .1)
+ QTest::newRow(QString(QLatin1String("scale=%1")).arg(i).toLatin1()) << i;
+}
+
+void tst_QPainter::drawScaledAntialiasedRoundedRect()
+{
+ QFETCH(float, scale);
+
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.setPen(QPen(Qt::black, 1));
+ p.setBrush(Qt::red);
+ p.scale(scale, scale);
+
+ QBENCHMARK {
+ p.drawRoundedRect(10, 10, 80, 80, 10, 10);
+ }
+}
+
+void tst_QPainter::drawTransformedAntialiasedRoundedRect_data()
+{
+ QTest::addColumn<QTransform>("transform");
+
+ for (float angle = 0; angle < 360; angle += 10)
+ QTest::newRow(QString(QLatin1String("angle=%1")).arg(angle).toLatin1()) << transformForAngle(angle);
+}
+
+void tst_QPainter::drawTransformedAntialiasedRoundedRect()
+{
+ QFETCH(QTransform, transform);
+
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.setPen(QPen(Qt::black, 1));
+ p.setBrush(Qt::red);
+
+ QBENCHMARK {
+ p.setWorldTransform(transform);
+ p.drawRoundedRect(100, 100, 80, 80, 10, 10);
+ }
+}
+
+void tst_QPainter::drawImageRoundedRect()
+{
+ //setup image
+ const int radius = 10;
+ QImage rectImage(81, 81, QImage::Format_ARGB32_Premultiplied);
+ rectImage.fill(0);
+ QPainter rp(&rectImage);
+ rp.setRenderHint(QPainter::Antialiasing);
+ rp.setPen(Qt::black);
+ rp.setBrush(Qt::red);
+ rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius);
+
+ //setup surface
+ QImage surface(100, 100, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ QBENCHMARK {
+ p.drawImage(0,0, rectImage);
+ }
+}
+
+void tst_QPainter::drawScaledImageRoundedRect_data()
+{
+ QTest::addColumn<int>("imageType");
+
+ QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied;
+}
+
+void tst_QPainter::drawScaledImageRoundedRect()
+{
+ QFETCH(int, imageType);
+
+ //setup image
+ const int radius = 10;
+ QImage rectImage(81, 81, (QImage::Format)imageType);
+ rectImage.fill(0);
+ QPainter rp(&rectImage);
+ rp.setRenderHint(QPainter::Antialiasing);
+ rp.setPen(Qt::black);
+ rp.setBrush(Qt::red);
+ rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius);
+
+ //setup surface
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+ p.scale(3, 3);
+
+ QBENCHMARK {
+ p.drawImage(0,0, rectImage);
+ }
+}
+
+void tst_QPainter::drawTransformedImageRoundedRect_data()
+{
+ QTest::addColumn<int>("imageType");
+
+ QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied;
+}
+
+void tst_QPainter::drawTransformedImageRoundedRect()
+{
+ QFETCH(int, imageType);
+
+ //setup image
+ const int radius = 10;
+ QImage rectImage(81, 81, (QImage::Format)imageType);
+ rectImage.fill(0);
+ QPainter rp(&rectImage);
+ rp.setRenderHint(QPainter::Antialiasing);
+ rp.setPen(Qt::black);
+ rp.setBrush(Qt::red);
+ rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius);
+
+ //setup surface
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ QBENCHMARK {
+ p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953));
+ p.drawImage(100,100, rectImage);
+ }
+}
+
+//code from QDeclarativeRectangle for drawing rounded rects
+void tst_QPainter::drawBorderPixmapRoundedRect()
+{
+ //setup image
+ const int pw = 1;
+ const int radius = 10;
+ QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, QImage::Format_ARGB32_Premultiplied);
+ rectImage.fill(0);
+ QPainter rp(&rectImage);
+ rp.setRenderHint(QPainter::Antialiasing);
+ rp.setPen(Qt::black);
+ rp.setBrush(Qt::red);
+ if (pw%2)
+ rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius);
+ else
+ rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius);
+ QPixmap rectPixmap = rasterPixmap(rectImage);
+
+ //setup surface
+ QImage surface(100, 100, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ QBENCHMARK {
+ const int pw = 2;
+ int width = 80;
+ int height = 80;
+
+ int xOffset = (rectPixmap.width()-1)/2;
+ int yOffset = (rectPixmap.height()-1)/2;
+ Q_ASSERT(rectPixmap.width() == 2*xOffset + 1);
+ Q_ASSERT(rectPixmap.height() == 2*yOffset + 1);
+
+ QMargins margins(xOffset, yOffset, xOffset, yOffset);
+ QTileRules rules(Qt::StretchTile, Qt::StretchTile);
+ //NOTE: even though our item may have qreal-based width and height, qDrawBorderPixmap only supports QRects
+ qDrawBorderPixmap(&p, QRect(-pw/2, -pw/2, width+pw, height+pw), margins, rectPixmap, rectPixmap.rect(), margins, rules);
+ }
+}
+
+void tst_QPainter::drawScaledBorderPixmapRoundedRect_data()
+{
+ QTest::addColumn<float>("scale");
+ QTest::addColumn<int>("imageType");
+
+ for (float i = 0; i < 3; i += .1)
+ QTest::newRow(QString(QLatin1String("scale=%1; imagetype=ARGB32_Pre")).arg(i).toLatin1()) << i << (int)QImage::Format_ARGB32_Premultiplied;
+ //for (float i = 0; i < 3; i += .1)
+ // QTest::newRow(QString(QLatin1String("scale=%1; imagetype=ARGB8565_Pre")).arg(i).toLatin1()) << i << (int)QImage::Format_ARGB8565_Premultiplied;
+}
+
+//code from QDeclarativeRectangle for drawing rounded rects
+void tst_QPainter::drawScaledBorderPixmapRoundedRect()
+{
+ QFETCH(float, scale);
+ QFETCH(int, imageType);
+
+ //setup image
+ const int pw = 1;
+ const int radius = 10;
+ QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, (QImage::Format)imageType);
+ rectImage.fill(0);
+ QPainter rp(&rectImage);
+ rp.setRenderHint(QPainter::Antialiasing);
+ rp.setPen(Qt::black);
+ rp.setBrush(Qt::red);
+ if (pw%2)
+ rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius);
+ else
+ rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius);
+
+ QPixmap rectPixmap = rasterPixmap(rectImage);
+
+ //setup surface
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+ p.scale(scale, scale);
+
+ QBENCHMARK {
+ const int pw = 2;
+ int width = 80;
+ int height = 80;
+
+ int xOffset = (rectPixmap.width()-1)/2;
+ int yOffset = (rectPixmap.height()-1)/2;
+ Q_ASSERT(rectPixmap.width() == 2*xOffset + 1);
+ Q_ASSERT(rectPixmap.height() == 2*yOffset + 1);
+
+ QMargins margins(xOffset, yOffset, xOffset, yOffset);
+ QTileRules rules(Qt::StretchTile, Qt::StretchTile);
+ qDrawBorderPixmap(&p, QRect(-pw/2, -pw/2, width+pw, height+pw), margins, rectPixmap, rectPixmap.rect(), margins, rules);
+ }
+}
+
+void tst_QPainter::drawTransformedBorderPixmapRoundedRect_data()
+{
+ QTest::addColumn<QTransform>("transform");
+ QTest::addColumn<int>("imageType");
+
+ for (float angle = 0; angle < 360; angle += 10)
+ QTest::newRow(QString(QLatin1String("angle=%1; imagetype=ARGB32_Pre")).arg(angle).toLatin1()) << transformForAngle(angle) << (int)QImage::Format_ARGB32_Premultiplied;
+ //for (float angle = 0; angle < 360; angle += 10)
+ // QTest::newRow(QString(QLatin1String("angle=%1; imagetype=ARGB8565_Pre")).arg(angle).toLatin1()) << transformForAngle(angle) << (int)QImage::Format_ARGB8565_Premultiplied;
+
+}
+
+//code from QDeclarativeRectangle for drawing rounded rects
+void tst_QPainter::drawTransformedBorderPixmapRoundedRect()
+{
+ QFETCH(QTransform, transform);
+ QFETCH(int, imageType);
+
+ //setup image
+ const int pw = 1;
+ const int radius = 10;
+ QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, (QImage::Format)imageType);
+ rectImage.fill(0);
+ QPainter rp(&rectImage);
+ rp.setRenderHint(QPainter::Antialiasing);
+ rp.setPen(Qt::black);
+ rp.setBrush(Qt::red);
+ if (pw%2)
+ rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius);
+ else
+ rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius);
+
+ QPixmap rectPixmap = rasterPixmap(rectImage);
+
+ //setup surface
+ QImage surface(400, 400, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ QBENCHMARK {
+ p.setWorldTransform(transform);
+ const int pw = 2;
+ int width = 80;
+ int height = 80;
+
+ int xOffset = (rectPixmap.width()-1)/2;
+ int yOffset = (rectPixmap.height()-1)/2;
+ Q_ASSERT(rectPixmap.width() == 2*xOffset + 1);
+ Q_ASSERT(rectPixmap.height() == 2*yOffset + 1);
+
+ QMargins margins(xOffset, yOffset, xOffset, yOffset);
+ QTileRules rules(Qt::StretchTile, Qt::StretchTile);
+ qDrawBorderPixmap(&p, QRect(-pw/2, -pw/2, width+pw, height+pw), margins, rectPixmap, rectPixmap.rect(), margins, rules);
+ }
+}
+
+void tst_QPainter::drawTransformedTransparentImage_data()
+{
+ QTest::addColumn<int>("imageType");
+
+ QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied;
+}
+
+void tst_QPainter::drawTransformedTransparentImage()
+{
+ QFETCH(int, imageType);
+
+ //setup image
+ QImage transImage(200, 200, (QImage::Format)imageType);
+ transImage.fill(0);
+
+ //setup surface
+ QImage surface(200, 200, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ QBENCHMARK {
+ p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953));
+ p.drawImage(0,0, transImage);
+ }
+}
+
+void tst_QPainter::drawTransformedSemiTransparentImage_data()
+{
+ QTest::addColumn<int>("imageType");
+
+ QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied;
+}
+
+void tst_QPainter::drawTransformedSemiTransparentImage()
+{
+ QFETCH(int, imageType);
+
+ //setup image
+ QImage transImage(200, 200, (QImage::Format)imageType);
+ transImage.fill(QColor(0,0,0, 128).rgba());
+
+ //setup surface
+ QImage surface(200, 200, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ QBENCHMARK {
+ p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953));
+ p.drawImage(0,0, transImage);
+ }
+}
+
+void tst_QPainter::drawTransformedFilledImage_data()
+{
+ QTest::addColumn<int>("imageType");
+
+ QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied;
+ QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied;
+}
+
+void tst_QPainter::drawTransformedFilledImage()
+{
+ QFETCH(int, imageType);
+
+ //setup image
+ QImage filledImage(200, 200, (QImage::Format)imageType);
+ filledImage.fill(QColor(0,0,0).rgb());
+
+ //setup surface
+ QImage surface(200, 200, QImage::Format_RGB16);
+ surface.fill(QColor(255,255,255).rgb());
+ QPainter p(&surface);
+
+ QBENCHMARK {
+ p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953));
+ p.drawImage(0,0, filledImage);
+ }
+}
+
+
+QTEST_MAIN(tst_QPainter)
+
+#include "tst_qpainter.moc"
diff --git a/tests/benchmarks/gui/painting/qregion/main.cpp b/tests/benchmarks/gui/painting/qregion/main.cpp
new file mode 100644
index 0000000000..31347bbccc
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qregion/main.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+// This file contains benchmarks for QRegion functions.
+
+#include <QDebug>
+#include <qtest.h>
+
+class tst_qregion : public QObject
+{
+ Q_OBJECT
+private slots:
+ void map_data();
+ void map();
+
+ void intersects_data();
+ void intersects();
+};
+
+
+void tst_qregion::map_data()
+{
+ QTest::addColumn<QRegion>("region");
+
+ {
+ QRegion region(0, 0, 100, 100);
+ QTest::newRow("single rect") << region;
+ }
+ {
+ QRegion region;
+ region = region.united(QRect(0, 0, 100, 100));
+ region = region.united(QRect(120, 20, 100, 100));
+
+ QTest::newRow("two rects") << region;
+ }
+ {
+ QRegion region(0, 0, 100, 100, QRegion::Ellipse);
+ QTest::newRow("ellipse") << region;
+ }
+}
+
+void tst_qregion::map()
+{
+ QFETCH(QRegion, region);
+
+ QTransform transform;
+ transform.rotate(30);
+ QBENCHMARK {
+ transform.map(region);
+ }
+}
+
+void tst_qregion::intersects_data()
+{
+ QTest::addColumn<QRegion>("region");
+ QTest::addColumn<QRect>("rect");
+
+ QRegion region(0, 0, 100, 100);
+ QRegion complexRegion;
+ complexRegion = complexRegion.united(QRect(0, 0, 100, 100));
+ complexRegion = complexRegion.united(QRect(120, 20, 100, 100));
+
+ {
+ QRect rect(0, 0, 100, 100);
+ QTest::newRow("same -- simple") << region << rect;
+ }
+ {
+ QRect rect(10, 10, 10, 10);
+ QTest::newRow("inside -- simple") << region << rect;
+ }
+ {
+ QRect rect(110, 110, 10, 10);
+ QTest::newRow("outside -- simple") << region << rect;
+ }
+
+ {
+ QRect rect(0, 0, 100, 100);
+ QTest::newRow("same -- complex") << complexRegion << rect;
+ }
+ {
+ QRect rect(10, 10, 10, 10);
+ QTest::newRow("inside -- complex") << complexRegion << rect;
+ }
+ {
+ QRect rect(110, 110, 10, 10);
+ QTest::newRow("outside -- complex") << complexRegion << rect;
+ }
+}
+
+void tst_qregion::intersects()
+{
+ QFETCH(QRegion, region);
+ QFETCH(QRect, rect);
+
+ QBENCHMARK {
+ region.intersects(rect);
+ }
+}
+
+QTEST_MAIN(tst_qregion)
+
+#include "main.moc"
diff --git a/tests/benchmarks/gui/painting/qregion/qregion.pro b/tests/benchmarks/gui/painting/qregion/qregion.pro
new file mode 100644
index 0000000000..ec93a62576
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qregion/qregion.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+TEMPLATE = app
+TARGET = tst_bench_qregion
+DEPENDPATH += .
+INCLUDEPATH += .
+
+CONFIG += release
+
+# Input
+SOURCES += main.cpp
diff --git a/tests/benchmarks/gui/painting/qtbench/benchmarktests.h b/tests/benchmarks/gui/painting/qtbench/benchmarktests.h
new file mode 100644
index 0000000000..f5bc717cfb
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qtbench/benchmarktests.h
@@ -0,0 +1,841 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BENCHMARKTESTS_H
+#define BENCHMARKTESTS_H
+
+#include <QApplication>
+#include <QTextDocument>
+#include <QDesktopWidget>
+#include <QTextLayout>
+#include <QFontMetrics>
+#include <QDebug>
+
+#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+# include <QStaticText>
+#endif
+
+class Benchmark
+{
+public:
+ virtual ~Benchmark() {}
+
+ Benchmark(const QSize &size)
+ : m_size(size)
+ {
+ for (int i=0; i<16; ++i) {
+ m_colors[i] = QColor::fromRgbF((rand() % 4) / 3.0,
+ (rand() % 4) / 3.0,
+ (rand() % 4) / 3.0,
+ 1);
+ }
+ }
+
+ virtual void draw(QPainter *p, const QRect &rect, int iteration) = 0;
+ virtual QString name() const = 0;
+
+ inline const QSize &size() const
+ {
+ return m_size;
+ }
+ virtual void begin(QPainter *, int iterations = 1) { Q_UNUSED(iterations); }
+ virtual void end(QPainter *) { }
+
+ inline const QColor &randomColor(int i) { return m_colors[i % 16]; }
+
+protected:
+ QColor m_colors[16];
+ QSize m_size;
+};
+
+class PaintingRectAdjuster
+{
+public:
+ PaintingRectAdjuster()
+ : m_benchmark(0),
+ m_bounds(),
+ m_screen_filled(false)
+ {
+ }
+
+ const QRect &newPaintingRect() {
+ m_rect.translate(m_rect.width(), 0);
+
+ if (m_rect.right() > m_bounds.width()) {
+ m_rect.moveLeft(m_bounds.left());
+ m_rect.translate(0,m_rect.height());
+ if (m_rect.bottom() > m_bounds.height()) {
+ m_screen_filled = true;
+ m_rect.moveTo(m_bounds.topLeft());
+ }
+ }
+ return m_rect;
+ }
+
+ inline bool isScreenFilled() const
+ { return m_screen_filled; }
+
+ void reset(const QRect &bounds)
+ {
+ m_bounds = bounds;
+ m_rect.moveTo(m_bounds.topLeft());
+ m_rect = QRect(m_bounds.topLeft(),m_benchmark->size());
+ m_rect.translate(-m_rect.width(),0);
+ m_screen_filled = false;
+ }
+
+ inline void setNewBenchmark( Benchmark *benchmark )
+ {
+ m_benchmark = benchmark;
+ }
+
+protected:
+ Benchmark *m_benchmark;
+ QRect m_rect;
+ QRect m_bounds;
+ bool m_screen_filled;
+};
+
+class FillRectBenchmark : public Benchmark
+{
+public:
+ FillRectBenchmark(int size)
+ : Benchmark(QSize(size, size))
+ {
+ }
+
+ virtual void draw(QPainter *p, const QRect &rect, int iterationCount) {
+ p->fillRect(rect, randomColor(iterationCount));
+ }
+
+ virtual QString name() const {
+ return QString::fromLatin1("fillRect(%1)").arg(m_size.width());
+ }
+};
+
+class ImageFillRectBenchmark : public Benchmark
+{
+public:
+ ImageFillRectBenchmark(int size)
+ : Benchmark(QSize(size, size))
+ {
+ int s = rand() % 24 + 8;
+ m_content = QImage(s, s, QImage::Format_ARGB32_Premultiplied);
+ QPainter p(&m_content);
+ p.fillRect(0, 0, s, s, Qt::white);
+ p.fillRect(s/2, 0, s/2, s/2, Qt::gray);
+ p.fillRect(0, s/2, s/2, s/2, Qt::gray);
+ p.end();
+
+ m_brush = QBrush(m_content);
+ }
+
+ virtual void draw(QPainter *p, const QRect &rect, int) {
+ p->fillRect(rect, m_brush);
+ }
+
+ virtual QString name() const {
+ return QString::fromLatin1("fillRect with image(%1)").arg(m_size.width());
+ }
+
+private:
+ QImage m_content;
+ QBrush m_brush;
+};
+
+
+class DrawRectBenchmark : public Benchmark
+{
+public:
+ DrawRectBenchmark(int size)
+ : Benchmark(QSize(size, size))
+ {
+ }
+
+ virtual void begin(QPainter *p, int) {
+ p->setPen(Qt::NoPen);
+ p->setBrush(randomColor(m_size.width()));
+ }
+
+
+ virtual void draw(QPainter *p, const QRect &rect, int) {
+ p->drawRect(rect);
+ }
+
+ virtual QString name() const {
+ return QString::fromLatin1("drawRect(%1)").arg(m_size.width());
+ }
+};
+
+
+class DrawRectWithBrushChangeBenchmark : public Benchmark
+{
+public:
+ DrawRectWithBrushChangeBenchmark(int size)
+ : Benchmark(QSize(size, size))
+ {
+ }
+
+ virtual void begin(QPainter *p, int) {
+ p->setPen(Qt::NoPen);
+ }
+
+
+ virtual void draw(QPainter *p, const QRect &rect, int i) {
+ p->setBrush(randomColor(i));
+ p->drawRect(rect);
+ }
+
+ virtual QString name() const {
+ return QString::fromLatin1("drawRect with brushchange(%1)").arg(m_size.width());
+ }
+};
+
+class RoundRectBenchmark : public Benchmark
+{
+public:
+ RoundRectBenchmark(int size)
+ : Benchmark(QSize(size, size))
+ {
+ m_roundness = size / 4.;
+ }
+
+ virtual void begin(QPainter *p, int) {
+ p->setPen(Qt::NoPen);
+ p->setBrush(Qt::red);
+ }
+
+ virtual void draw(QPainter *p, const QRect &rect, int) {
+ p->drawRoundedRect(rect, m_roundness, m_roundness);
+ }
+
+ virtual QString name() const {
+ return QString::fromLatin1("drawRoundedRect(%1)").arg(m_size.width());
+ }
+
+ qreal m_roundness;
+};
+
+
+class ArcsBenchmark : public Benchmark
+{
+public:
+ enum Type {
+ Stroked = 0x0001,
+ Filled = 0x0002,
+
+ ArcShape = 0x0010,
+ ChordShape = 0x0020,
+ PieShape = 0x0040,
+ CircleShape = 0x0080,
+ Shapes = 0x00f0
+
+ };
+
+ ArcsBenchmark(int size, uint type)
+ : Benchmark(QSize(size, size)),
+ m_type(type)
+ {
+ }
+
+ virtual void begin(QPainter *p, int) {
+ if (m_type & Stroked)
+ p->setPen(Qt::black);
+ else
+ p->setPen(Qt::NoPen);
+
+ if (m_type & Filled)
+ p->setBrush(Qt::red);
+ else
+ p->setBrush(Qt::NoBrush);
+ }
+
+ virtual void draw(QPainter *p, const QRect &rect, int) {
+ switch (m_type & Shapes) {
+ case ArcShape:
+ p->drawArc(rect, 45*16, 120*16);
+ break;
+ case ChordShape:
+ p->drawChord(rect, 45*16, 120*16);
+ break;
+ case PieShape:
+ p->drawPie(rect, 45*16, 120*16);
+ break;
+ case CircleShape:
+ p->drawEllipse(rect);
+ break;
+ }
+ }
+
+ virtual QString name() const {
+ QString fillStroke;
+
+ if ((m_type & (Stroked|Filled)) == (Stroked|Filled)) {
+ fillStroke = QLatin1String("Fill & Outline");
+ } else if (m_type & Stroked) {
+ fillStroke = QLatin1String("Outline");
+ } else if (m_type & Filled) {
+ fillStroke = QLatin1String("Fill");
+ }
+
+ QString shape;
+ if (m_type & PieShape) shape = QLatin1String("drawPie");
+ else if (m_type & ChordShape) shape = QLatin1String("drawChord");
+ else if (m_type & ArcShape) shape = QLatin1String("drawArc");
+ else if (m_type & CircleShape) shape = QLatin1String("drawEllipse");
+
+ return QString::fromLatin1("%1(%2) %3").arg(shape).arg(m_size.width()).arg(fillStroke);
+ }
+
+ uint m_type;
+};
+
+
+class DrawScaledImage : public Benchmark
+{
+public:
+ DrawScaledImage(const QImage &image, qreal scale, bool asPixmap)
+ : Benchmark(QSize(image.width(), image.height())),
+ m_image(image),
+ m_type(m_as_pixmap ? "Pixmap" : "Image"),
+ m_scale(scale),
+ m_as_pixmap(asPixmap)
+ {
+ m_pixmap = QPixmap::fromImage(m_image);
+ }
+ DrawScaledImage(const QString& type, const QPixmap &pixmap, qreal scale)
+ : Benchmark(QSize(pixmap.width(), pixmap.height())),
+ m_type(type),
+ m_scale(scale),
+ m_as_pixmap(true),
+ m_pixmap(pixmap)
+ {
+ }
+
+ virtual void begin(QPainter *p, int) {
+ p->scale(m_scale, m_scale);
+ }
+
+ virtual void draw(QPainter *p, const QRect &rect, int) {
+ if (m_as_pixmap)
+ p->drawPixmap(rect.topLeft(), m_pixmap);
+ else
+ p->drawImage(rect.topLeft(), m_image);
+ }
+
+ virtual QString name() const {
+ return QString::fromLatin1("draw%4(%1) at scale=%2, depth=%3")
+ .arg(m_size.width())
+ .arg(m_scale)
+ .arg(m_as_pixmap ? m_pixmap.depth() : m_image.depth())
+ .arg(m_type);
+ }
+
+private:
+ QImage m_image;
+ QString m_type;
+ qreal m_scale;
+ bool m_as_pixmap;
+ QPixmap m_pixmap;
+};
+
+class DrawTransformedImage : public Benchmark
+{
+public:
+ DrawTransformedImage(const QImage &image, bool asPixmap)
+ : Benchmark(QSize(image.width(), image.height())),
+ m_image(image),
+ m_type(m_as_pixmap ? "Pixmap" : "Image"),
+ m_as_pixmap(asPixmap)
+ {
+ m_pixmap = QPixmap::fromImage(m_image);
+ }
+ DrawTransformedImage(const QString& type, const QPixmap &pixmap)
+ : Benchmark(QSize(pixmap.width(), pixmap.height())),
+ m_type(type),
+ m_as_pixmap(true),
+ m_pixmap(pixmap)
+ {
+ }
+
+ virtual void draw(QPainter *p, const QRect &rect, int) {
+ QTransform oldTransform = p->transform();
+ p->translate(0.5 * rect.width() + rect.left(), 0.5 * rect.height() + rect.top());
+ p->shear(0.25, 0.0);
+ p->rotate(5.0);
+ if (m_as_pixmap)
+ p->drawPixmap(-0.5 * rect.width(), -0.5 * rect.height(), m_pixmap);
+ else
+ p->drawImage(-0.5 * rect.width(), -0.5 * rect.height(), m_image);
+ p->setTransform(oldTransform);
+ }
+
+ virtual QString name() const {
+ return QString::fromLatin1("draw%3(%1) w/transform, depth=%2")
+ .arg(m_size.width())
+ .arg(m_as_pixmap ? m_pixmap.depth() : m_image.depth())
+ .arg(m_type);
+ }
+
+private:
+ QImage m_image;
+ QString m_type;
+ bool m_as_pixmap;
+ QPixmap m_pixmap;
+};
+
+
+class DrawImage : public Benchmark
+{
+public:
+ DrawImage(const QImage &image, bool asPixmap)
+ : Benchmark(QSize(image.width(), image.height())),
+ m_image(image),
+ m_type(m_as_pixmap ? "Pixmap" : "Image"),
+ m_as_pixmap(asPixmap)
+ {
+ m_pixmap = QPixmap::fromImage(image);
+ }
+ DrawImage(const QString& type, const QPixmap &pixmap)
+ : Benchmark(QSize(pixmap.width(), pixmap.height())),
+ m_type(type),
+ m_as_pixmap(true),
+ m_pixmap(pixmap)
+ {
+ }
+
+ virtual void draw(QPainter *p, const QRect &rect, int) {
+ if (m_as_pixmap)
+ p->drawPixmap(rect.topLeft(), m_pixmap);
+ else
+ p->drawImage(rect.topLeft(), m_image);
+ }
+
+ virtual QString name() const {
+ return QString::fromLatin1("draw%2(%1), depth=%3")
+ .arg(m_size.width())
+ .arg(m_type)
+ .arg(m_as_pixmap ? m_pixmap.depth() : m_image.depth());
+ }
+
+private:
+ QImage m_image;
+ QString m_type;
+ bool m_as_pixmap;
+ QPixmap m_pixmap;
+};
+
+
+class DrawText : public Benchmark
+{
+public:
+ enum Mode {
+ PainterMode,
+ PainterQPointMode,
+ LayoutMode,
+ DocumentMode,
+ PixmapMode
+
+#if QT_VERSION >= 0x040700
+ , StaticTextMode,
+ StaticTextWithMaximumSizeMode,
+ StaticTextBackendOptimizations
+#endif
+ };
+
+ DrawText(const QString &text, Mode mode)
+ : Benchmark(QSize()), m_mode(mode), m_text(text), m_document(text), m_layout(text)
+ {
+ }
+
+ virtual void begin(QPainter *p, int iterations) {
+#if QT_VERSION >= 0x040700
+ m_staticTexts.clear();
+ m_currentStaticText = 0;
+#else
+ Q_UNUSED(iterations);
+#endif
+ m_pixmaps.clear();
+ m_currentPixmap = 0;
+ QRect m_bounds = QRect(0,0,p->device()->width(), p->device()->height());
+ switch (m_mode) {
+ case PainterMode:
+ m_size = (p->boundingRect(m_bounds, 0, m_text)).size();
+// m_rect = m_rect.translated(-m_rect.topLeft());
+ break;
+ case DocumentMode:
+ m_size = QSize(m_document.size().toSize());
+ break;
+ case PixmapMode:
+ for (int i=0; i<4; ++i) {
+ m_size = (p->boundingRect(m_bounds, 0, m_text)).size();
+ QPixmap pixmap = QPixmap(m_size);
+ pixmap.fill(Qt::transparent);
+ {
+ QPainter p(&pixmap);
+ p.drawText(pixmap.rect(), m_text);
+ }
+ m_pixmaps.append(pixmap);
+ }
+ break;
+
+ case LayoutMode: {
+ QRect r = p->boundingRect(m_bounds, 0, m_text);
+ QStringList lines = m_text.split('\n');
+ int height = 0;
+ int leading = p->fontMetrics().leading();
+ m_layout.beginLayout();
+ for (int i=0; i<lines.size(); ++i) {
+ QTextLine textLine = m_layout.createLine();
+ if (textLine.isValid()) {
+ textLine.setLineWidth(r.width());
+ textLine.setPosition(QPointF(0, height));
+ height += leading + textLine.height();
+ }
+ }
+ m_layout.endLayout();
+ m_layout.setCacheEnabled(true);
+ m_size = m_layout.boundingRect().toRect().size();
+ break; }
+
+#if QT_VERSION >= 0x040700
+ case StaticTextWithMaximumSizeMode: {
+ QStaticText staticText;
+ m_size = (p->boundingRect(m_bounds, 0, m_text)).size();
+ staticText.setTextWidth(m_size.width() + 10);
+ staticText.setText(m_text);
+ staticText.prepare(p->transform(), p->font());
+ m_staticTexts.append(staticText);
+ break;
+ }
+ case StaticTextBackendOptimizations: {
+ m_size = (p->boundingRect(m_bounds, 0, m_text)).size();
+ for (int i=0; i<iterations; ++i) {
+ QStaticText staticText;
+ staticText.setPerformanceHint(QStaticText::AggressiveCaching);
+ staticText.setTextWidth(m_size.width() + 10);
+ staticText.setText(m_text);
+ staticText.prepare(p->transform(), p->font());
+ m_staticTexts.append(staticText);
+ }
+
+ break;
+ }
+ case StaticTextMode: {
+ QStaticText staticText;
+ staticText.setText(m_text);
+ staticText.prepare(p->transform(), p->font());
+ m_staticTexts.append(staticText);
+
+ QFontMetrics fm(p->font());
+ m_size = QSize(fm.width(m_text, m_text.length()), fm.height());
+
+ break;
+ }
+#endif
+
+ case PainterQPointMode: {
+ QFontMetrics fm(p->font());
+ m_size = QSize(fm.width(m_text, m_text.length()), fm.height());
+ break;
+ }
+
+ }
+ }
+
+ virtual void draw(QPainter *p, const QRect &rect, int)
+ {
+ switch (m_mode) {
+ case PainterMode:
+ p->drawText(rect, 0, m_text);
+ break;
+ case PainterQPointMode:
+ p->drawText(rect.topLeft(), m_text);
+ break;
+ case PixmapMode:
+ p->drawPixmap(rect.topLeft(), m_pixmaps.at(m_currentPixmap));
+ m_currentPixmap = (m_currentPixmap + 1) % m_pixmaps.size();
+ break;
+ case DocumentMode:
+ p->translate(rect.topLeft());
+ m_document.drawContents(p);
+ p->translate(-rect.topLeft());
+ break;
+ case LayoutMode:
+ m_layout.draw(p, rect.topLeft());
+ break;
+
+#if QT_VERSION >= 0x040700
+ case StaticTextWithMaximumSizeMode:
+ case StaticTextMode:
+ p->drawStaticText(rect.topLeft(), m_staticTexts.at(0));
+ break;
+ case StaticTextBackendOptimizations:
+ p->drawStaticText(rect.topLeft(), m_staticTexts.at(m_currentStaticText));
+ m_currentStaticText = (m_currentStaticText + 1) % m_staticTexts.size();
+ break;
+#endif
+ }
+ }
+
+ virtual QString name() const {
+ int letters = m_text.length();
+ int lines = m_text.count('\n');
+ if (lines == 0)
+ lines = 1;
+ QString type;
+ switch (m_mode) {
+ case PainterMode: type = "drawText(rect)"; break;
+ case PainterQPointMode: type = "drawText(point)"; break;
+ case LayoutMode: type = "layout.draw()"; break;
+ case DocumentMode: type = "doc.drawContents()"; break;
+ case PixmapMode: type = "pixmap cached text"; break;
+
+#if QT_VERSION >= 0x040700
+ case StaticTextMode: type = "drawStaticText()"; break;
+ case StaticTextWithMaximumSizeMode: type = "drawStaticText() w/ maxsize"; break;
+ case StaticTextBackendOptimizations: type = "drawStaticText() w/ backend optimizations"; break;
+#endif
+ }
+
+ return QString::fromLatin1("%3, len=%1, lines=%2")
+ .arg(letters)
+ .arg(lines)
+ .arg(type);
+ }
+
+private:
+ Mode m_mode;
+ QString m_text;
+ QTextDocument m_document;
+ QTextLayout m_layout;
+
+ QList<QPixmap> m_pixmaps;
+ int m_currentPixmap;
+
+#if QT_VERSION >= 0x040700
+ int m_currentStaticText;
+ QList<QStaticText> m_staticTexts;
+#endif
+};
+
+
+
+
+class ClippedDrawRectBenchmark : public Benchmark
+{
+public:
+ enum ClipType {
+ RectClip,
+ TwoRectRegionClip,
+ EllipseRegionClip,
+ TwoRectPathClip,
+ EllipsePathClip,
+ AAEllipsePathClip,
+ EllipseRegionThenRectClip,
+ EllipsePathThenRectClip
+ };
+
+ ClippedDrawRectBenchmark(int size, ClipType type)
+ : Benchmark(QSize(size, size)), m_type(type)
+ {
+ }
+
+ virtual void begin(QPainter *p, int) {
+ QRect m_bounds = QRect(0,0,p->device()->width(), p->device()->height());
+ p->setPen(Qt::NoPen);
+ p->setBrush(Qt::red);
+
+ switch (m_type) {
+ case RectClip:
+ p->setClipRect(m_bounds.adjusted(1, 1, -1, -1));
+ break;
+ case TwoRectRegionClip:
+ p->setClipRegion(QRegion(m_bounds.adjusted(0, 0, -1, -1))
+ | QRegion(m_bounds.adjusted(1, 1, 0, 0)));
+ break;
+ case EllipseRegionClip:
+ p->setClipRegion(QRegion(m_bounds, QRegion::Ellipse));
+ break;
+ case TwoRectPathClip:
+ {
+ QPainterPath path;
+ path.addRect(m_bounds.adjusted(0, 0, -1, -1));
+ path.addRect(m_bounds.adjusted(1, 1, 0, 0));
+ path.setFillRule(Qt::WindingFill);
+ p->setClipPath(path);
+ }
+ break;
+ case EllipsePathClip:
+ {
+ QPainterPath path;
+ path.addEllipse(m_bounds);
+ p->setClipPath(path);
+ }
+ break;
+ case AAEllipsePathClip:
+ {
+ QPainterPath path;
+ path.addEllipse(m_bounds);
+ p->setRenderHint(QPainter::Antialiasing);
+ p->setClipPath(path);
+ p->setRenderHint(QPainter::Antialiasing, false);
+ }
+ break;
+ case EllipseRegionThenRectClip:
+ p->setClipRegion(QRegion(m_bounds, QRegion::Ellipse));
+ p->setClipRegion(QRegion(m_bounds.width() / 4,
+ m_bounds.height() / 4,
+ m_bounds.width() / 2,
+ m_bounds.height() / 2), Qt::IntersectClip);
+ break;
+ case EllipsePathThenRectClip:
+ {
+ QPainterPath path;
+ path.addEllipse(m_bounds);
+ p->setClipPath(path);
+ p->setClipRegion(QRegion(m_bounds.width() / 4,
+ m_bounds.height() / 4,
+ m_bounds.width() / 2,
+ m_bounds.height() / 2), Qt::IntersectClip);
+ }
+ break;
+ }
+ }
+
+ virtual void draw(QPainter *p, const QRect &rect, int) {
+ p->drawRect(rect);
+ }
+
+ virtual QString name() const {
+ QString namedType;
+ switch (m_type) {
+ case RectClip:
+ namedType = "rect";
+ break;
+ case TwoRectRegionClip:
+ namedType = "two-rect-region";
+ break;
+ case EllipseRegionClip:
+ namedType = "ellipse-region";
+ break;
+ case TwoRectPathClip:
+ namedType = "two-rect-path";
+ break;
+ case EllipsePathClip:
+ namedType = "ellipse-path";
+ break;
+ case AAEllipsePathClip:
+ namedType = "aa-ellipse-path";
+ break;
+ case EllipseRegionThenRectClip:
+ namedType = "ellipseregion&rect";
+ break;
+ case EllipsePathThenRectClip:
+ namedType = "ellipsepath&rect";
+ break;
+ }
+ return QString::fromLatin1("%1-clipped-drawRect(%2)").arg(namedType).arg(m_size.width());
+ }
+
+ ClipType m_type;
+};
+
+class LinesBenchmark : public Benchmark
+{
+public:
+ enum LineType {
+ Horizontal_Integer,
+ Diagonal_Integer,
+ Vertical_Integer,
+ Horizontal_Float,
+ Diagonal_Float,
+ Vertical_Float
+ };
+
+ LinesBenchmark(int length, LineType type)
+ : Benchmark(QSize(qAbs(length), qAbs(length))),
+ m_type(type),
+ m_length(length)
+ {
+
+ }
+
+ virtual void draw(QPainter *p, const QRect &rect, int) {
+ switch (m_type) {
+ case Horizontal_Integer:
+ p->drawLine(QLine(rect.x(), rect.y(), rect.x() + m_length, rect.y()));
+ break;
+ case Diagonal_Integer:
+ p->drawLine(QLine(rect.x(), rect.y(), rect.x() + m_length, rect.y() + m_length));
+ break;
+ case Vertical_Integer:
+ p->drawLine(QLine(rect.x() + 4, rect.y(), rect.x() + 4, rect.y() + m_length));
+ break;
+ case Horizontal_Float:
+ p->drawLine(QLineF(rect.x(), rect.y(), rect.x() + m_length, rect.y()));
+ break;
+ case Diagonal_Float:
+ p->drawLine(QLineF(rect.x(), rect.y(), rect.x() + m_length, rect.y() + m_length));
+ break;
+ case Vertical_Float:
+ p->drawLine(QLineF(rect.x() + 4, rect.y(), rect.x() + 4, rect.y() + m_length));
+ break;
+ }
+ }
+
+ virtual QString name() const {
+ const char *names[] = {
+ "Hor_I",
+ "Diag_I",
+ "Ver_I",
+ "Hor_F",
+ "Diag_F",
+ "Ver_F"
+ };
+ return QString::fromLatin1("drawLine(size=%1,type=%2)").arg(m_length).arg(names[m_type]);
+ }
+
+ LineType m_type;
+ int m_length;
+};
+
+#endif // BENCHMARKTESTS_H
diff --git a/tests/benchmarks/gui/painting/qtbench/qtbench.pro b/tests/benchmarks/gui/painting/qtbench/qtbench.pro
new file mode 100644
index 0000000000..91f416de79
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qtbench/qtbench.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+TEMPLATE = app
+TARGET = tst_qtbench
+
+SOURCES += tst_qtbench.cpp
+
diff --git a/tests/benchmarks/gui/painting/qtbench/tst_qtbench.cpp b/tests/benchmarks/gui/painting/qtbench/tst_qtbench.cpp
new file mode 100644
index 0000000000..d8082cc2e0
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qtbench/tst_qtbench.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+
+#include <QtGui>
+
+#include "benchmarktests.h"
+
+//TESTED_FILES=
+
+class BenchWidget : public QWidget
+{
+public:
+ BenchWidget(Benchmark *benchmark);
+
+ void paintEvent(QPaintEvent *event);
+
+ bool done() const { return m_done; }
+ qreal result() const { return m_result; }
+
+public:
+ QTime timer;
+
+ Benchmark *m_benchmark;
+
+ bool m_done;
+ qreal m_result;
+
+ uint m_total;
+ uint m_iteration;
+
+ QVector<uint> iterationTimes;
+};
+
+void BenchWidget::paintEvent(QPaintEvent *)
+{
+ if (m_done)
+ return;
+
+ QPainter p(this);
+
+ m_benchmark->begin(&p, 100);
+
+ PaintingRectAdjuster adjuster;
+ adjuster.setNewBenchmark(m_benchmark);
+ adjuster.reset(rect());
+
+ for (int i = 0; i < 100; ++i)
+ m_benchmark->draw(&p, adjuster.newPaintingRect(), i);
+
+ m_benchmark->end(&p);
+
+ ++m_iteration;
+
+ uint currentElapsed = timer.isNull() ? 0 : timer.elapsed();
+ timer.restart();
+
+ m_total += currentElapsed;
+
+ // warm up for at most 5 iterations or half a second
+ if (m_iteration >= 5 || m_total >= 500) {
+ iterationTimes << currentElapsed;
+
+ if (iterationTimes.size() >= 5) {
+ qreal mean = 0;
+ qreal stddev = 0;
+ uint min = INT_MAX;
+
+ for (int i = 0; i < iterationTimes.size(); ++i) {
+ mean += iterationTimes.at(i);
+ min = qMin(min, iterationTimes.at(i));
+ }
+
+ mean /= qreal(iterationTimes.size());
+
+ for (int i = 0; i < iterationTimes.size(); ++i) {
+ qreal delta = iterationTimes.at(i) - mean;
+ stddev += delta * delta;
+ }
+
+ stddev = qSqrt(stddev / iterationTimes.size());
+
+ stddev = 100 * stddev / mean;
+ // do 50 iterations, break earlier if we spend more than 5 seconds or have a low std deviation after 2 seconds
+ if (iterationTimes.size() >= 50 || m_total >= 5000 || (m_total >= 2000 && stddev < 4)) {
+ m_result = min;
+ m_done = true;
+ return;
+ }
+ }
+ }
+}
+
+BenchWidget::BenchWidget(Benchmark *benchmark)
+ : m_benchmark(benchmark)
+ , m_done(false)
+ , m_result(0)
+ , m_total(0)
+ , m_iteration(0)
+{
+ setWindowTitle(benchmark->name());
+ resize(640, 480);
+}
+
+class tst_QtBench : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void qtBench();
+ void qtBench_data();
+};
+
+QString makeString(int length)
+{
+ const char chars[] = "abcd efgh ijkl mnop qrst uvwx yz!$. ABCD 1234";
+ int len = strlen(chars);
+
+ QString ret;
+ for (int j = 0; j < length; j++) {
+ ret += QChar(chars[(j * 97) % len]);
+ }
+
+ return ret;
+}
+
+void tst_QtBench::qtBench_data()
+{
+ QTest::addColumn<void *>("benchmark");
+
+ QString shortString = makeString(5);
+ QString middleString = makeString(50);
+ QString longString = makeString(35) + "\n"
+ + makeString(45) + "\n"
+ + makeString(75);
+ QString superLongString = "Lorem ipsum dolor sit am\n"
+ "et, consectetur adipisci\n"
+ "ng elit. Integer mi leo,\n"
+ "interdum ut congue at, p\n"
+ "ulvinar et tellus. Quisq\n"
+ "ue pretium eleifend laci\n"
+ "nia. Ut semper gravida l\n"
+ "ectus in commodo. Vestib\n"
+ "ulum pharetra arcu in en\n"
+ "im ultrices hendrerit. P\n"
+ "ellentesque habitant mor\n"
+ "bi tristique senectus et\n"
+ "netus et malesuada fames\n"
+ "ac turpis egestas. Ut er\n"
+ "os sem, feugiat in eleme\n"
+ "ntum in, porta sit amet \n"
+ "neque. Fusce mi tellus, \n"
+ "congue non dapibus eget,\n"
+ "pharetra quis quam. Duis\n"
+ "dui massa, pulvinar ac s\n"
+ "odales pharetra, dictum \n"
+ "in enim. Phasellus a nis\n"
+ "i erat, sed pellentesque\n"
+ "mi. Curabitur sed.";
+
+ QList<Benchmark *> benchmarks;
+ benchmarks << (new DrawText(shortString, DrawText::PainterMode));
+ benchmarks << (new DrawText(middleString, DrawText::PainterMode));
+ benchmarks << (new DrawText(longString, DrawText::PainterMode));
+ benchmarks << (new DrawText(superLongString, DrawText::PainterMode));
+
+ benchmarks << (new DrawText(shortString, DrawText::PainterQPointMode));
+ benchmarks << (new DrawText(middleString, DrawText::PainterQPointMode));
+ benchmarks << (new DrawText(longString, DrawText::PainterQPointMode));
+ benchmarks << (new DrawText(superLongString, DrawText::PainterQPointMode));
+
+ benchmarks << (new DrawText(shortString, DrawText::PixmapMode));
+ benchmarks << (new DrawText(middleString, DrawText::PixmapMode));
+ benchmarks << (new DrawText(longString, DrawText::PixmapMode));
+ benchmarks << (new DrawText(superLongString, DrawText::PixmapMode));
+
+#if QT_VERSION >= 0x040700
+ benchmarks << (new DrawText(shortString, DrawText::StaticTextMode));
+ benchmarks << (new DrawText(middleString, DrawText::StaticTextMode));
+ benchmarks << (new DrawText(longString, DrawText::StaticTextMode));
+ benchmarks << (new DrawText(superLongString, DrawText::StaticTextMode));
+
+ benchmarks << (new DrawText(shortString, DrawText::StaticTextWithMaximumSizeMode));
+ benchmarks << (new DrawText(middleString, DrawText::StaticTextWithMaximumSizeMode));
+ benchmarks << (new DrawText(longString, DrawText::StaticTextWithMaximumSizeMode));
+ benchmarks << (new DrawText(superLongString, DrawText::StaticTextWithMaximumSizeMode));
+
+ benchmarks << (new DrawText(shortString, DrawText::StaticTextBackendOptimizations));
+ benchmarks << (new DrawText(middleString, DrawText::StaticTextBackendOptimizations));
+ benchmarks << (new DrawText(longString, DrawText::StaticTextBackendOptimizations));
+ benchmarks << (new DrawText(superLongString, DrawText::StaticTextBackendOptimizations));
+#endif
+
+ foreach (Benchmark *benchmark, benchmarks)
+ QTest::newRow(qPrintable(benchmark->name())) << reinterpret_cast<void *>(benchmark);
+}
+
+void tst_QtBench::qtBench()
+{
+ QFETCH(void *, benchmark);
+
+ BenchWidget widget(reinterpret_cast<Benchmark *>(benchmark));
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ while (!widget.done()) {
+ widget.update();
+ QApplication::processEvents();
+ }
+
+ QTest::setBenchmarkResult(widget.result(), QTest::WalltimeMilliseconds);
+}
+
+QTEST_MAIN(tst_QtBench)
+#include "tst_qtbench.moc"
diff --git a/tests/benchmarks/gui/painting/qtracebench/qtracebench.pro b/tests/benchmarks/gui/painting/qtracebench/qtracebench.pro
new file mode 100644
index 0000000000..56ec8bbe4e
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qtracebench/qtracebench.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+TEMPLATE = app
+TARGET = tst_qtracebench
+
+INCLUDEPATH += . $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src
+
+RESOURCES += qtracebench.qrc
+
+SOURCES += tst_qtracebench.cpp
+
diff --git a/tests/benchmarks/gui/painting/qtracebench/qtracebench.qrc b/tests/benchmarks/gui/painting/qtracebench/qtracebench.qrc
new file mode 100644
index 0000000000..5569550bc5
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qtracebench/qtracebench.qrc
@@ -0,0 +1,10 @@
+<RCC>
+ <qresource>
+ <file>traces/basicdrawing.trace</file>
+ <file>traces/webkit.trace</file>
+ <file>traces/textedit.trace</file>
+ <file>traces/creator.trace</file>
+ <file>traces/qmlphoneconcept.trace</file>
+ <file>traces/qmlsamegame.trace</file>
+ </qresource>
+</RCC>
diff --git a/tests/benchmarks/gui/painting/qtracebench/traces/basicdrawing.trace b/tests/benchmarks/gui/painting/qtracebench/traces/basicdrawing.trace
new file mode 100644
index 0000000000..0241d08a97
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qtracebench/traces/basicdrawing.trace
Binary files differ
diff --git a/tests/benchmarks/gui/painting/qtracebench/traces/creator.trace b/tests/benchmarks/gui/painting/qtracebench/traces/creator.trace
new file mode 100644
index 0000000000..55ee9e183e
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qtracebench/traces/creator.trace
Binary files differ
diff --git a/tests/benchmarks/gui/painting/qtracebench/traces/qmlphoneconcept.trace b/tests/benchmarks/gui/painting/qtracebench/traces/qmlphoneconcept.trace
new file mode 100644
index 0000000000..835ebfa8fb
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qtracebench/traces/qmlphoneconcept.trace
Binary files differ
diff --git a/tests/benchmarks/gui/painting/qtracebench/traces/qmlsamegame.trace b/tests/benchmarks/gui/painting/qtracebench/traces/qmlsamegame.trace
new file mode 100644
index 0000000000..1d76195443
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qtracebench/traces/qmlsamegame.trace
Binary files differ
diff --git a/tests/benchmarks/gui/painting/qtracebench/traces/textedit.trace b/tests/benchmarks/gui/painting/qtracebench/traces/textedit.trace
new file mode 100644
index 0000000000..998716d6c1
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qtracebench/traces/textedit.trace
Binary files differ
diff --git a/tests/benchmarks/gui/painting/qtracebench/traces/webkit.trace b/tests/benchmarks/gui/painting/qtracebench/traces/webkit.trace
new file mode 100644
index 0000000000..43e752d193
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qtracebench/traces/webkit.trace
Binary files differ
diff --git a/tests/benchmarks/gui/painting/qtracebench/tst_qtracebench.cpp b/tests/benchmarks/gui/painting/qtracebench/tst_qtracebench.cpp
new file mode 100644
index 0000000000..e71cfc6413
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qtracebench/tst_qtracebench.cpp
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+
+#include <QtGui>
+
+#include <private/qpaintengineex_p.h>
+#include <private/qpaintbuffer_p.h>
+
+//TESTED_FILES=
+
+class ReplayWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ ReplayWidget(const QString &filename);
+
+ void paintEvent(QPaintEvent *event);
+ void resizeEvent(QResizeEvent *event);
+
+ bool done() const { return m_done; }
+ qreal result() const { return m_result; }
+
+public slots:
+ void updateRect();
+
+public:
+ QList<QRegion> updates;
+ QPaintBuffer buffer;
+
+ int currentFrame;
+ int currentIteration;
+ QTime timer;
+
+ QList<uint> visibleUpdates;
+ QList<uint> iterationTimes;
+ QString filename;
+
+ bool m_done;
+ qreal m_result;
+
+ uint m_total;
+};
+
+void ReplayWidget::updateRect()
+{
+ if (!visibleUpdates.isEmpty())
+ update(updates.at(visibleUpdates.at(currentFrame)));
+}
+
+void ReplayWidget::paintEvent(QPaintEvent *)
+{
+ if (m_done)
+ return;
+
+ QPainter p(this);
+
+ // if partial updates don't work
+ // p.setClipRegion(frames.at(currentFrame).updateRegion);
+
+ buffer.draw(&p, visibleUpdates.at(currentFrame));
+
+ ++currentFrame;
+ if (currentFrame >= visibleUpdates.size()) {
+ currentFrame = 0;
+ ++currentIteration;
+
+ uint currentElapsed = timer.isNull() ? 0 : timer.elapsed();
+ timer.restart();
+
+ m_total += currentElapsed;
+
+ // warm up for at most 5 iterations or half a second
+ if (currentIteration >= 5 || m_total >= 500) {
+ iterationTimes << currentElapsed;
+
+ if (iterationTimes.size() >= 5) {
+ qreal mean = 0;
+ qreal stddev = 0;
+ uint min = INT_MAX;
+
+ for (int i = 0; i < iterationTimes.size(); ++i) {
+ mean += iterationTimes.at(i);
+ min = qMin(min, iterationTimes.at(i));
+ }
+
+ mean /= qreal(iterationTimes.size());
+
+ for (int i = 0; i < iterationTimes.size(); ++i) {
+ qreal delta = iterationTimes.at(i) - mean;
+ stddev += delta * delta;
+ }
+
+ stddev = qSqrt(stddev / iterationTimes.size());
+
+ qSort(iterationTimes.begin(), iterationTimes.end());
+ uint median = iterationTimes.at(iterationTimes.size() / 2);
+
+ stddev = 100 * stddev / mean;
+ // do 100 iterations, break earlier if we spend more than 5 seconds or have a low std deviation after 2 seconds
+ if (iterationTimes.size() >= 100 || m_total >= 5000 || (m_total >= 2000 && stddev < 4)) {
+ printf("%s, iterations: %d, frames: %d, min(ms): %d, median(ms): %d, stddev: %f %%, max(fps): %f\n", qPrintable(filename),
+ iterationTimes.size(), visibleUpdates.size(), min, median, stddev, 1000. * visibleUpdates.size() / min);
+ m_result = min;
+ m_done = true;
+ return;
+ }
+ }
+ }
+ }
+}
+
+void ReplayWidget::resizeEvent(QResizeEvent *event)
+{
+ visibleUpdates.clear();
+
+ QRect bounds = rect();
+ for (int i = 0; i < updates.size(); ++i) {
+ if (updates.at(i).intersects(bounds))
+ visibleUpdates << i;
+ }
+
+ if (visibleUpdates.size() != updates.size())
+ printf("Warning: skipped %d frames due to limited resolution\n", updates.size() - visibleUpdates.size());
+
+}
+
+ReplayWidget::ReplayWidget(const QString &filename_)
+ : currentFrame(0)
+ , currentIteration(0)
+ , filename(filename_)
+ , m_done(false)
+ , m_result(0)
+ , m_total(0)
+{
+ setWindowTitle(filename);
+ QFile file(filename);
+
+ if (!file.open(QIODevice::ReadOnly)) {
+ printf("Failed to load input file '%s'\n", qPrintable(filename_));
+ return;
+ }
+
+ QDataStream in(&file);
+
+ char *data;
+ uint size;
+ in.readBytes(data, size);
+ bool isTraceFile = size >= 7 && qstrncmp(data, "qttrace", 7) == 0;
+ uint version = 0;
+ if (size == 9 && qstrncmp(data, "qttraceV2", 9) == 0) {
+ in.setFloatingPointPrecision(QDataStream::SinglePrecision);
+ in >> version;
+ }
+
+ delete [] data;
+ if (!isTraceFile) {
+ printf("File '%s' is not a trace file\n", qPrintable(filename_));
+ return;
+ }
+
+ in >> buffer >> updates;
+
+ resize(buffer.boundingRect().size().toSize());
+
+ setAutoFillBackground(false);
+ setAttribute(Qt::WA_NoSystemBackground);
+}
+
+
+class tst_QTraceBench : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void trace();
+ void trace_data();
+};
+
+static const QLatin1String prefix(":/traces/");
+
+void tst_QTraceBench::trace_data()
+{
+ QTest::addColumn<QString>("filename");
+
+ QTest::newRow("basicdrawing") << (prefix + "basicdrawing.trace");
+ QTest::newRow("webkit") << (prefix + "webkit.trace");
+ QTest::newRow("creator") << (prefix + "creator.trace");
+ QTest::newRow("textedit") << (prefix + "textedit.trace");
+ QTest::newRow("qmlphoneconcept") << (prefix + "qmlphoneconcept.trace");
+ QTest::newRow("qmlsamegame") << (prefix + "qmlsamegame.trace");
+}
+
+void tst_QTraceBench::trace()
+{
+ QFETCH(QString, filename);
+
+ QFile file(filename);
+ if (!file.exists()) {
+ qWarning() << "Missing file" << filename;
+ return;
+ }
+
+ ReplayWidget widget(filename);
+
+ if (widget.updates.isEmpty()) {
+ qWarning() << "No trace updates" << filename;
+ return;
+ }
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ while (!widget.done()) {
+ widget.updateRect();
+ QApplication::processEvents();
+ }
+
+ QTest::setBenchmarkResult(widget.result(), QTest::WalltimeMilliseconds);
+}
+
+QTEST_MAIN(tst_QTraceBench)
+#include "tst_qtracebench.moc"
diff --git a/tests/benchmarks/gui/painting/qtransform/qtransform.pro b/tests/benchmarks/gui/painting/qtransform/qtransform.pro
new file mode 100644
index 0000000000..dc60407252
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qtransform/qtransform.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+TEMPLATE = app
+TARGET = tst_bench_qtransform
+
+SOURCES += tst_qtransform.cpp
+
diff --git a/tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp b/tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp
new file mode 100644
index 0000000000..d9498d941a
--- /dev/null
+++ b/tests/benchmarks/gui/painting/qtransform/tst_qtransform.cpp
@@ -0,0 +1,592 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QTransform>
+
+//TESTED_FILES=
+
+class tst_QTransform : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QTransform();
+ virtual ~tst_QTransform();
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void construct();
+ void translate_data();
+ void translate();
+ void scale_data();
+ void scale();
+ void shear_data();
+ void shear();
+ void rotate_data();
+ void rotate();
+ void rotateXYZ_data();
+ void rotateXYZ();
+ void operatorAssign_data();
+ void operatorAssign();
+ void operatorEqual_data();
+ void operatorEqual();
+ void operatorNotEqual_data();
+ void operatorNotEqual();
+ void operatorMultiply_data();
+ void operatorMultiply();
+ void operatorPlusEqualScalar_data();
+ void operatorPlusEqualScalar();
+ void operatorMinusEqualScalar_data();
+ void operatorMinusEqualScalar();
+ void operatorMultiplyEqual_data();
+ void operatorMultiplyEqual();
+ void operatorMultiplyEqualScalar_data();
+ void operatorMultiplyEqualScalar();
+ void operatorDivideEqualScalar_data();
+ void operatorDivideEqualScalar();
+ void mapQPoint_data();
+ void mapQPoint();
+ void mapQPointF_data();
+ void mapQPointF();
+ void mapRect_data();
+ void mapRect();
+ void mapRectF_data();
+ void mapRectF();
+ void mapQPolygon_data();
+ void mapQPolygon();
+ void mapQPolygonF_data();
+ void mapQPolygonF();
+ void mapQRegion_data();
+ void mapQRegion();
+ void mapToPolygon_data();
+ void mapToPolygon();
+ void mapQPainterPath_data();
+ void mapQPainterPath();
+ void isIdentity_data();
+ void isIdentity();
+ void isAffine_data();
+ void isAffine();
+ void isInvertible_data();
+ void isInvertible();
+ void isRotating_data();
+ void isRotating();
+ void isScaling_data();
+ void isScaling();
+ void isTranslating_data();
+ void isTranslating();
+ void type_data();
+ void type();
+ void determinant_data();
+ void determinant();
+ void adjoint_data();
+ void adjoint();
+ void transposed_data();
+ void transposed();
+ void inverted_data();
+ void inverted();
+
+private:
+ QMap<const char *, QTransform> generateTransforms() const;
+};
+
+tst_QTransform::tst_QTransform()
+{
+}
+
+tst_QTransform::~tst_QTransform()
+{
+}
+
+void tst_QTransform::init()
+{
+}
+
+void tst_QTransform::cleanup()
+{
+}
+
+QMap<const char *, QTransform> tst_QTransform::generateTransforms() const
+{
+ QMap<const char *, QTransform> x;
+ x["0: identity"] = QTransform();
+ x["1: translate"] = QTransform().translate(10, 10);
+ x["2: translate"] = QTransform().translate(-10, -10);
+ x["3: rotate45"] = QTransform().rotate(45);
+ x["4: rotate90"] = QTransform().rotate(90);
+ x["5: rotate180"] = QTransform().rotate(180);
+ x["6: shear2,2"] = QTransform().shear(2, 2);
+ x["7: shear-2,-2"] = QTransform().shear(-2, -2);
+ x["8: scaleUp2,2"] = QTransform().scale(2, 2);
+ x["9: scaleUp2,3"] = QTransform().scale(2, 3);
+ x["10: scaleDown0.5,0.5"] = QTransform().scale(0.5, 0.5);
+ x["11: scaleDown0.5,0.25"] = QTransform().scale(0.5, 0.25);
+ x["12: rotateX"] = QTransform().rotate(45, Qt::XAxis);
+ x["13: rotateY"] = QTransform().rotate(45, Qt::YAxis);
+ x["14: rotateXY"] = QTransform().rotate(45, Qt::XAxis).rotate(45, Qt::YAxis);
+ x["15: rotateYZ"] = QTransform().rotate(45, Qt::YAxis).rotate(45, Qt::ZAxis);
+ x["16: full"] = QTransform().translate(10, 10).rotate(45).shear(2, 2).scale(2, 2).rotate(45, Qt::YAxis).rotate(45, Qt::XAxis).rotate(45, Qt::ZAxis);
+ return x;
+}
+
+void tst_QTransform::construct()
+{
+ QBENCHMARK {
+ QTransform x;
+ }
+}
+
+#define SINGLE_DATA_IMPLEMENTATION(func) \
+void tst_QTransform::func##_data() \
+{ \
+ QTest::addColumn<QTransform>("transform"); \
+ QMap<const char *, QTransform> x = generateTransforms(); \
+ QMapIterator<const char *, QTransform> it(x); \
+ while (it.hasNext()) { \
+ it.next(); \
+ QTest::newRow(it.key()) << it.value(); \
+ } \
+}
+
+#define DOUBLE_DATA_IMPLEMENTATION(func) \
+void tst_QTransform::func##_data() \
+{ \
+ QTest::addColumn<QTransform>("x1"); \
+ QTest::addColumn<QTransform>("x2"); \
+ QMap<const char *, QTransform> x = generateTransforms(); \
+ QMapIterator<const char *, QTransform> it(x); \
+ while (it.hasNext()) { \
+ it.next(); \
+ const char *key1 = it.key(); \
+ QTransform x1 = it.value(); \
+ QMapIterator<const char *, QTransform> it2(x); \
+ while (it2.hasNext()) { \
+ it2.next(); \
+ QTest::newRow(QString("%1 + %2").arg(key1).arg(it2.key()).toLatin1().constData()) \
+ << x1 << it2.value(); \
+ } \
+ } \
+}
+
+SINGLE_DATA_IMPLEMENTATION(translate)
+
+void tst_QTransform::translate()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QBENCHMARK {
+ x.translate(10, 10);
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(scale)
+
+void tst_QTransform::scale()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QBENCHMARK {
+ x.scale(2, 2);
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(shear)
+
+void tst_QTransform::shear()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QBENCHMARK {
+ x.shear(2, 2);
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(rotate)
+
+void tst_QTransform::rotate()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QBENCHMARK {
+ x.rotate(45);
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(rotateXYZ)
+
+void tst_QTransform::rotateXYZ()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QBENCHMARK {
+ x.rotate(45, Qt::XAxis);
+ x.rotate(45, Qt::YAxis);
+ x.rotate(45, Qt::ZAxis);
+ }
+}
+
+DOUBLE_DATA_IMPLEMENTATION(operatorAssign)
+
+void tst_QTransform::operatorAssign()
+{
+ QFETCH(QTransform, x1);
+ QFETCH(QTransform, x2);
+ QTransform x = x1;
+ QBENCHMARK {
+ x = x2;
+ }
+}
+
+DOUBLE_DATA_IMPLEMENTATION(operatorEqual)
+
+void tst_QTransform::operatorEqual()
+{
+ QFETCH(QTransform, x1);
+ QFETCH(QTransform, x2);
+ QTransform x = x1;
+ QBENCHMARK {
+ x == x2;
+ }
+}
+
+DOUBLE_DATA_IMPLEMENTATION(operatorNotEqual)
+
+void tst_QTransform::operatorNotEqual()
+{
+ QFETCH(QTransform, x1);
+ QFETCH(QTransform, x2);
+ QTransform x = x1;
+ QBENCHMARK {
+ x != x2;
+ }
+}
+
+DOUBLE_DATA_IMPLEMENTATION(operatorMultiply)
+
+void tst_QTransform::operatorMultiply()
+{
+ QFETCH(QTransform, x1);
+ QFETCH(QTransform, x2);
+ QTransform x = x1;
+ QBENCHMARK {
+ x * x2;
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(operatorPlusEqualScalar)
+
+void tst_QTransform::operatorPlusEqualScalar()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QBENCHMARK {
+ x += 3.14;
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(operatorMinusEqualScalar)
+
+void tst_QTransform::operatorMinusEqualScalar()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QBENCHMARK {
+ x -= 3.14;
+ }
+}
+
+DOUBLE_DATA_IMPLEMENTATION(operatorMultiplyEqual)
+
+void tst_QTransform::operatorMultiplyEqual()
+{
+ QFETCH(QTransform, x1);
+ QFETCH(QTransform, x2);
+ QTransform x = x1;
+ QBENCHMARK {
+ x *= x2;
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(operatorMultiplyEqualScalar)
+
+void tst_QTransform::operatorMultiplyEqualScalar()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QBENCHMARK {
+ x * 3;
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(operatorDivideEqualScalar)
+
+void tst_QTransform::operatorDivideEqualScalar()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QBENCHMARK {
+ x /= 3;
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(mapQPoint)
+
+void tst_QTransform::mapQPoint()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QBENCHMARK {
+ x.map(QPoint(3, 3));
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(mapQPointF)
+
+void tst_QTransform::mapQPointF()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QBENCHMARK {
+ x.map(QPointF(3, 3));
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(mapRect)
+
+void tst_QTransform::mapRect()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QBENCHMARK {
+ x.mapRect(QRect(0, 0, 100, 100));
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(mapRectF)
+
+void tst_QTransform::mapRectF()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QBENCHMARK {
+ x.mapRect(QRectF(0, 0, 100, 100));
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(mapQPolygon)
+
+void tst_QTransform::mapQPolygon()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QPolygon poly = QPolygon(QRect(0, 0, 100, 100));
+ QBENCHMARK {
+ x.map(poly);
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(mapQPolygonF)
+
+void tst_QTransform::mapQPolygonF()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QPolygonF poly = QPolygonF(QRectF(0, 0, 100, 100));
+ QBENCHMARK {
+ x.map(poly);
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(mapQRegion)
+
+void tst_QTransform::mapQRegion()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QRegion region;
+ for (int i = 0; i < 10; ++i)
+ region += QRect(i * 10, i * 10, 100, 100);
+ QBENCHMARK {
+ x.map(region);
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(mapToPolygon)
+
+void tst_QTransform::mapToPolygon()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QBENCHMARK {
+ x.mapToPolygon(QRect(0, 0, 100, 100));
+ }
+}
+
+
+SINGLE_DATA_IMPLEMENTATION(mapQPainterPath)
+
+void tst_QTransform::mapQPainterPath()
+{
+ QFETCH(QTransform, transform);
+ QTransform x = transform;
+ QPainterPath path;
+ for (int i = 0; i < 10; ++i)
+ path.addEllipse(i * 10, i * 10, 100, 100);
+ QBENCHMARK {
+ x.map(path);
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(isIdentity)
+
+void tst_QTransform::isIdentity()
+{
+ QFETCH(QTransform, transform);
+ QBENCHMARK {
+ transform.isIdentity();
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(isAffine)
+
+void tst_QTransform::isAffine()
+{
+ QFETCH(QTransform, transform);
+ QBENCHMARK {
+ transform.isAffine();
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(isInvertible)
+
+void tst_QTransform::isInvertible()
+{
+ QFETCH(QTransform, transform);
+ QBENCHMARK {
+ transform.isInvertible();
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(isRotating)
+
+void tst_QTransform::isRotating()
+{
+ QFETCH(QTransform, transform);
+ QBENCHMARK {
+ transform.isRotating();
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(isScaling)
+
+void tst_QTransform::isScaling()
+{
+ QFETCH(QTransform, transform);
+ QBENCHMARK {
+ transform.isScaling();
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(isTranslating)
+
+void tst_QTransform::isTranslating()
+{
+ QFETCH(QTransform, transform);
+ QBENCHMARK {
+ transform.isTranslating();
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(type)
+
+void tst_QTransform::type()
+{
+ QFETCH(QTransform, transform);
+ QBENCHMARK {
+ transform.type();
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(determinant)
+
+void tst_QTransform::determinant()
+{
+ QFETCH(QTransform, transform);
+ QBENCHMARK {
+ transform.determinant();
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(adjoint)
+
+void tst_QTransform::adjoint()
+{
+ QFETCH(QTransform, transform);
+ QBENCHMARK {
+ transform.adjoint();
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(transposed)
+
+void tst_QTransform::transposed()
+{
+ QFETCH(QTransform, transform);
+ QBENCHMARK {
+ transform.transposed();
+ }
+}
+
+SINGLE_DATA_IMPLEMENTATION(inverted)
+
+void tst_QTransform::inverted()
+{
+ QFETCH(QTransform, transform);
+ QBENCHMARK {
+ transform.inverted();
+ }
+}
+
+QTEST_MAIN(tst_QTransform)
+#include "tst_qtransform.moc"