From d54484122b7653ad1a96e7ef361c6250bb666f3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 8 Mar 2010 12:20:53 +0100 Subject: Added text benchmarks from qtbench to tests/benchmarks Reviewed-by: Gunnar Sletta --- tests/benchmarks/gui/painting/painting.pro | 3 +- .../gui/painting/qtbench/benchmarktests.h | 800 +++++++++++++++++++++ tests/benchmarks/gui/painting/qtbench/qtbench.pro | 6 + .../gui/painting/qtbench/tst_qtbench.cpp | 254 +++++++ 4 files changed, 1062 insertions(+), 1 deletion(-) create mode 100644 tests/benchmarks/gui/painting/qtbench/benchmarktests.h create mode 100644 tests/benchmarks/gui/painting/qtbench/qtbench.pro create mode 100644 tests/benchmarks/gui/painting/qtbench/tst_qtbench.cpp diff --git a/tests/benchmarks/gui/painting/painting.pro b/tests/benchmarks/gui/painting/painting.pro index 2c042b5..76c26c1 100644 --- a/tests/benchmarks/gui/painting/painting.pro +++ b/tests/benchmarks/gui/painting/painting.pro @@ -3,4 +3,5 @@ SUBDIRS = \ qpainter \ qregion \ qtransform \ - qtracebench + qtracebench \ + qtbench 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 +#include +#include +#include +#include +#include + +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) +# include +#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= 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; itransform(), 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 m_pixmaps; + int m_currentPixmap; + +#if QT_VERSION >= 0x040700 + int m_currentStaticText; + QList 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 0000000..91f416d --- /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 0000000..8eef472 --- /dev/null +++ b/tests/benchmarks/gui/painting/qtbench/tst_qtbench.cpp @@ -0,0 +1,254 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 + +#include + +#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 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("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 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(benchmark); +} + +void tst_QtBench::qtBench() +{ + QFETCH(void *, benchmark); + + BenchWidget widget(reinterpret_cast(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" -- cgit v0.12 From 7b500ed543bb86429ef6fdb82b103784d6cc6a0c Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Fri, 5 Mar 2010 16:59:01 +0100 Subject: Fixed vector-effect property output from QSvgGenerator. The vector-effect property is not inherited by default, so it must be set on each item with a stroke. It is not sufficient to set it on G nodes. Task-number: QTBUG-8733 Reviewed-by: Trond --- src/svg/qsvggenerator.cpp | 27 +++++++++------------- .../referenceSvgs/fileName_output.svg | 6 ++--- .../referenceSvgs/radial_gradient.svg | 10 ++++---- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/svg/qsvggenerator.cpp b/src/svg/qsvggenerator.cpp index 4a8fc0b..cb9086c 100644 --- a/src/svg/qsvggenerator.cpp +++ b/src/svg/qsvggenerator.cpp @@ -310,7 +310,6 @@ public: { *d_func()->stream << QLatin1String("fill=\"none\" "); *d_func()->stream << QLatin1String("stroke=\"black\" "); - *d_func()->stream << QLatin1String("vector-effect=\"non-scaling-stroke\" "); *d_func()->stream << QLatin1String("stroke-width=\"1\" "); *d_func()->stream << QLatin1String("fill-rule=\"evenodd\" "); *d_func()->stream << QLatin1String("stroke-linecap=\"square\" "); @@ -380,13 +379,10 @@ public: break; } - if (spen.widthF() == 0) { - width = QLatin1String("1"); - stream() << "vector-effect=\"non-scaling-stroke\" "; - } + if (spen.widthF() == 0) + stream() <<"stroke-width=\"1\" "; else - width = QString::number(spen.widthF()); - stream() <<"stroke-width=\""<stream << "stream << "\"nonzero\" "; - - *d->stream << "d=\""; + *d->stream << "pen().isCosmetic() ? "non-scaling-stroke" : "none") + << "\" fill-rule=\"" + << (p.fillRule() == Qt::OddEvenFill ? "evenodd" : "nonzero") + << "\" d=\""; for (int i=0; ipen().isCosmetic() ? "non-scaling-stroke" : "none") + << "\" points=\""; for (int i = 0; i < pointCount; ++i) { const QPointF &pt = points[i]; stream() << pt.x() << ',' << pt.y() << ' '; diff --git a/tests/auto/qsvggenerator/referenceSvgs/fileName_output.svg b/tests/auto/qsvggenerator/referenceSvgs/fileName_output.svg index 99926b3..f1f9e35 100644 --- a/tests/auto/qsvggenerator/referenceSvgs/fileName_output.svg +++ b/tests/auto/qsvggenerator/referenceSvgs/fileName_output.svg @@ -4,12 +4,12 @@ Generated with Qt - + - + diff --git a/tests/auto/qsvggenerator/referenceSvgs/radial_gradient.svg b/tests/auto/qsvggenerator/referenceSvgs/radial_gradient.svg index f61dd40..84afbf3 100644 --- a/tests/auto/qsvggenerator/referenceSvgs/radial_gradient.svg +++ b/tests/auto/qsvggenerator/referenceSvgs/radial_gradient.svg @@ -13,18 +13,18 @@ - + - + - + -- cgit v0.12 From ea9f2aeba6f18d19d6a82b3a829373ec032af14f Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Mon, 8 Mar 2010 16:15:44 +0100 Subject: Fixed bounds calculation in QtSvg. This commit fixes an auto-test failure after fixing QTBUG-8733. The calculated element bounds should now be much tighter and respect the width of non-cosmetic pens. Task-number: QTBUG-8733 Reviewed-by: Trond --- src/svg/qsvggraphics.cpp | 178 +++++++++------------------ src/svg/qsvggraphics_p.h | 40 +++--- src/svg/qsvgnode.cpp | 65 ++++++---- src/svg/qsvgnode_p.h | 14 ++- src/svg/qsvgstructure.cpp | 13 +- src/svg/qsvgstructure_p.h | 3 +- src/svg/qsvgstyle.cpp | 46 +++---- src/svg/qsvgstyle_p.h | 28 ++--- src/svg/qsvgtinydocument.cpp | 7 +- src/svg/qsvgtinydocument_p.h | 5 +- tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp | 31 +++++ 11 files changed, 204 insertions(+), 226 deletions(-) diff --git a/src/svg/qsvggraphics.cpp b/src/svg/qsvggraphics.cpp index cd0e1ac..a29764a 100644 --- a/src/svg/qsvggraphics.cpp +++ b/src/svg/qsvggraphics.cpp @@ -78,33 +78,29 @@ void QSvgAnimation::draw(QPainter *, QSvgExtraStates &) qWarning(" no implemented"); } -static inline QRectF boundsOnStroke(const QPainterPath &path, qreal width) +static inline QRectF boundsOnStroke(QPainter *p, const QPainterPath &path, qreal width) { QPainterPathStroker stroker; stroker.setWidth(width); QPainterPath stroke = stroker.createStroke(path); - return stroke.boundingRect(); + return p->transform().map(stroke).boundingRect(); } -QSvgCircle::QSvgCircle(QSvgNode *parent, const QRectF &rect) +QSvgEllipse::QSvgEllipse(QSvgNode *parent, const QRectF &rect) : QSvgNode(parent), m_bounds(rect) { } -QRectF QSvgCircle::bounds() const +QRectF QSvgEllipse::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_bounds; - else { - QPainterPath path; - path.addRect(m_bounds); - return boundsOnStroke(path, sw); - } + QPainterPath path; + path.addEllipse(m_bounds); + qreal sw = strokeWidth(p); + return qFuzzyIsNull(sw) ? p->transform().map(path).boundingRect() : boundsOnStroke(p, path, sw); } -void QSvgCircle::draw(QPainter *p, QSvgExtraStates &states) +void QSvgEllipse::draw(QPainter *p, QSvgExtraStates &states) { applyStyle(p, states); QT_SVG_DRAW_SHAPE(p->drawEllipse(m_bounds)); @@ -112,9 +108,8 @@ void QSvgCircle::draw(QPainter *p, QSvgExtraStates &states) } QSvgArc::QSvgArc(QSvgNode *parent, const QPainterPath &path) - : QSvgNode(parent), cubic(path) + : QSvgNode(parent), m_path(path) { - m_cachedBounds = path.boundingRect(); } void QSvgArc::draw(QPainter *p, QSvgExtraStates &states) @@ -123,36 +118,12 @@ void QSvgArc::draw(QPainter *p, QSvgExtraStates &states) if (p->pen().widthF() != 0) { qreal oldOpacity = p->opacity(); p->setOpacity(oldOpacity * states.strokeOpacity); - p->drawPath(cubic); + p->drawPath(m_path); p->setOpacity(oldOpacity); } revertStyle(p, states); } -QSvgEllipse::QSvgEllipse(QSvgNode *parent, const QRectF &rect) - : QSvgNode(parent), m_bounds(rect) -{ -} - -QRectF QSvgEllipse::bounds() const -{ - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_bounds; - else { - QPainterPath path; - path.addEllipse(m_bounds); - return boundsOnStroke(path, sw); - } -} - -void QSvgEllipse::draw(QPainter *p, QSvgExtraStates &states) -{ - applyStyle(p, states); - QT_SVG_DRAW_SHAPE(p->drawEllipse(m_bounds)); - revertStyle(p, states); -} - QSvgImage::QSvgImage(QSvgNode *parent, const QImage &image, const QRect &bounds) : QSvgNode(parent), m_image(image), @@ -173,7 +144,7 @@ void QSvgImage::draw(QPainter *p, QSvgExtraStates &states) QSvgLine::QSvgLine(QSvgNode *parent, const QLineF &line) - : QSvgNode(parent), m_bounds(line) + : QSvgNode(parent), m_line(line) { } @@ -184,7 +155,7 @@ void QSvgLine::draw(QPainter *p, QSvgExtraStates &states) if (p->pen().widthF() != 0) { qreal oldOpacity = p->opacity(); p->setOpacity(oldOpacity * states.strokeOpacity); - p->drawLine(m_bounds); + p->drawLine(m_line); p->setOpacity(oldOpacity); } revertStyle(p, states); @@ -203,19 +174,11 @@ void QSvgPath::draw(QPainter *p, QSvgExtraStates &states) revertStyle(p, states); } -QRectF QSvgPath::bounds() const +QRectF QSvgPath::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) { - if (m_cachedBounds.isNull()) - //m_cachedBounds = m_path.controlPointRect(); - m_cachedBounds = m_path.boundingRect(); - - return m_cachedBounds; - } - else { - return boundsOnStroke(m_path, sw); - } + qreal sw = strokeWidth(p); + return qFuzzyIsNull(sw) ? p->transform().map(m_path).boundingRect() + : boundsOnStroke(p, m_path, sw); } QSvgPolygon::QSvgPolygon(QSvgNode *parent, const QPolygonF &poly) @@ -223,15 +186,15 @@ QSvgPolygon::QSvgPolygon(QSvgNode *parent, const QPolygonF &poly) { } -QRectF QSvgPolygon::bounds() const +QRectF QSvgPolygon::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_poly.boundingRect(); - else { + qreal sw = strokeWidth(p); + if (qFuzzyIsNull(sw)) { + return p->transform().map(m_poly).boundingRect(); + } else { QPainterPath path; path.addPolygon(m_poly); - return boundsOnStroke(path, sw); + return boundsOnStroke(p, path, sw); } } @@ -274,15 +237,15 @@ QSvgRect::QSvgRect(QSvgNode *node, const QRectF &rect, int rx, int ry) { } -QRectF QSvgRect::bounds() const +QRectF QSvgRect::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_rect; - else { + qreal sw = strokeWidth(p); + if (qFuzzyIsNull(sw)) { + return p->transform().mapRect(m_rect); + } else { QPainterPath path; path.addRect(m_rect); - return boundsOnStroke(path, sw); + return boundsOnStroke(p, path, sw); } } @@ -322,7 +285,7 @@ void QSvgText::setTextArea(const QSizeF &size) m_type = TEXTAREA; } -//QRectF QSvgText::bounds() const {} +//QRectF QSvgText::bounds(QPainter *p, QSvgExtraStates &) const {} void QSvgText::draw(QPainter *p, QSvgExtraStates &states) { @@ -593,80 +556,57 @@ QSvgNode::Type QSvgVideo::type() const return VIDEO; } -QRectF QSvgUse::bounds() const -{ - if (m_link && m_bounds.isEmpty()) { - m_bounds = m_link->bounds(); - m_bounds = QRectF(m_bounds.x()+m_start.x(), - m_bounds.y()+m_start.y(), - m_bounds.width(), - m_bounds.height()); - - return m_bounds; - } - return m_bounds; -} - -QRectF QSvgUse::transformedBounds(const QTransform &transform) const +QRectF QSvgUse::bounds(QPainter *p, QSvgExtraStates &states) const { QRectF bounds; - QTransform t = transform; - - if (m_link) { - QSvgTransformStyle *transStyle = m_style.transform; - if (transStyle) { - t = transStyle->qtransform() * t; - } - t.translate(m_start.x(), m_start.y()); - - bounds = m_link->transformedBounds(t); - - return bounds; + if (m_link) { + p->translate(m_start); + bounds = m_link->transformedBounds(p, states); + p->translate(-m_start); } return bounds; } -QRectF QSvgPolyline::bounds() const +QRectF QSvgPolyline::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_poly.boundingRect(); - else { + qreal sw = strokeWidth(p); + if (qFuzzyIsNull(sw)) { + return p->transform().map(m_poly).boundingRect(); + } else { QPainterPath path; path.addPolygon(m_poly); - return boundsOnStroke(path, sw); + return boundsOnStroke(p, path, sw); } } -QRectF QSvgArc::bounds() const +QRectF QSvgArc::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); - if (qFuzzyIsNull(sw)) - return m_cachedBounds; - else { - return boundsOnStroke(cubic, sw); - } + qreal sw = strokeWidth(p); + return qFuzzyIsNull(sw) ? p->transform().map(m_path).boundingRect() + : boundsOnStroke(p, m_path, sw); } -QRectF QSvgImage::bounds() const +QRectF QSvgImage::bounds(QPainter *p, QSvgExtraStates &) const { - return m_bounds; + return p->transform().mapRect(m_bounds); } -QRectF QSvgLine::bounds() const +QRectF QSvgLine::bounds(QPainter *p, QSvgExtraStates &) const { - qreal sw = strokeWidth(); + qreal sw = strokeWidth(p); if (qFuzzyIsNull(sw)) { - qreal minX = qMin(m_bounds.x1(), m_bounds.x2()); - qreal minY = qMin(m_bounds.y1(), m_bounds.y2()); - qreal maxX = qMax(m_bounds.x1(), m_bounds.x2()); - qreal maxY = qMax(m_bounds.y1(), m_bounds.y2()); - return QRectF(minX, minY, maxX-minX, maxY-minY); + QPointF p1 = p->transform().map(m_line.p1()); + QPointF p2 = p->transform().map(m_line.p2()); + qreal minX = qMin(p1.x(), p2.x()); + qreal minY = qMin(p1.y(), p2.y()); + qreal maxX = qMax(p1.x(), p2.x()); + qreal maxY = qMax(p1.y(), p2.y()); + return QRectF(minX, minY, maxX - minX, maxY - minY); } else { QPainterPath path; - path.moveTo(m_bounds.x1(), m_bounds.y1()); - path.lineTo(m_bounds.x2(), m_bounds.y2()); - return boundsOnStroke(path, sw); + path.moveTo(m_line.p1()); + path.lineTo(m_line.p2()); + return boundsOnStroke(p, path, sw); } } diff --git a/src/svg/qsvggraphics_p.h b/src/svg/qsvggraphics_p.h index ca06777..fdc770a 100644 --- a/src/svg/qsvggraphics_p.h +++ b/src/svg/qsvggraphics_p.h @@ -80,32 +80,27 @@ public: QSvgArc(QSvgNode *parent, const QPainterPath &path); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: - QPainterPath cubic; - QRectF m_cachedBounds; + QPainterPath m_path; }; -class QSvgCircle : public QSvgNode +class QSvgEllipse : public QSvgNode { public: - QSvgCircle(QSvgNode *parent, const QRectF &rect); + QSvgEllipse(QSvgNode *parent, const QRectF &rect); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QRectF m_bounds; }; -class QSvgEllipse : public QSvgNode +class QSvgCircle : public QSvgEllipse { public: - QSvgEllipse(QSvgNode *parent, const QRectF &rect); - virtual void draw(QPainter *p, QSvgExtraStates &states); + QSvgCircle(QSvgNode *parent, const QRectF &rect) : QSvgEllipse(parent, rect) { } virtual Type type() const; - virtual QRectF bounds() const; -private: - QRectF m_bounds; }; class QSvgImage : public QSvgNode @@ -115,7 +110,7 @@ public: const QRect &bounds); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QImage m_image; QRect m_bounds; @@ -127,9 +122,9 @@ public: QSvgLine(QSvgNode *parent, const QLineF &line); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: - QLineF m_bounds; + QLineF m_line; }; class QSvgPath : public QSvgNode @@ -138,14 +133,13 @@ public: QSvgPath(QSvgNode *parent, const QPainterPath &qpath); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; QPainterPath *qpath() { return &m_path; } private: QPainterPath m_path; - mutable QRectF m_cachedBounds; }; class QSvgPolygon : public QSvgNode @@ -154,7 +148,7 @@ public: QSvgPolygon(QSvgNode *parent, const QPolygonF &poly); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QPolygonF m_poly; }; @@ -165,7 +159,7 @@ public: QSvgPolyline(QSvgNode *parent, const QPolygonF &poly); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QPolygonF m_poly; }; @@ -176,7 +170,7 @@ public: QSvgRect(QSvgNode *paren, const QRectF &rect, int rx=0, int ry=0); virtual Type type() const; virtual void draw(QPainter *p, QSvgExtraStates &states); - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QRectF m_rect; int m_rx, m_ry; @@ -205,7 +199,7 @@ public: void addLineBreak() {m_tspans.append(LINEBREAK);} void setWhitespaceMode(WhitespaceMode mode) {m_mode = mode;} - //virtual QRectF bounds() const; + //virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: static QSvgTspan * const LINEBREAK; @@ -248,13 +242,11 @@ public: QSvgUse(const QPointF &start, QSvgNode *parent, QSvgNode *link); virtual void draw(QPainter *p, QSvgExtraStates &states); virtual Type type() const; - virtual QRectF bounds() const; - virtual QRectF transformedBounds(const QTransform &transform) const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; private: QSvgNode *m_link; QPointF m_start; - mutable QRectF m_bounds; }; class QSvgVideo : public QSvgNode diff --git a/src/svg/qsvgnode.cpp b/src/svg/qsvgnode.cpp index 86f2af5..f6bc1c0 100644 --- a/src/svg/qsvgnode.cpp +++ b/src/svg/qsvgnode.cpp @@ -45,6 +45,7 @@ #ifndef QT_NO_SVG #include "qdebug.h" +#include "qstack.h" QT_BEGIN_NAMESPACE @@ -114,12 +115,12 @@ void QSvgNode::appendStyleProperty(QSvgStyleProperty *prop, const QString &id) } } -void QSvgNode::applyStyle(QPainter *p, QSvgExtraStates &states) +void QSvgNode::applyStyle(QPainter *p, QSvgExtraStates &states) const { - m_style.apply(p, bounds(), this, states); + m_style.apply(p, this, states); } -void QSvgNode::revertStyle(QPainter *p, QSvgExtraStates &states) +void QSvgNode::revertStyle(QPainter *p, QSvgExtraStates &states) const { m_style.revert(p, states); } @@ -195,11 +196,40 @@ QSvgFillStyleProperty * QSvgNode::styleProperty(const QString &id) const return doc ? doc->namedStyle(rid) : 0; } -QRectF QSvgNode::bounds() const +QRectF QSvgNode::bounds(QPainter *, QSvgExtraStates &) const { return QRectF(0, 0, 0, 0); } +QRectF QSvgNode::transformedBounds() const +{ + if (!m_cachedBounds.isEmpty()) + return m_cachedBounds; + + QImage dummy(1, 1, QImage::Format_RGB32); + QPainter p(&dummy); + QSvgExtraStates states; + + QPen pen(Qt::NoBrush, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin); + pen.setMiterLimit(4); + p.setPen(pen); + + QStack parentApplyStack; + QSvgNode *parent = m_parent; + while (parent) { + parentApplyStack.push(parent); + parent = parent->parent(); + } + + for (int i = parentApplyStack.size() - 1; i >= 0; --i) + parentApplyStack[i]->applyStyle(&p, states); + + p.setWorldTransform(QTransform()); + + m_cachedBounds = transformedBounds(&p, states); + return m_cachedBounds; +} + QSvgTinyDocument * QSvgNode::document() const { QSvgTinyDocument *doc = 0; @@ -274,19 +304,11 @@ void QSvgNode::setVisible(bool visible) m_visible = visible; } -QRectF QSvgNode::transformedBounds(const QTransform &transform) const +QRectF QSvgNode::transformedBounds(QPainter *p, QSvgExtraStates &states) const { - QTransform t = transform; - - QSvgTransformStyle *transStyle = m_style.transform; - if (transStyle) { - t = transStyle->qtransform() * t; - } - - QRectF rect = bounds(); - - rect = t.mapRect(rect); - + applyStyle(p, states); + QRectF rect = bounds(p, states); + revertStyle(p, states); return rect; } @@ -310,15 +332,12 @@ QSvgNode::DisplayMode QSvgNode::displayMode() const return m_displayMode; } -qreal QSvgNode::strokeWidth() const +qreal QSvgNode::strokeWidth(QPainter *p) { - QSvgStrokeStyle *stroke = static_cast( - styleProperty(QSvgStyleProperty::STROKE)); - if (!stroke) - return 0; - if (stroke->stroke().brush().style() == Qt::NoBrush) + QPen pen = p->pen(); + if (pen.style() == Qt::NoPen || pen.brush().style() == Qt::NoBrush || pen.isCosmetic()) return 0; - return stroke->width(); + return pen.widthF(); } QT_END_NAMESPACE diff --git a/src/svg/qsvgnode_p.h b/src/svg/qsvgnode_p.h index 15466f2..a34c7c0 100644 --- a/src/svg/qsvgnode_p.h +++ b/src/svg/qsvgnode_p.h @@ -118,16 +118,17 @@ public: QSvgNode *parent() const; void appendStyleProperty(QSvgStyleProperty *prop, const QString &id); - void applyStyle(QPainter *p, QSvgExtraStates &states); - void revertStyle(QPainter *p, QSvgExtraStates &states); + void applyStyle(QPainter *p, QSvgExtraStates &states) const; + void revertStyle(QPainter *p, QSvgExtraStates &states) const; QSvgStyleProperty *styleProperty(QSvgStyleProperty::Type type) const; QSvgFillStyleProperty *styleProperty(const QString &id) const; QSvgTinyDocument *document() const; virtual Type type() const =0; - virtual QRectF bounds() const; - virtual QRectF transformedBounds(const QTransform &transform) const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; + virtual QRectF transformedBounds(QPainter *p, QSvgExtraStates &states) const; + QRectF transformedBounds() const; void setRequiredFeatures(const QStringList &lst); const QStringList & requiredFeatures() const; @@ -156,9 +157,9 @@ public: QString xmlClass() const; void setXmlClass(const QString &str); protected: - QSvgStyle m_style; + mutable QSvgStyle m_style; - qreal strokeWidth() const; + static qreal strokeWidth(QPainter *p); private: QSvgNode *m_parent; @@ -174,6 +175,7 @@ private: QString m_class; DisplayMode m_displayMode; + mutable QRectF m_cachedBounds; friend class QSvgTinyDocument; }; diff --git a/src/svg/qsvgstructure.cpp b/src/svg/qsvgstructure.cpp index 34426b7..db5cb9e 100644 --- a/src/svg/qsvgstructure.cpp +++ b/src/svg/qsvgstructure.cpp @@ -357,15 +357,12 @@ void QSvgSwitch::init() m_systemLanguagePrefix = m_systemLanguage.mid(0, idx); } -QRectF QSvgStructureNode::bounds() const +QRectF QSvgStructureNode::bounds(QPainter *p, QSvgExtraStates &states) const { - if (m_bounds.isEmpty()) { - foreach(QSvgNode *node, m_renderers) { - m_bounds |= node->transformedBounds(QTransform()); - } - } - - return m_bounds; + QRectF bounds; + foreach(QSvgNode *node, m_renderers) + bounds |= node->transformedBounds(p, states); + return bounds; } QSvgNode * QSvgStructureNode::previousSiblingNode(QSvgNode *n) const diff --git a/src/svg/qsvgstructure_p.h b/src/svg/qsvgstructure_p.h index fd6eb0a..dd82fc0 100644 --- a/src/svg/qsvgstructure_p.h +++ b/src/svg/qsvgstructure_p.h @@ -74,14 +74,13 @@ public: ~QSvgStructureNode(); QSvgNode *scopeNode(const QString &id) const; void addChild(QSvgNode *child, const QString &id); - virtual QRectF bounds() const; + virtual QRectF bounds(QPainter *p, QSvgExtraStates &states) const; QSvgNode *previousSiblingNode(QSvgNode *n) const; QList renderers() const { return m_renderers; } protected: QList m_renderers; QHash m_scope; QList m_linkedScopes; - mutable QRectF m_bounds; }; class QSvgG : public QSvgStructureNode diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp index 2b12c49..0d1bad9 100644 --- a/src/svg/qsvgstyle.cpp +++ b/src/svg/qsvgstyle.cpp @@ -73,7 +73,7 @@ QSvgStyleProperty::~QSvgStyleProperty() { } -void QSvgFillStyleProperty::apply(QPainter *, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgFillStyleProperty::apply(QPainter *, const QSvgNode *, QSvgExtraStates &) { Q_ASSERT(!"This should not be called!"); } @@ -89,7 +89,7 @@ QSvgQualityStyle::QSvgQualityStyle(int color) { } -void QSvgQualityStyle::apply(QPainter *, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgQualityStyle::apply(QPainter *, const QSvgNode *, QSvgExtraStates &) { } @@ -136,7 +136,7 @@ void QSvgFillStyle::setBrush(QBrush brush) m_fillSet = 1; } -void QSvgFillStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &states) +void QSvgFillStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &states) { m_oldFill = p->brush(); m_oldFillRule = states.fillRule; @@ -169,7 +169,7 @@ QSvgViewportFillStyle::QSvgViewportFillStyle(const QBrush &brush) { } -void QSvgViewportFillStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgViewportFillStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &) { m_oldFill = p->brush(); p->setBrush(m_viewportFill); @@ -224,7 +224,7 @@ int QSvgFontStyle::SVGToQtWeight(int weight) { return QFont::Normal; } -void QSvgFontStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &states) +void QSvgFontStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &states) { m_oldQFont = p->font(); m_oldSvgFont = states.svgFont; @@ -292,7 +292,7 @@ QSvgStrokeStyle::QSvgStrokeStyle() { } -void QSvgStrokeStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &states) +void QSvgStrokeStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &states) { m_oldStroke = p->pen(); m_oldStrokeOpacity = states.strokeOpacity; @@ -443,7 +443,7 @@ QSvgTransformStyle::QSvgTransformStyle(const QTransform &trans) { } -void QSvgTransformStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgTransformStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &) { m_oldWorldTransform = p->worldTransform(); p->setWorldTransform(m_transform, true); @@ -501,7 +501,7 @@ QSvgCompOpStyle::QSvgCompOpStyle(QPainter::CompositionMode mode) } -void QSvgCompOpStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgCompOpStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &) { m_oldMode = p->compositionMode(); p->setCompositionMode(m_mode); @@ -521,34 +521,34 @@ QSvgStyle::~QSvgStyle() { } -void QSvgStyle::apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtraStates &states) +void QSvgStyle::apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) { if (quality) { - quality->apply(p, rect, node, states); + quality->apply(p, node, states); } if (fill) { - fill->apply(p, rect, node, states); + fill->apply(p, node, states); } if (viewportFill) { - viewportFill->apply(p, rect, node, states); + viewportFill->apply(p, node, states); } if (font) { - font->apply(p, rect, node, states); + font->apply(p, node, states); } if (stroke) { - stroke->apply(p, rect, node, states); + stroke->apply(p, node, states); } if (transform) { - transform->apply(p, rect, node, states); + transform->apply(p, node, states); } if (animateColor) { - animateColor->apply(p, rect, node, states); + animateColor->apply(p, node, states); } //animated transforms have to be applied @@ -572,16 +572,16 @@ void QSvgStyle::apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtra // Apply the animateTransforms after and including the last one with additive="replace". for (; itr != animateTransforms.constEnd(); ++itr) { if ((*itr)->animActive(totalTimeElapsed)) - (*itr)->apply(p, rect, node, states); + (*itr)->apply(p, node, states); } } if (opacity) { - opacity->apply(p, rect, node, states); + opacity->apply(p, node, states); } if (compop) { - compop->apply(p, rect, node, states); + compop->apply(p, node, states); } } @@ -655,7 +655,7 @@ void QSvgAnimateTransform::setArgs(TransformType type, Additive additive, const m_count = args.count() / 3; } -void QSvgAnimateTransform::apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &) +void QSvgAnimateTransform::apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &) { m_oldWorldTransform = p->worldTransform(); resolveMatrix(node); @@ -669,7 +669,7 @@ void QSvgAnimateTransform::revert(QPainter *p, QSvgExtraStates &) m_transformApplied = false; } -void QSvgAnimateTransform::resolveMatrix(QSvgNode *node) +void QSvgAnimateTransform::resolveMatrix(const QSvgNode *node) { static const qreal deg2rad = qreal(0.017453292519943295769); qreal totalTimeElapsed = node->document()->currentElapsed(); @@ -834,7 +834,7 @@ void QSvgAnimateColor::setRepeatCount(qreal repeatCount) m_repeatCount = repeatCount; } -void QSvgAnimateColor::apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &) +void QSvgAnimateColor::apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &) { qreal totalTimeElapsed = node->document()->currentElapsed(); if (totalTimeElapsed < m_from || m_finished) @@ -912,7 +912,7 @@ QSvgOpacityStyle::QSvgOpacityStyle(qreal opacity) } -void QSvgOpacityStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) +void QSvgOpacityStyle::apply(QPainter *p, const QSvgNode *, QSvgExtraStates &) { m_oldOpacity = p->opacity(); p->setOpacity(m_opacity * m_oldOpacity); diff --git a/src/svg/qsvgstyle_p.h b/src/svg/qsvgstyle_p.h index 202de93..af3b4e5 100644 --- a/src/svg/qsvgstyle_p.h +++ b/src/svg/qsvgstyle_p.h @@ -172,7 +172,7 @@ public: }; public: virtual ~QSvgStyleProperty(); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states) =0; + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states) = 0; virtual void revert(QPainter *p, QSvgExtraStates &states) =0; virtual Type type() const=0; }; @@ -181,7 +181,7 @@ class QSvgFillStyleProperty : public QSvgStyleProperty { public: virtual QBrush brush(QPainter *p, QSvgExtraStates &states) = 0; - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); }; @@ -189,7 +189,7 @@ class QSvgQualityStyle : public QSvgStyleProperty { public: QSvgQualityStyle(int color); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; private: @@ -221,7 +221,7 @@ class QSvgOpacityStyle : public QSvgStyleProperty { public: QSvgOpacityStyle(qreal opacity); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; private: @@ -233,7 +233,7 @@ class QSvgFillStyle : public QSvgStyleProperty { public: QSvgFillStyle(); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -306,7 +306,7 @@ class QSvgViewportFillStyle : public QSvgStyleProperty { public: QSvgViewportFillStyle(const QBrush &brush); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -330,7 +330,7 @@ public: QSvgFontStyle(QSvgFont *font, QSvgTinyDocument *doc); QSvgFontStyle(); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -410,7 +410,7 @@ class QSvgStrokeStyle : public QSvgStyleProperty { public: QSvgStrokeStyle(); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -617,7 +617,7 @@ class QSvgTransformStyle : public QSvgStyleProperty { public: QSvgTransformStyle(const QTransform &transform); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -654,7 +654,7 @@ public: void setArgs(TransformType type, Additive additive, const QVector &args); void setFreeze(bool freeze); void setRepeatCount(qreal repeatCount); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; QSvgAnimateTransform::Additive additiveType() const @@ -688,7 +688,7 @@ public: } protected: - void resolveMatrix(QSvgNode *node); + void resolveMatrix(const QSvgNode *node); private: qreal m_from, m_to, m_by; qreal m_totalRunningTime; @@ -712,7 +712,7 @@ public: void setArgs(bool fill, const QList &colors); void setFreeze(bool freeze); void setRepeatCount(qreal repeatCount); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; private: @@ -732,7 +732,7 @@ class QSvgCompOpStyle : public QSvgStyleProperty { public: QSvgCompOpStyle(QPainter::CompositionMode mode); - virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); + virtual void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; @@ -766,7 +766,7 @@ public: {} ~QSvgStyle(); - void apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtraStates &states); + void apply(QPainter *p, const QSvgNode *node, QSvgExtraStates &states); void revert(QPainter *p, QSvgExtraStates &states); QSvgRefCounter quality; QSvgRefCounter fill; diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp index 17618f7..b21b99f 100644 --- a/src/svg/qsvgtinydocument.cpp +++ b/src/svg/qsvgtinydocument.cpp @@ -277,7 +277,7 @@ void QSvgTinyDocument::draw(QPainter *p, const QString &id, p->save(); - const QRectF elementBounds = node->transformedBounds(QTransform()); + const QRectF elementBounds = node->transformedBounds(); mapSourceToTarget(p, bounds, elementBounds); QTransform originalTransform = p->worldTransform(); @@ -299,7 +299,7 @@ void QSvgTinyDocument::draw(QPainter *p, const QString &id, for (int i = parentApplyStack.size() - 1; i >= 0; --i) parentApplyStack[i]->applyStyle(p, m_states); - + // Reset the world transform so that our parents don't affect // the position QTransform currentTransform = p->worldTransform(); @@ -432,8 +432,7 @@ QRectF QSvgTinyDocument::boundsOnElement(const QString &id) const const QSvgNode *node = scopeNode(id); if (!node) node = this; - - return node->transformedBounds(QTransform()); + return node->transformedBounds(); } bool QSvgTinyDocument::elementExists(const QString &id) const diff --git a/src/svg/qsvgtinydocument_p.h b/src/svg/qsvgtinydocument_p.h index c03c798..3b40770 100644 --- a/src/svg/qsvgtinydocument_p.h +++ b/src/svg/qsvgtinydocument_p.h @@ -173,9 +173,8 @@ inline bool QSvgTinyDocument::heightPercent() const inline QRectF QSvgTinyDocument::viewBox() const { - if (m_viewBox.isNull()) { - m_viewBox = transformedBounds(QTransform()); - } + if (m_viewBox.isNull()) + m_viewBox = transformedBounds(); return m_viewBox; } diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp index 16dd2b4..106fd8c 100644 --- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp @@ -74,6 +74,7 @@ private slots: void nestedQXmlStreamReader() const; void stylePropagation() const; void matrixForElement() const; + void boundsOnElement() const; void gradientStops() const; void gradientRefs(); void fillRule(); @@ -470,6 +471,36 @@ void tst_QSvgRenderer::matrixForElement() const compareTransforms(QTransform(painter.worldMatrix()), QTransform(renderer.matrixForElement(QLatin1String("firkant")))); } +void tst_QSvgRenderer::boundsOnElement() const +{ + QByteArray data("" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""); + + qreal sqrt2 = qSqrt(2); + QSvgRenderer renderer(data); + QCOMPARE(renderer.boundsOnElement(QLatin1String("sjokade")), QRectF(-10 * sqrt2, -10 * sqrt2, 20 * sqrt2, 20 * sqrt2)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("kaviar")), QRectF(-10 * sqrt2, -10 * sqrt2, 20 * sqrt2, 20 * sqrt2)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("nugatti")), QRectF(-11, -11, 22, 22)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("nutella")), QRectF(-10 * sqrt2, -10 * sqrt2, 20 * sqrt2, 20 * sqrt2)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("baconost")), QRectF(-10 * sqrt2, -10 * sqrt2, 20 * sqrt2, 20 * sqrt2)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("hapaa")), QRectF(-13, -9, 22, 22)); + QCOMPARE(renderer.boundsOnElement(QLatin1String("prim")), QRectF(-10 * sqrt2 - 3, -10 * sqrt2 + 1, 20 * sqrt2, 20 * sqrt2)); +} + void tst_QSvgRenderer::gradientStops() const { { -- cgit v0.12 From 42233381569dccd6fd23f2a112b9eac758093afa Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 9 Mar 2010 17:13:52 +1000 Subject: Fix qdeclarativevaluetype::font() autotest --- .../qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp b/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp index 51f9a07..eba83ce 100644 --- a/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp +++ b/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp @@ -314,8 +314,17 @@ void tst_qdeclarativevaluetypes::font() font.setLetterSpacing(QFont::AbsoluteSpacing, 9.7); font.setWordSpacing(11.2); - QEXPECT_FAIL("", "QT-2920", Continue); - QCOMPARE(object->font(), font); + QFont f = object->font(); + QCOMPARE(f.family(), font.family()); + QCOMPARE(f.bold(), font.bold()); + QCOMPARE(f.weight(), font.weight()); + QCOMPARE(f.italic(), font.italic()); + QCOMPARE(f.underline(), font.underline()); + QCOMPARE(f.strikeOut(), font.strikeOut()); + QCOMPARE(f.pointSize(), font.pointSize()); + QCOMPARE(f.capitalization(), font.capitalization()); + QCOMPARE(f.letterSpacing(), font.letterSpacing()); + QCOMPARE(f.wordSpacing(), font.wordSpacing()); delete object; } -- cgit v0.12 From f7fe4701713aff5f5af146fafbb38fa852ebde33 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 9 Mar 2010 09:32:12 +0100 Subject: Add license header --- .../gui/painting/qtbench/benchmarktests.h | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/benchmarks/gui/painting/qtbench/benchmarktests.h b/tests/benchmarks/gui/painting/qtbench/benchmarktests.h index 8626ae7..362d121 100644 --- a/tests/benchmarks/gui/painting/qtbench/benchmarktests.h +++ b/tests/benchmarks/gui/painting/qtbench/benchmarktests.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 -- cgit v0.12 From 3b58b103bfa2e2b9bb12a042cbba36fb0a1baf9f Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 9 Mar 2010 11:58:40 +0100 Subject: QTreeView: let the dataChanged signal refresh the hasChildren attribute. That is required for the Locals & Watchers view in Creator. Task-number: QTBUG-7115 Reviewed-by: Thierry --- src/gui/itemviews/qtreeview.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 1145235..78184a9 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -679,16 +679,20 @@ void QTreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &botto d->defaultItemHeight = indexRowSizeHint(topLeft); bool sizeChanged = false; if (topViewIndex != -1) { - if (topLeft == bottomRight) { + if (topLeft.row() == bottomRight.row()) { int oldHeight = d->itemHeight(topViewIndex); d->invalidateHeightCache(topViewIndex); sizeChanged = (oldHeight != d->itemHeight(topViewIndex)); + if (topLeft.column() == 0) + d->viewItems[topViewIndex].hasChildren = d->hasVisibleChildren(topLeft); } else { int bottomViewIndex = d->viewIndex(bottomRight); for (int i = topViewIndex; i <= bottomViewIndex; ++i) { int oldHeight = d->itemHeight(i); d->invalidateHeightCache(i); sizeChanged |= (oldHeight != d->itemHeight(i)); + if (topLeft.column() == 0) + d->viewItems[i].hasChildren = d->hasVisibleChildren(d->viewItems.at(i).index); } } } -- cgit v0.12 From 9cf0e75b2b73a59a65edb640b62a6838f31a8a1f Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 9 Mar 2010 12:15:53 +0100 Subject: Probably fix compile should fix the current failure when building on windows. --- src/declarative/graphicsitems/qdeclarativeitem_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/graphicsitems/qdeclarativeitem_p.h b/src/declarative/graphicsitems/qdeclarativeitem_p.h index 76ebcb4..dab0fb6 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem_p.h +++ b/src/declarative/graphicsitems/qdeclarativeitem_p.h @@ -101,7 +101,7 @@ private: qreal m_height; }; -class QDeclarativeItemPrivate : public QGraphicsItemPrivate +class Q_DECLARATIVE_EXPORT QDeclarativeItemPrivate : public QGraphicsItemPrivate { Q_DECLARE_PUBLIC(QDeclarativeItem) -- cgit v0.12 From bb966fe9dd8be25530da5a66727c7fe2123fafbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Tue, 9 Mar 2010 12:26:51 +0100 Subject: Renamed QPainter::Fragment/Hint -> QPainter::PixmapFragment/Hint Reviewed-by: Kim --- .../graphicsitems/qdeclarativeparticles.cpp | 2 +- src/gui/painting/qdrawutil.cpp | 4 +-- src/gui/painting/qpaintengineex.cpp | 4 +-- src/gui/painting/qpaintengineex_p.h | 3 +- src/gui/painting/qpainter.cpp | 40 +++++++++++----------- src/gui/painting/qpainter.h | 12 +++---- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 7 ++-- .../gl2paintengineex/qpaintengineex_opengl2_p.h | 6 ++-- src/openvg/qpaintengine_vg.cpp | 4 +-- src/openvg/qpaintengine_vg_p.h | 3 +- tests/auto/qpainter/tst_qpainter.cpp | 10 +++--- 11 files changed, 50 insertions(+), 45 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeparticles.cpp b/src/declarative/graphicsitems/qdeclarativeparticles.cpp index ec0bf6c..593c80a 100644 --- a/src/declarative/graphicsitems/qdeclarativeparticles.cpp +++ b/src/declarative/graphicsitems/qdeclarativeparticles.cpp @@ -1263,7 +1263,7 @@ void QDeclarativeParticlesPainter::paint(QPainter *p, const QStyleOptionGraphics const int myY = y() + parentItem()->y(); #if (QT_VERSION >= QT_VERSION_CHECK(4,7,0)) - QVarLengthArray pixmapData; + QVarLengthArray pixmapData; #else QVarLengthArray pixmapData; #endif diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp index d76c709..a62f06b 100644 --- a/src/gui/painting/qdrawutil.cpp +++ b/src/gui/painting/qdrawutil.cpp @@ -1081,7 +1081,7 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs, according to the \a margins structure. */ -typedef QVarLengthArray QPixmapFragmentsArray; +typedef QVarLengthArray QPixmapFragmentsArray; /*! \since 4.6 @@ -1102,7 +1102,7 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins, const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints) { - QPainter::Fragment d; + QPainter::PixmapFragment d; d.opacity = 1.0; d.rotation = 0.0; diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 98762f0..1fd622d 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -970,8 +970,8 @@ void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, con fill(path, brush); } -void QPaintEngineEx::drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, - const QPixmap &pixmap, QPainter::FragmentHints /*hints*/) +void QPaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, + const QPixmap &pixmap, QPainter::PixmapFragmentHints /*hints*/) { qreal oldOpacity = state()->opacity; QTransform oldTransform = state()->matrix; diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index 2401b94..6c654bd 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -197,7 +197,8 @@ public: virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); - virtual void drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, const QPixmap &pixmap, QFlags hints); + virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, + QFlags hints); virtual void updateState(const QPaintEngineState &state); diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 9d83718..50279e4 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -8914,11 +8914,11 @@ QTransform QPainter::combinedTransform() const This function is potentially faster than multiple calls to drawPixmap(), since the backend can optimize state changes. - \sa QPainter::Fragment, QPainter::FragmentHint + \sa QPainter::PixmapFragment, QPainter::PixmapFragmentHint */ -void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount, - const QPixmap &pixmap, FragmentHints hints) +void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount, + const QPixmap &pixmap, PixmapFragmentHints hints) { Q_D(QPainter); @@ -8959,7 +8959,7 @@ void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount, /*! \since 4.7 - \class QPainter::Fragment + \class QPainter::PixmapFragment \brief This class is used in conjunction with the QPainter::drawPixmapFragments() function to specify how a pixmap, or @@ -8980,73 +8980,73 @@ void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount, /*! \since 4.7 - This is a convenience function that returns a QPainter::Fragment that is + This is a convenience function that returns a QPainter::PixmapFragment that is initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a rotation, \a opacity parameters. */ -QPainter::Fragment QPainter::Fragment::create(const QPointF &pos, const QRectF &sourceRect, +QPainter::PixmapFragment QPainter::PixmapFragment::create(const QPointF &pos, const QRectF &sourceRect, qreal scaleX, qreal scaleY, qreal rotation, qreal opacity) { - Fragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(), - sourceRect.height(), scaleX, scaleY, rotation, opacity}; + PixmapFragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(), + sourceRect.height(), scaleX, scaleY, rotation, opacity}; return fragment; } /*! - \variable QPainter::Fragment::x + \variable QPainter::PixmapFragment::x \brief the x coordinate of center point in the target rectangle. */ /*! - \variable QPainter::Fragment::y + \variable QPainter::PixmapFragment::y \brief the y coordinate of the center point in the target rectangle. */ /*! - \variable QPainter::Fragment::sourceLeft + \variable QPainter::PixmapFragment::sourceLeft \brief the left coordinate of the source rectangle. */ /*! - \variable QPainter::Fragment::sourceTop + \variable QPainter::PixmapFragment::sourceTop \brief the top coordinate of the source rectangle. */ /*! - \variable QPainter::Fragment::width + \variable QPainter::PixmapFragment::width \brief the width of the source rectangle and is used to calculate the width of the target rectangle. */ /*! - \variable QPainter::Fragment::height + \variable QPainter::PixmapFragment::height \brief the height of the source rectangle and is used to calculate the height of the target rectangle. */ /*! - \variable QPainter::Fragment::scaleX + \variable QPainter::PixmapFragment::scaleX \brief the horizontal scale of the target rectangle. */ /*! - \variable QPainter::Fragment::scaleY + \variable QPainter::PixmapFragment::scaleY \brief the vertical scale of the target rectangle. */ /*! - \variable QPainter::Fragment::rotation + \variable QPainter::PixmapFragment::rotation \brief the rotation of the target rectangle in degrees. The target rectangle is rotated after it has been scaled. */ /*! - \variable QPainter::Fragment::opacity + \variable QPainter::PixmapFragment::opacity \brief the opacity of the target rectangle, where 0.0 is fully transparent and 1.0 is fully opaque. @@ -9055,12 +9055,12 @@ QPainter::Fragment QPainter::Fragment::create(const QPointF &pos, const QRectF & /*! \since 4.7 - \enum QPainter::FragmentHint + \enum QPainter::PixmapFragmentHint \value OpaqueHint Indicates that the pixmap fragments to be drawn are opaque. Opaque fragments are potentially faster to draw. - \sa QPainter::drawPixmapFragments(), QPainter::Fragment + \sa QPainter::drawPixmapFragments(), QPainter::PixmapFragment */ void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation) diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index bcb0b50..443925b 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -99,7 +99,7 @@ public: Q_DECLARE_FLAGS(RenderHints, RenderHint) - class Fragment { + class PixmapFragment { public: qreal x; qreal y; @@ -111,16 +111,16 @@ public: qreal scaleY; qreal rotation; qreal opacity; - static Fragment Q_GUI_EXPORT create(const QPointF &pos, const QRectF &sourceRect, + static PixmapFragment Q_GUI_EXPORT create(const QPointF &pos, const QRectF &sourceRect, qreal scaleX = 1, qreal scaleY = 1, qreal rotation = 0, qreal opacity = 1); }; - enum FragmentHint { + enum PixmapFragmentHint { OpaqueHint = 0x01 }; - Q_DECLARE_FLAGS(FragmentHints, FragmentHint) + Q_DECLARE_FLAGS(PixmapFragmentHints, PixmapFragmentHint) QPainter(); explicit QPainter(QPaintDevice *); @@ -375,8 +375,8 @@ public: inline void drawPixmap(const QRect &r, const QPixmap &pm); inline void drawPixmap(int x, int y, int w, int h, const QPixmap &pm); - void drawPixmapFragments(const Fragment *fragments, int fragmentCount, - const QPixmap &pixmap, FragmentHints hints = 0); + void drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount, + const QPixmap &pixmap, PixmapFragmentHints hints = 0); void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, Qt::ImageConversionFlags flags = Qt::AutoColor); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 8eb72b0..2b5f2f4 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1641,7 +1641,8 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp s->matrix = old; } -void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::FragmentHints hints) +void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, + QPainter::PixmapFragmentHints hints) { Q_D(QGL2PaintEngineEx); // Use fallback for extended composition modes. @@ -1655,9 +1656,9 @@ void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::Fragment *fragments, } -void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::Fragment *fragments, +void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, - QPainter::FragmentHints hints) + QPainter::PixmapFragmentHints hints) { GLfloat dx = 1.0f / pixmap.size().width(); GLfloat dy = 1.0f / pixmap.size().height(); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 5d3608b..ed8fbbc 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -125,7 +125,8 @@ public: virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr); virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - virtual void drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::FragmentHints hints); + virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, + QPainter::PixmapFragmentHints hints); virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags = Qt::AutoColor); virtual void drawTextItem(const QPointF &p, const QTextItem &textItem); @@ -196,7 +197,8 @@ public: void fill(const QVectorPath &path); void stroke(const QVectorPath &path, const QPen &pen); void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false); - void drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::FragmentHints hints); + void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, + QPainter::PixmapFragmentHints hints); void drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, QStaticTextItem *staticTextItem, bool includeMatrixInCache); diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 4df894a..2c850c9 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -3041,8 +3041,8 @@ void QVGPaintEngine::drawTiledPixmap // (i.e. no opacity), no rotation or scaling, and drawing the full // pixmap rather than parts of the pixmap. Even having just one of // these conditions will improve performance. -void QVGPaintEngine::drawPixmapFragments(const QPainter::Fragment *drawingData, int dataCount, - const QPixmap &pixmap, QFlags hints) +void QVGPaintEngine::drawPixmapFragments(const QPainter::PixmapFragment *drawingData, int dataCount, + const QPixmap &pixmap, QFlags hints) { #if !defined(QT_SHIVAVG) Q_D(QVGPaintEngine); diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h index 1203af5..1e7e26c 100644 --- a/src/openvg/qpaintengine_vg_p.h +++ b/src/openvg/qpaintengine_vg_p.h @@ -137,7 +137,8 @@ public: void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); - void drawPixmapFragments(const QPainter::Fragment *drawingData, int dataCount, const QPixmap &pixmap, QFlags hints); + void drawPixmapFragments(const QPainter::PixmapFragment *drawingData, int dataCount, const QPixmap &pixmap, + QFlags hints); void drawTextItem(const QPointF &p, const QTextItem &textItem); void drawStaticTextItem(QStaticTextItem *staticTextItem); diff --git a/tests/auto/qpainter/tst_qpainter.cpp b/tests/auto/qpainter/tst_qpainter.cpp index a03b2c7..701dc2e 100644 --- a/tests/auto/qpainter/tst_qpainter.cpp +++ b/tests/auto/qpainter/tst_qpainter.cpp @@ -999,10 +999,10 @@ void tst_QPainter::drawPixmapFragments() { QPixmap origPixmap(20, 20); QPixmap resPixmap(20, 20); - QPainter::Fragment fragments[4] = { {15, 15, 0, 0, 10, 10, 1, 1, 0, 1}, - { 5, 15, 10, 0, 10, 10, 1, 1, 0, 1}, - {15, 5, 0, 10, 10, 10, 1, 1, 0, 1}, - { 5, 5, 10, 10, 10, 10, 1, 1, 0, 1} }; + QPainter::PixmapFragment fragments[4] = { {15, 15, 0, 0, 10, 10, 1, 1, 0, 1}, + { 5, 15, 10, 0, 10, 10, 1, 1, 0, 1}, + {15, 5, 0, 10, 10, 10, 1, 1, 0, 1}, + { 5, 5, 10, 10, 10, 10, 1, 1, 0, 1} }; { QPainter p(&origPixmap); p.fillRect(0, 0, 10, 10, Qt::red); @@ -1025,7 +1025,7 @@ void tst_QPainter::drawPixmapFragments() QVERIFY(resImage.pixel(15, 15) == origImage.pixel(5, 5)); - QPainter::Fragment fragment = QPainter::Fragment::create(QPointF(20, 20), QRectF(30, 30, 2, 2)); + QPainter::PixmapFragment fragment = QPainter::PixmapFragment::create(QPointF(20, 20), QRectF(30, 30, 2, 2)); QVERIFY(fragment.x == 20); QVERIFY(fragment.y == 20); QVERIFY(fragment.sourceLeft == 30); -- cgit v0.12 From fb77eadad25d55d1b1d08776f7f74e6cb5c1b39e Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 9 Mar 2010 13:07:45 +0100 Subject: Fix typo in docs QStringList::appenf is private API, and shouldn't show up in docs. --- doc/src/declarative/qdeclarativemodels.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/declarative/qdeclarativemodels.qdoc b/doc/src/declarative/qdeclarativemodels.qdoc index c0e028e..f7d1a73 100644 --- a/doc/src/declarative/qdeclarativemodels.qdoc +++ b/doc/src/declarative/qdeclarativemodels.qdoc @@ -208,7 +208,7 @@ QStringList provides the contents of the list via the \e modelData role: QStringList dataList; dataList.append("Fred"); dataList.append("Ginger"); -dataList.appenf("Skipper"); +dataList.append("Skipper"); QDeclarativeContext *ctxt = view.rootContext(); ctxt->setContextProperty("myModel", QVariant::fromValue(&dataList)); -- cgit v0.12 From cd7f6dae4c886b8b1bfb2ddc56eb986fad545220 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 9 Mar 2010 13:17:09 +0100 Subject: Probably fix compile on windows --- src/declarative/graphicsitems/qdeclarativeitem_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/graphicsitems/qdeclarativeitem_p.h b/src/declarative/graphicsitems/qdeclarativeitem_p.h index dab0fb6..55df063 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem_p.h +++ b/src/declarative/graphicsitems/qdeclarativeitem_p.h @@ -259,7 +259,7 @@ public: static int consistentTime; static QTime currentTime(); - static void Q_DECLARATIVE_EXPORT setConsistentTime(int t); + static void setConsistentTime(int t); static void start(QTime &); static int elapsed(QTime &); static int restart(QTime &); -- cgit v0.12 From 83b057467054004fe0c1f14638f455cbf447d2b0 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 9 Mar 2010 13:32:25 +0100 Subject: Update Autotests Unless given an id, animations in behaviours aren't created until needed. As they are never actually needed in these tests, ids are needed --- tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml | 2 +- .../declarative/qdeclarativebehaviors/data/reassignedAnimation.qml | 4 ++-- tests/auto/declarative/qdeclarativebehaviors/data/simple.qml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml b/tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml index 12b1b7b..5e1891a 100644 --- a/tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml +++ b/tests/auto/declarative/qdeclarativebehaviors/data/dontStart.qml @@ -10,7 +10,7 @@ Rectangle { width: 100; height: 100 color: Qt.rgba(1,0,0) Behavior on x { - NumberAnimation { objectName: "MyAnim"; running: true } + NumberAnimation {id: myAnim; objectName: "MyAnim"; running: true } } } diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml b/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml index 6419a6b..11b2d3a 100644 --- a/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml +++ b/tests/auto/declarative/qdeclarativebehaviors/data/reassignedAnimation.qml @@ -8,8 +8,8 @@ Rectangle { width: 100; height: 100; color: "green" Behavior on x { objectName: "MyBehavior" - NumberAnimation { duration: 200 } - NumberAnimation { duration: 1000 } + NumberAnimation {id: na1; duration: 200 } + NumberAnimation {id: na2; duration: 1000 } } } MouseArea { diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/simple.qml b/tests/auto/declarative/qdeclarativebehaviors/data/simple.qml index c28fa9a..5e72bca 100644 --- a/tests/auto/declarative/qdeclarativebehaviors/data/simple.qml +++ b/tests/auto/declarative/qdeclarativebehaviors/data/simple.qml @@ -8,7 +8,7 @@ Rectangle { width: 100; height: 100; color: "green" Behavior on x { objectName: "MyBehavior"; - NumberAnimation { duration: 500; } + NumberAnimation {id: na; duration: 500; } } } MouseArea { -- cgit v0.12 From 4029da6fae201512b15f1e088bf720b0c37e1437 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 9 Mar 2010 14:58:00 +0100 Subject: update Browser.qml to run again --- tools/qml/content/Browser.qml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/qml/content/Browser.qml b/tools/qml/content/Browser.qml index 35120bc..62996ef 100644 --- a/tools/qml/content/Browser.qml +++ b/tools/qml/content/Browser.qml @@ -137,12 +137,12 @@ Rectangle { Transition { to: "current" SequentialAnimation { - NumberAnimation { matchProperties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } } }, Transition { - NumberAnimation { matchProperties: "x"; duration: 250 } - NumberAnimation { matchProperties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } } ] Keys.onPressed: { root.keyPressed = true; } @@ -177,11 +177,11 @@ Rectangle { Transition { to: "current" SequentialAnimation { - NumberAnimation { matchProperties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } } }, Transition { - NumberAnimation { matchProperties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } } ] Keys.onPressed: { root.keyPressed = true; } -- cgit v0.12 From d85b149a5c7f3532f8e1a593a79298c9ae38a95f Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 9 Mar 2010 14:13:58 +0100 Subject: Fix alignment of text with negative right bearing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In change 5364fd96a72c89b281f0540da909fe64d0575ccf and some related changes, we made sure that the natural text width used for calculating bounding rects and line breaks in the text, takes the right bearing of the last glyph into consideration. As a side-effect, this broke alignment of text, as we want to align based on the accumulated advance of the glyphs, not based on the actual width. This is in particular important when aligning monospaced text, since the text can become misaligned if the glyphs extend beyond their advance. The bug was visible e.g. in line numbers ending with 2 in Qt Creator on X11, which would be shifted one pixel to the left compared to other line numbers. Task-number: QTBUG-8864 Reviewed-by: Thorbjørn --- src/gui/painting/qpainter.cpp | 5 +++-- src/gui/text/qtextengine_p.h | 1 + src/gui/text/qtextlayout.cpp | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index dc96c17..9e2fc82 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -7994,10 +7994,11 @@ start_lengthVariant: for (int i = 0; i < textLayout.lineCount(); i++) { QTextLine line = textLayout.lineAt(i); + qreal advance = textLayout.engine()->lines[i].textAdvance.toReal(); if (tf & Qt::AlignRight) - xoff = r.width() - line.naturalTextWidth(); + xoff = r.width() - advance; else if (tf & Qt::AlignHCenter) - xoff = (r.width() - line.naturalTextWidth())/2; + xoff = (r.width() - advance)/2; line.draw(painter, QPointF(r.x() + xoff + line.x(), r.y() + yoff)); } diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index f36cbd2..5054b66 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -382,6 +382,7 @@ struct Q_AUTOTEST_EXPORT QScriptLine QFixed y; QFixed width; QFixed textWidth; + QFixed textAdvance; int from; signed int length : 29; mutable uint justified : 1; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index af91603..cc6793d 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1875,6 +1875,7 @@ void QTextLine::layout_helper(int maxGlyphs) line.textWidth += lbh.softHyphenWidth; } + line.textAdvance = line.textWidth; line.textWidth += lbh.rightBearing; goto found; @@ -1885,6 +1886,7 @@ void QTextLine::layout_helper(int maxGlyphs) } LB_DEBUG("reached end of line"); lbh.checkFullOtherwiseExtend(line); + line.textAdvance = line.textWidth; line.textWidth += lbh.rightBearing; found: -- cgit v0.12 From b0514ccdd318e2e508edab57bfd7ed064a550308 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Tue, 9 Mar 2010 14:45:54 +0100 Subject: Minimal fix to get the svgalib example to compile Confirmed to work in 16 and 32 bit modes. Patch made by David Boddie. Testing and README by me. Task-number: QTBUG-7403 Reviewed-by: David Boddie --- doc/src/examples/svgalib.qdoc | 3 -- examples/qws/svgalib/README | 12 +++++--- examples/qws/svgalib/svgalibpaintdevice.cpp | 2 +- examples/qws/svgalib/svgalibpaintengine.cpp | 45 ++++++++++++++--------------- examples/qws/svgalib/svgalibpaintengine.h | 6 ++-- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/doc/src/examples/svgalib.qdoc b/doc/src/examples/svgalib.qdoc index cf6512c..9142112 100644 --- a/doc/src/examples/svgalib.qdoc +++ b/doc/src/examples/svgalib.qdoc @@ -43,9 +43,6 @@ \example qws/svgalib \title Accelerated Graphics Driver Example - \warning This example was designed to work with Qt 4.4 and will not work - with current versions of Qt. It will be removed from Qt 4.7. - The Accelerated Graphics Driver example shows how you can write your own accelerated graphics driver and \l {add your graphics driver to Qt for Embedded Linux}. In \l{Qt for Embedded Linux}, diff --git a/examples/qws/svgalib/README b/examples/qws/svgalib/README index 0b2831f..227c066 100644 --- a/examples/qws/svgalib/README +++ b/examples/qws/svgalib/README @@ -1,5 +1,9 @@ -This is the SVGA screen driver plugin example from Qt 4.4. The code does -not compile with Qt 4.5, because the internal graphics engine has changed. +This is the SVGA screen driver plugin example for QWS. -This is unsupported code, provided for convenience in case there is -interest in porting it to Qt 4.5. +You may need to set the SVGALIB_DEFAULT_MODE environment +variable. These values have been confirmed to work on one specific +machine using svgalib 1.4.3: 18, 24, 34, 35, 36 + +There is a bug in the example causing missing updates in 8-bit mode +(e.g. modes 10 and 12). Fixing this bug is left as an exercise for the +reader. diff --git a/examples/qws/svgalib/svgalibpaintdevice.cpp b/examples/qws/svgalib/svgalibpaintdevice.cpp index 090311f..86613d2 100644 --- a/examples/qws/svgalib/svgalibpaintdevice.cpp +++ b/examples/qws/svgalib/svgalibpaintdevice.cpp @@ -48,7 +48,7 @@ SvgalibPaintDevice::SvgalibPaintDevice(QWidget *w) : QCustomRasterPaintDevice(w) { - pengine = new SvgalibPaintEngine; + pengine = new SvgalibPaintEngine(this); } SvgalibPaintDevice::~SvgalibPaintDevice() diff --git a/examples/qws/svgalib/svgalibpaintengine.cpp b/examples/qws/svgalib/svgalibpaintengine.cpp index 8713863..59740da 100644 --- a/examples/qws/svgalib/svgalibpaintengine.cpp +++ b/examples/qws/svgalib/svgalibpaintengine.cpp @@ -45,7 +45,8 @@ #include #include -SvgalibPaintEngine::SvgalibPaintEngine() +SvgalibPaintEngine::SvgalibPaintEngine(QPaintDevice *device) + : QRasterPaintEngine(device) { } @@ -61,7 +62,7 @@ bool SvgalibPaintEngine::begin(QPaintDevice *dev) simplePen = true; brush = Qt::NoBrush; simpleBrush = true; - matrix = QMatrix(); + matrix = QTransform(); simpleMatrix = true; setClip(QRect(0, 0, device->width(), device->height())); opaque = true; @@ -81,54 +82,52 @@ bool SvgalibPaintEngine::end() //! [1] //! [2] -void SvgalibPaintEngine::updateState(const QPaintEngineState &state) +void SvgalibPaintEngine::updateState() { - QPaintEngine::DirtyFlags flags = state.state(); + QRasterPaintEngineState *s = state(); - if (flags & DirtyTransform) { - matrix = state.matrix(); + if (s->dirty & DirtyTransform) { + matrix = s->matrix; simpleMatrix = (matrix.m12() == 0 && matrix.m21() == 0); } - if (flags & DirtyPen) { - pen = state.pen(); + if (s->dirty & DirtyPen) { + pen = s->pen; simplePen = (pen.width() == 0 || pen.widthF() <= 1) && (pen.style() == Qt::NoPen || pen.style() == Qt::SolidLine) && (pen.color().alpha() == 255); } - if (flags & DirtyBrush) { - brush = state.brush(); + if (s->dirty & DirtyBrush) { + brush = s->brush; simpleBrush = (brush.style() == Qt::SolidPattern || brush.style() == Qt::NoBrush) && (brush.color().alpha() == 255); } - if (flags & DirtyClipRegion) - setClip(state.clipRegion()); + if (s->dirty & DirtyClipRegion) + setClip(s->clipRegion); - if (flags & DirtyClipEnabled) { - clipEnabled = state.isClipEnabled(); + if (s->dirty & DirtyClipEnabled) { + clipEnabled = s->isClipEnabled(); updateClip(); } - if (flags & DirtyClipPath) { + if (s->dirty & DirtyClipPath) { setClip(QRegion()); simpleClip = false; } - if (flags & DirtyCompositionMode) { - const QPainter::CompositionMode m = state.compositionMode(); + if (s->dirty & DirtyCompositionMode) { + const QPainter::CompositionMode m = s->composition_mode; sourceOver = (m == QPainter::CompositionMode_SourceOver); } - if (flags & DirtyOpacity) - opaque = (state.opacity() == 256); + if (s->dirty & DirtyOpacity) + opaque = (s->opacity == 256); - if (flags & DirtyHints) - aliased = !(state.renderHints() & QPainter::Antialiasing); - - QRasterPaintEngine::updateState(state); + if (s->dirty & DirtyHints) + aliased = !(s->flags.antialiased); } //! [2] diff --git a/examples/qws/svgalib/svgalibpaintengine.h b/examples/qws/svgalib/svgalibpaintengine.h index f43d201..27b77ee 100644 --- a/examples/qws/svgalib/svgalibpaintengine.h +++ b/examples/qws/svgalib/svgalibpaintengine.h @@ -48,12 +48,12 @@ class SvgalibPaintEngine : public QRasterPaintEngine { public: - SvgalibPaintEngine(); + SvgalibPaintEngine(QPaintDevice *device); ~SvgalibPaintEngine(); bool begin(QPaintDevice *device); bool end(); - void updateState(const QPaintEngineState &state); + void updateState(); void drawRects(const QRect *rects, int rectCount); private: @@ -64,7 +64,7 @@ private: bool simplePen; QBrush brush; bool simpleBrush; - QMatrix matrix; + QTransform matrix; bool simpleMatrix; QRegion clip; bool clipEnabled; -- cgit v0.12