diff options
Diffstat (limited to 'tests/benchmarks/gui/painting/qtbench/benchmarktests.h')
-rw-r--r-- | tests/benchmarks/gui/painting/qtbench/benchmarktests.h | 800 |
1 files changed, 800 insertions, 0 deletions
diff --git a/tests/benchmarks/gui/painting/qtbench/benchmarktests.h b/tests/benchmarks/gui/painting/qtbench/benchmarktests.h new file mode 100644 index 0000000..8626ae7 --- /dev/null +++ b/tests/benchmarks/gui/painting/qtbench/benchmarktests.h @@ -0,0 +1,800 @@ +#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.setMaximumSize(m_size + QSize(10, 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.setMaximumSize(m_size + QSize(10, 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 |