| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the test suite of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include <qtest.h> |
| #include <QPainter> |
| #include <QPainterPath> |
| #include <QPixmap> |
| #include <QImage> |
| #include <QPaintEngine> |
| #include <QTileRules> |
| #include <qmath.h> |
| |
| #include <private/qpixmap_raster_p.h> |
| |
| 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) |
| { |
| QPlatformPixmap *data = |
| new QRasterPlatformPixmap(QPlatformPixmap::PixmapType); |
| |
| data->resize(width, height); |
| |
| return QPixmap(data); |
| } |
| |
| QPixmap rasterPixmap(const QSize &size) |
| { |
| return rasterPixmap(size.width(), size.height()); |
| } |
| |
| QPixmap rasterPixmap(const QImage &image) |
| { |
| QPlatformPixmap *data = |
| new QRasterPlatformPixmap(QPlatformPixmap::PixmapType); |
| |
| data->fromImage(image, Qt::AutoColor | Qt::NoFormatConversion); |
| |
| 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 drawPixmapImage_data_helper(bool); |
| 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).toLatin1().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::drawPixmapImage_data_helper(bool pixmaps) |
| { |
| 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(10, 10) |
| << 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", |
| "RGBx8888", |
| "RGBA8888", |
| "RGBA8888_pm", |
| "BGR30", |
| "A2BGR30_pm", |
| "RGB30", |
| "A2RGB30_pm", |
| "Alpha8", |
| "Grayscale8", |
| "RGBx64", |
| "RGBA64", |
| "RGBA64_pm", |
| }; |
| |
| const QImage::Format pixmapFormats[] = { |
| QImage::Format_RGB32, |
| QImage::Format_ARGB32_Premultiplied, |
| QImage::Format_RGB16, |
| QImage::Format_BGR30, |
| QImage::Format_Invalid |
| }; |
| |
| const QImage::Format targetImageFormats[] = { |
| QImage::Format_RGB32, |
| QImage::Format_ARGB32, |
| QImage::Format_ARGB32_Premultiplied, |
| QImage::Format_RGB16, |
| QImage::Format_ARGB8565_Premultiplied, |
| QImage::Format_RGBX8888, |
| QImage::Format_RGBA8888_Premultiplied, |
| QImage::Format_BGR30, |
| QImage::Format_A2RGB30_Premultiplied, |
| QImage::Format_Grayscale8, |
| QImage::Format_Invalid |
| }; |
| |
| const QImage::Format sourceImageFormats[] = { |
| QImage::Format_Indexed8, |
| QImage::Format_RGB32, |
| QImage::Format_ARGB32, |
| QImage::Format_ARGB32_Premultiplied, |
| QImage::Format_RGB16, |
| QImage::Format_RGB888, |
| QImage::Format_RGBX8888, |
| QImage::Format_RGBA8888, |
| QImage::Format_RGB30, |
| QImage::Format_Grayscale8, |
| QImage::Format_Invalid |
| }; |
| |
| const QImage::Format *targetFormats = pixmaps ? pixmapFormats : targetImageFormats; |
| for (; *targetFormats != QImage::Format_Invalid; ++targetFormats) { |
| const QImage::Format *sourceFormats = pixmaps ? pixmapFormats : sourceImageFormats; |
| for (; *sourceFormats != QImage::Format_Invalid; ++sourceFormats) { |
| for (const QSize &s : qAsConst(sizes)) { |
| for (int type=0; type<=3; ++type) { |
| QString name = QString::fromLatin1("%1 on %2, (%3x%4), %5") |
| .arg(formatNames[*sourceFormats]) |
| .arg(formatNames[*targetFormats]) |
| .arg(s.width()).arg(s.height()) |
| .arg(typeNames[type]); |
| QTest::newRow(name.toLatin1()) << *sourceFormats |
| << *targetFormats |
| << 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_data() |
| { |
| drawPixmapImage_data_helper(true); |
| } |
| |
| 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() |
| { |
| drawPixmapImage_data_helper(false); |
| } |
| |
| |
| 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; |
| case Primitive_Last_Primitive: 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 = qDegreesToRadians(angle); |
| 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 += .1f) |
| 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 += .1f) |
| 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" |