From 143409c36749a1b3dd55e425914e5b3ac2157993 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 14 Dec 2009 15:15:08 +1000 Subject: Benchmark cleanup. --- .../declarative/binding/objectproperty.txt | 2 + .../declarative/qmlpainting/qmlpainting.pro | 5 + .../declarative/qmlpainting/tst_qmlpainting.cpp | 629 +++++++++++++++++++ tests/benchmarks/qmlpainting/qmlpainting.pro | 5 - tests/benchmarks/qmlpainting/tst_qmlpainting.cpp | 696 --------------------- 5 files changed, 636 insertions(+), 701 deletions(-) create mode 100644 tests/benchmarks/declarative/qmlpainting/qmlpainting.pro create mode 100644 tests/benchmarks/declarative/qmlpainting/tst_qmlpainting.cpp delete mode 100644 tests/benchmarks/qmlpainting/qmlpainting.pro delete mode 100644 tests/benchmarks/qmlpainting/tst_qmlpainting.cpp diff --git a/tests/benchmarks/declarative/binding/objectproperty.txt b/tests/benchmarks/declarative/binding/objectproperty.txt index 597c965..63fa74d 100644 --- a/tests/benchmarks/declarative/binding/objectproperty.txt +++ b/tests/benchmarks/declarative/binding/objectproperty.txt @@ -1,3 +1,5 @@ +import Test 1.0 + MyQmlObject { id: MyObject diff --git a/tests/benchmarks/declarative/qmlpainting/qmlpainting.pro b/tests/benchmarks/declarative/qmlpainting/qmlpainting.pro new file mode 100644 index 0000000..58e9775 --- /dev/null +++ b/tests/benchmarks/declarative/qmlpainting/qmlpainting.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_qmlpainting + +SOURCES += tst_qmlpainting.cpp diff --git a/tests/benchmarks/declarative/qmlpainting/tst_qmlpainting.cpp b/tests/benchmarks/declarative/qmlpainting/tst_qmlpainting.cpp new file mode 100644 index 0000000..45941f8 --- /dev/null +++ b/tests/benchmarks/declarative/qmlpainting/tst_qmlpainting.cpp @@ -0,0 +1,629 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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 + +#include +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +class tst_QmlPainting : public QObject +{ + Q_OBJECT + + public: + tst_QmlPainting() {} + +private slots: + void drawRoundedRect(); + void drawScaledRoundedRect(); + void drawTransformedRoundedRect(); + void drawAntialiasedRoundedRect(); + void drawScaledAntialiasedRoundedRect_data(); + void drawScaledAntialiasedRoundedRect(); + void drawTransformedAntialiasedRoundedRect_data(); + void drawTransformedAntialiasedRoundedRect(); + void drawImageRoundedRect(); + void drawScaledImageRoundedRect_data(); + void drawScaledImageRoundedRect(); + void drawTransformedImageRoundedRect_data(); + void drawTransformedImageRoundedRect(); + void drawScaleGridRoundedRect(); + void drawScaledScaleGridRoundedRect_data(); + void drawScaledScaleGridRoundedRect(); + void drawTransformedScaleGridRoundedRect_data(); + void drawTransformedScaleGridRoundedRect(); + void drawTransformedTransparentImage_data(); + void drawTransformedTransparentImage(); + void drawTransformedSemiTransparentImage_data(); + void drawTransformedSemiTransparentImage(); + void drawTransformedFilledImage_data(); + void drawTransformedFilledImage(); +}; + +const qreal inv_dist_to_plane = 1. / 1024.; +QTransform transformForAngle(qreal angle) +{ + QTransform transform; + + QTransform rotTrans; + rotTrans.translate(-40, 0); + QTransform rotTrans2; + rotTrans2.translate(40, 0); + + qreal rad = angle * 2. * M_PI / 360.; + qreal c = ::cos(rad); + qreal s = ::sin(rad); + + qreal x = 0; + qreal y = 80; + qreal z = 0; + + qreal len = x * x + y * y + z * z; + if (len != 1.) { + len = ::sqrt(len); + x /= len; + y /= len; + z /= len; + } + + QTransform rot(x*x*(1-c)+c, x*y*(1-c)-z*s, x*z*(1-c)+y*s*inv_dist_to_plane, + y*x*(1-c)+z*s, y*y*(1-c)+c, y*z*(1-c)-x*s*inv_dist_to_plane, + 0, 0, 1); + + transform *= rotTrans; + transform *= rot; + transform *= rotTrans2; + + return transform; +} + +void tst_QmlPainting::drawRoundedRect() +{ + QImage surface(100, 100, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + p.setPen(QPen(Qt::black, 1)); + p.setBrush(Qt::red); + + QBENCHMARK { + p.drawRoundedRect(QRectF(.5, .5, 80, 80), 10, 10); + } + surface.save("regular.png"); +} + +void tst_QmlPainting::drawScaledRoundedRect() +{ + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + p.setPen(QPen(Qt::black, 1)); + p.setBrush(Qt::red); + p.scale(3, 3); + + QBENCHMARK { + p.drawRoundedRect(10, 10, 80, 80, 10, 10); + } + surface.save("scaled.png"); +} + +void tst_QmlPainting::drawTransformedRoundedRect() +{ + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + p.setPen(QPen(Qt::black, 1)); + p.setBrush(Qt::red); + + QBENCHMARK { + p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); + p.drawRoundedRect(100, 100, 80, 80, 10, 10); + } + surface.save("transformed.png"); +} + +void tst_QmlPainting::drawAntialiasedRoundedRect() +{ + QImage surface(100, 100, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + p.setRenderHint(QPainter::Antialiasing, true); + p.setPen(QPen(Qt::black, 1)); + p.setBrush(Qt::red); + + QBENCHMARK { + p.drawRoundedRect(QRectF(.5, .5, 80, 80), 10, 10); + } + surface.save("aar.png"); +} + +void tst_QmlPainting::drawScaledAntialiasedRoundedRect_data() +{ + QTest::addColumn("scale"); + + for (float i = 0; i < 3; i += .1) + QTest::newRow(QString(QLatin1String("scale=%1")).arg(i).toLatin1()) << i; +} + +void tst_QmlPainting::drawScaledAntialiasedRoundedRect() +{ + QFETCH(float, scale); + + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + p.setRenderHint(QPainter::Antialiasing, true); + p.setPen(QPen(Qt::black, 1)); + p.setBrush(Qt::red); + p.scale(scale, scale); + + QBENCHMARK { + p.drawRoundedRect(10, 10, 80, 80, 10, 10); + } + surface.save("aas.png"); +} + +void tst_QmlPainting::drawTransformedAntialiasedRoundedRect_data() +{ + QTest::addColumn("transform"); + + for (float angle = 0; angle < 360; angle += 10) + QTest::newRow(QString(QLatin1String("angle=%1")).arg(angle).toLatin1()) << transformForAngle(angle); +} + +void tst_QmlPainting::drawTransformedAntialiasedRoundedRect() +{ + QFETCH(QTransform, transform); + + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + p.setRenderHint(QPainter::Antialiasing, true); + p.setPen(QPen(Qt::black, 1)); + p.setBrush(Qt::red); + + QBENCHMARK { + p.setWorldTransform(transform); + p.drawRoundedRect(100, 100, 80, 80, 10, 10); + } + surface.save("aat.png"); +} + +void tst_QmlPainting::drawImageRoundedRect() +{ + //setup image + const int radius = 10; + QImage rectImage(81, 81, QImage::Format_ARGB32_Premultiplied); + rectImage.fill(0); + QPainter rp(&rectImage); + rp.setRenderHint(QPainter::Antialiasing); + rp.setPen(Qt::black); + rp.setBrush(Qt::red); + rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius); + + //setup surface + QImage surface(100, 100, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + QBENCHMARK { + p.drawImage(0,0, rectImage); + } + surface.save("ri.png"); +} + +void tst_QmlPainting::drawScaledImageRoundedRect_data() +{ + QTest::addColumn("imageType"); + + QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; + QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; +} + +void tst_QmlPainting::drawScaledImageRoundedRect() +{ + QFETCH(int, imageType); + + //setup image + const int radius = 10; + QImage rectImage(81, 81, (QImage::Format)imageType); + rectImage.fill(0); + QPainter rp(&rectImage); + rp.setRenderHint(QPainter::Antialiasing); + rp.setPen(Qt::black); + rp.setBrush(Qt::red); + rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius); + + //setup surface + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + p.scale(3, 3); + + QBENCHMARK { + p.drawImage(0,0, rectImage); + } + surface.save("si.png"); +} + +void tst_QmlPainting::drawTransformedImageRoundedRect_data() +{ + QTest::addColumn("imageType"); + + QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; + QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; +} + +void tst_QmlPainting::drawTransformedImageRoundedRect() +{ + QFETCH(int, imageType); + + //setup image + const int radius = 10; + QImage rectImage(81, 81, (QImage::Format)imageType); + rectImage.fill(0); + QPainter rp(&rectImage); + rp.setRenderHint(QPainter::Antialiasing); + rp.setPen(Qt::black); + rp.setBrush(Qt::red); + rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius); + + //setup surface + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + QBENCHMARK { + p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); + p.drawImage(100,100, rectImage); + } + surface.save("ti.png"); +} + +//code from QmlGraphicsRectangle for drawing rounded rects +void tst_QmlPainting::drawScaleGridRoundedRect() +{ + //setup image + const int pw = 1; + const int radius = 10; + QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, QImage::Format_ARGB32_Premultiplied); + rectImage.fill(0); + QPainter rp(&rectImage); + rp.setRenderHint(QPainter::Antialiasing); + rp.setPen(Qt::black); + rp.setBrush(Qt::red); + if (pw%2) + rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius); + else + rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius); + QPixmap rectPixmap = QPixmap::fromImage(rectImage); + + //setup surface + QImage surface(100, 100, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + QBENCHMARK { + const int pw = 2; + //int offset = int(radius+1.5+pw); + int width = 80; + int height = 80; + + /*int w = width+pw; + int h = height+pw; + int xOffset = offset; + int xSide = xOffset * 2; + bool xMiddles=true; + if (xSide > w) { + xMiddles=false; + xOffset = w/2 + 1; + xSide = xOffset * 2; + } + int yOffset = offset; + int ySide = yOffset * 2; + bool yMiddles=true; + if (ySide > h) { + yMiddles = false; + yOffset = h/2 + 1; + ySide = yOffset * 2; + }*/ + + int xOffset = (rectPixmap.width()-1)/2; + int yOffset = (rectPixmap.height()-1)/2; + Q_ASSERT(rectPixmap.width() == 2*xOffset + 1); + Q_ASSERT(rectPixmap.height() == 2*yOffset + 1); + + QMargins margins(xOffset, yOffset, xOffset, yOffset); + QTileRules rules(Qt::StretchTile, Qt::StretchTile); + //NOTE: even though our item may have qreal-based width and height, qDrawBorderPixmap only supports QRects + qDrawBorderPixmap(&p, QRect(-pw/2, -pw/2, width+pw, height+pw), margins, rectPixmap, rectPixmap.rect(), margins, rules); + } + surface.save("rsg.png"); +} + +void tst_QmlPainting::drawScaledScaleGridRoundedRect_data() +{ + QTest::addColumn("scale"); + QTest::addColumn("imageType"); + + for (float i = 0; i < 3; i += .1) + QTest::newRow(QString(QLatin1String("scale=%1; imagetype=ARGB32_Pre")).arg(i).toLatin1()) << i << (int)QImage::Format_ARGB32_Premultiplied; + //for (float i = 0; i < 3; i += .1) + // QTest::newRow(QString(QLatin1String("scale=%1; imagetype=ARGB8565_Pre")).arg(i).toLatin1()) << i << (int)QImage::Format_ARGB8565_Premultiplied; +} + +//code from QmlGraphicsRectangle for drawing rounded rects +void tst_QmlPainting::drawScaledScaleGridRoundedRect() +{ + QFETCH(float, scale); + QFETCH(int, imageType); + + //setup image + const int pw = 1; + const int radius = 10; + QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, (QImage::Format)imageType); + rectImage.fill(0); + QPainter rp(&rectImage); + rp.setRenderHint(QPainter::Antialiasing); + rp.setPen(Qt::black); + rp.setBrush(Qt::red); + if (pw%2) + rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius); + else + rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius); + + QPixmap rectPixmap = QPixmap::fromImage(rectImage); + + //setup surface + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + p.scale(scale, scale); + + QBENCHMARK { + const int pw = 2; + //int offset = int(radius+1.5+pw); + int width = 80; + int height = 80; + + /*int w = width+pw; + int h = height+pw; + int xOffset = offset; + int xSide = xOffset * 2; + bool xMiddles=true; + if (xSide > w) { + xMiddles=false; + xOffset = w/2 + 1; + xSide = xOffset * 2; + } + int yOffset = offset; + int ySide = yOffset * 2; + bool yMiddles=true; + if (ySide > h) { + yMiddles = false; + yOffset = h/2 + 1; + ySide = yOffset * 2; + }*/ + + int xOffset = (rectPixmap.width()-1)/2; + int yOffset = (rectPixmap.height()-1)/2; + Q_ASSERT(rectPixmap.width() == 2*xOffset + 1); + Q_ASSERT(rectPixmap.height() == 2*yOffset + 1); + + QMargins margins(xOffset, yOffset, xOffset, yOffset); + QTileRules rules(Qt::StretchTile, Qt::StretchTile); + //NOTE: even though our item may have qreal-based width and height, qDrawBorderPixmap only supports QRects + qDrawBorderPixmap(&p, QRect(-pw/2, -pw/2, width+pw, height+pw), margins, rectPixmap, rectPixmap.rect(), margins, rules); + } + surface.save("ssg.png"); +} + +void tst_QmlPainting::drawTransformedScaleGridRoundedRect_data() +{ + QTest::addColumn("transform"); + QTest::addColumn("imageType"); + + for (float angle = 0; angle < 360; angle += 10) + QTest::newRow(QString(QLatin1String("angle=%1; imagetype=ARGB32_Pre")).arg(angle).toLatin1()) << transformForAngle(angle) << (int)QImage::Format_ARGB32_Premultiplied; + //for (float angle = 0; angle < 360; angle += 10) + // QTest::newRow(QString(QLatin1String("angle=%1; imagetype=ARGB8565_Pre")).arg(angle).toLatin1()) << transformForAngle(angle) << (int)QImage::Format_ARGB8565_Premultiplied; + +} + +//code from QmlGraphicsRectangle for drawing rounded rects +void tst_QmlPainting::drawTransformedScaleGridRoundedRect() +{ + QFETCH(QTransform, transform); + QFETCH(int, imageType); + + //setup image + const int pw = 1; + const int radius = 10; + QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, (QImage::Format)imageType); + rectImage.fill(0); + QPainter rp(&rectImage); + rp.setRenderHint(QPainter::Antialiasing); + rp.setPen(Qt::black); + rp.setBrush(Qt::red); + if (pw%2) + rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius); + else + rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius); + + QPixmap rectPixmap = QPixmap::fromImage(rectImage); + + //setup surface + QImage surface(400, 400, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + QBENCHMARK { + p.setWorldTransform(transform); + const int pw = 2; + //int offset = int(radius+1.5+pw); + int width = 80; + int height = 80; + + /*int w = width+pw; + int h = height+pw; + int xOffset = offset; + int xSide = xOffset * 2; + bool xMiddles=true; + if (xSide > w) { + xMiddles=false; + xOffset = w/2 + 1; + xSide = xOffset * 2; + } + int yOffset = offset; + int ySide = yOffset * 2; + bool yMiddles=true; + if (ySide > h) { + yMiddles = false; + yOffset = h/2 + 1; + ySide = yOffset * 2; + }*/ + + int xOffset = (rectPixmap.width()-1)/2; + int yOffset = (rectPixmap.height()-1)/2; + Q_ASSERT(rectPixmap.width() == 2*xOffset + 1); + Q_ASSERT(rectPixmap.height() == 2*yOffset + 1); + + QMargins margins(xOffset, yOffset, xOffset, yOffset); + QTileRules rules(Qt::StretchTile, Qt::StretchTile); + //NOTE: even though our item may have qreal-based width and height, qDrawBorderPixmap only supports QRects + qDrawBorderPixmap(&p, QRect(-pw/2, -pw/2, width+pw, height+pw), margins, rectPixmap, rectPixmap.rect(), margins, rules); + } + surface.save("tsg.png"); +} + +void tst_QmlPainting::drawTransformedTransparentImage_data() +{ + QTest::addColumn("imageType"); + + QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; + QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; +} + +void tst_QmlPainting::drawTransformedTransparentImage() +{ + QFETCH(int, imageType); + + //setup image + QImage transImage(200, 200, (QImage::Format)imageType); + transImage.fill(0); + + //setup surface + QImage surface(200, 200, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + QBENCHMARK { + p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); + p.drawImage(0,0, transImage); + } +} + +void tst_QmlPainting::drawTransformedSemiTransparentImage_data() +{ + QTest::addColumn("imageType"); + + QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; + QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; +} + +void tst_QmlPainting::drawTransformedSemiTransparentImage() +{ + QFETCH(int, imageType); + + //setup image + QImage transImage(200, 200, (QImage::Format)imageType); + transImage.fill(QColor(0,0,0, 128).rgba()); + + //setup surface + QImage surface(200, 200, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + QBENCHMARK { + p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); + p.drawImage(0,0, transImage); + } +} + +void tst_QmlPainting::drawTransformedFilledImage_data() +{ + QTest::addColumn("imageType"); + + QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; + QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; +} + +void tst_QmlPainting::drawTransformedFilledImage() +{ + QFETCH(int, imageType); + + //setup image + QImage filledImage(200, 200, (QImage::Format)imageType); + filledImage.fill(QColor(0,0,0).rgb()); + + //setup surface + QImage surface(200, 200, QImage::Format_RGB16); + surface.fill(QColor(255,255,255).rgb()); + QPainter p(&surface); + + QBENCHMARK { + p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); + p.drawImage(0,0, filledImage); + } +} + +QTEST_MAIN(tst_QmlPainting) + +#include "tst_qmlpainting.moc" diff --git a/tests/benchmarks/qmlpainting/qmlpainting.pro b/tests/benchmarks/qmlpainting/qmlpainting.pro deleted file mode 100644 index 58e9775..0000000 --- a/tests/benchmarks/qmlpainting/qmlpainting.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -TEMPLATE = app -TARGET = tst_qmlpainting - -SOURCES += tst_qmlpainting.cpp diff --git a/tests/benchmarks/qmlpainting/tst_qmlpainting.cpp b/tests/benchmarks/qmlpainting/tst_qmlpainting.cpp deleted file mode 100644 index e268136..0000000 --- a/tests/benchmarks/qmlpainting/tst_qmlpainting.cpp +++ /dev/null @@ -1,696 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 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 - -#include -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -class tst_QmlPainting : public QObject -{ - Q_OBJECT - - public: - tst_QmlPainting() {} - -private slots: - void drawRoundedRect(); - void drawScaledRoundedRect(); - void drawTransformedRoundedRect(); - void drawAntialiasedRoundedRect(); - void drawScaledAntialiasedRoundedRect_data(); - void drawScaledAntialiasedRoundedRect(); - void drawTransformedAntialiasedRoundedRect_data(); - void drawTransformedAntialiasedRoundedRect(); - void drawImageRoundedRect(); - void drawScaledImageRoundedRect_data(); - void drawScaledImageRoundedRect(); - void drawTransformedImageRoundedRect_data(); - void drawTransformedImageRoundedRect(); - void drawScaleGridRoundedRect(); - void drawScaledScaleGridRoundedRect_data(); - void drawScaledScaleGridRoundedRect(); - void drawTransformedScaleGridRoundedRect_data(); - void drawTransformedScaleGridRoundedRect(); - void drawTransformedTransparentImage_data(); - void drawTransformedTransparentImage(); - void drawTransformedSemiTransparentImage_data(); - void drawTransformedSemiTransparentImage(); - void drawTransformedFilledImage_data(); - void drawTransformedFilledImage(); -}; - -const qreal inv_dist_to_plane = 1. / 1024.; -QTransform transformForAngle(qreal angle) -{ - QTransform transform; - - QTransform rotTrans; - rotTrans.translate(-40, 0); - QTransform rotTrans2; - rotTrans2.translate(40, 0); - - qreal rad = angle * 2. * M_PI / 360.; - qreal c = ::cos(rad); - qreal s = ::sin(rad); - - qreal x = 0; - qreal y = 80; - qreal z = 0; - - qreal len = x * x + y * y + z * z; - if (len != 1.) { - len = ::sqrt(len); - x /= len; - y /= len; - z /= len; - } - - QTransform rot(x*x*(1-c)+c, x*y*(1-c)-z*s, x*z*(1-c)+y*s*inv_dist_to_plane, - y*x*(1-c)+z*s, y*y*(1-c)+c, y*z*(1-c)-x*s*inv_dist_to_plane, - 0, 0, 1); - - transform *= rotTrans; - transform *= rot; - transform *= rotTrans2; - - return transform; -} - -void tst_QmlPainting::drawRoundedRect() -{ - QImage surface(100, 100, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - - p.setPen(QPen(Qt::black, 1)); - p.setBrush(Qt::red); - - QBENCHMARK { - p.drawRoundedRect(QRectF(.5, .5, 80, 80), 10, 10); - } - surface.save("regular.png"); -} - -void tst_QmlPainting::drawScaledRoundedRect() -{ - QImage surface(400, 400, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - - p.setPen(QPen(Qt::black, 1)); - p.setBrush(Qt::red); - p.scale(3, 3); - - QBENCHMARK { - p.drawRoundedRect(10, 10, 80, 80, 10, 10); - } - surface.save("scaled.png"); -} - -void tst_QmlPainting::drawTransformedRoundedRect() -{ - QImage surface(400, 400, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - - p.setPen(QPen(Qt::black, 1)); - p.setBrush(Qt::red); - - QBENCHMARK { - p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); - p.drawRoundedRect(100, 100, 80, 80, 10, 10); - } - surface.save("transformed.png"); -} - -void tst_QmlPainting::drawAntialiasedRoundedRect() -{ - QImage surface(100, 100, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - - p.setRenderHint(QPainter::Antialiasing, true); - p.setPen(QPen(Qt::black, 1)); - p.setBrush(Qt::red); - - QBENCHMARK { - p.drawRoundedRect(QRectF(.5, .5, 80, 80), 10, 10); - } - surface.save("aar.png"); -} - -void tst_QmlPainting::drawScaledAntialiasedRoundedRect_data() -{ - QTest::addColumn("scale"); - - for (float i = 0; i < 3; i += .1) - QTest::newRow(QString(QLatin1String("scale=%1")).arg(i).toLatin1()) << i; -} - -void tst_QmlPainting::drawScaledAntialiasedRoundedRect() -{ - QFETCH(float, scale); - - QImage surface(400, 400, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - - p.setRenderHint(QPainter::Antialiasing, true); - p.setPen(QPen(Qt::black, 1)); - p.setBrush(Qt::red); - p.scale(scale, scale); - - QBENCHMARK { - p.drawRoundedRect(10, 10, 80, 80, 10, 10); - } - surface.save("aas.png"); -} - -void tst_QmlPainting::drawTransformedAntialiasedRoundedRect_data() -{ - QTest::addColumn("transform"); - - for (float angle = 0; angle < 360; angle += 10) - QTest::newRow(QString(QLatin1String("angle=%1")).arg(angle).toLatin1()) << transformForAngle(angle); -} - -void tst_QmlPainting::drawTransformedAntialiasedRoundedRect() -{ - QFETCH(QTransform, transform); - - QImage surface(400, 400, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - - p.setRenderHint(QPainter::Antialiasing, true); - p.setPen(QPen(Qt::black, 1)); - p.setBrush(Qt::red); - - QBENCHMARK { - p.setWorldTransform(transform); - p.drawRoundedRect(100, 100, 80, 80, 10, 10); - } - surface.save("aat.png"); -} - -void tst_QmlPainting::drawImageRoundedRect() -{ - //setup image - const int radius = 10; - QImage rectImage(81, 81, QImage::Format_ARGB32_Premultiplied); - rectImage.fill(0); - QPainter rp(&rectImage); - rp.setRenderHint(QPainter::Antialiasing); - rp.setPen(Qt::black); - rp.setBrush(Qt::red); - rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius); - - //setup surface - QImage surface(100, 100, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - - QBENCHMARK { - p.drawImage(0,0, rectImage); - } - surface.save("ri.png"); -} - -void tst_QmlPainting::drawScaledImageRoundedRect_data() -{ - QTest::addColumn("imageType"); - - QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; - QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; -} - -void tst_QmlPainting::drawScaledImageRoundedRect() -{ - QFETCH(int, imageType); - - //setup image - const int radius = 10; - QImage rectImage(81, 81, (QImage::Format)imageType); - rectImage.fill(0); - QPainter rp(&rectImage); - rp.setRenderHint(QPainter::Antialiasing); - rp.setPen(Qt::black); - rp.setBrush(Qt::red); - rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius); - - //setup surface - QImage surface(400, 400, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - p.scale(3, 3); - - QBENCHMARK { - p.drawImage(0,0, rectImage); - } - surface.save("si.png"); -} - -void tst_QmlPainting::drawTransformedImageRoundedRect_data() -{ - QTest::addColumn("imageType"); - - QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; - QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; -} - -void tst_QmlPainting::drawTransformedImageRoundedRect() -{ - QFETCH(int, imageType); - - //setup image - const int radius = 10; - QImage rectImage(81, 81, (QImage::Format)imageType); - rectImage.fill(0); - QPainter rp(&rectImage); - rp.setRenderHint(QPainter::Antialiasing); - rp.setPen(Qt::black); - rp.setBrush(Qt::red); - rp.drawRoundedRect(QRectF(.5, .5, 80, 80), radius, radius); - - //setup surface - QImage surface(400, 400, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - - QBENCHMARK { - p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); - p.drawImage(100,100, rectImage); - } - surface.save("ti.png"); -} - -//code from QmlGraphicsRectangle for drawing rounded rects -void tst_QmlPainting::drawScaleGridRoundedRect() -{ - //setup image - const int pw = 1; - const int radius = 10; - QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, QImage::Format_ARGB32_Premultiplied); - rectImage.fill(0); - QPainter rp(&rectImage); - rp.setRenderHint(QPainter::Antialiasing); - rp.setPen(Qt::black); - rp.setBrush(Qt::red); - if (pw%2) - rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius); - else - rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius); - - //setup surface - QImage surface(100, 100, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - - QBENCHMARK { - const int pw = 2; - int offset = int(radius+1.5+pw); - int width = 80; - int height = 80; - - int w = width+pw; - int h = height+pw; - int xOffset = offset; - int xSide = xOffset * 2; - bool xMiddles=true; - if (xSide > w) { - xMiddles=false; - xOffset = w/2 + 1; - xSide = xOffset * 2; - } - int yOffset = offset; - int ySide = yOffset * 2; - bool yMiddles=true; - if (ySide > h) { - yMiddles = false; - yOffset = h/2 + 1; - ySide = yOffset * 2; - } - - // Upper left - p.drawImage(QRect(-pw/2, -pw/2, xOffset, yOffset), rectImage, QRect(0, 0, xOffset, yOffset)); - - // Upper middle - if (xMiddles) - p.drawImage(QRect(xOffset-pw/2, -pw/2, width - xSide + pw, yOffset), rectImage, - QRect(rectImage.width()/2, 0, 1, yOffset)); - // Upper right - p.drawImage(QPoint(width-xOffset+pw/2, -pw/2), rectImage, - QRect(rectImage.width()-xOffset, 0, xOffset, yOffset)); - // Middle left - if (yMiddles) - p.drawImage(QRect(-pw/2, yOffset-pw/2, xOffset, height - ySide + pw), rectImage, - QRect(0, rectImage.height()/2, xOffset, 1)); - - // Middle - if (xMiddles && yMiddles) - p.drawImage(QRect(xOffset-pw/2, yOffset-pw/2, width - xSide + pw, height - ySide + pw), rectImage, - QRect(rectImage.width()/2, rectImage.height()/2, 1, 1)); - // Middle right - if (yMiddles) - p.drawImage(QRect(width-xOffset+pw/2, yOffset-pw/2, xOffset, height - ySide + pw), rectImage, - QRect(rectImage.width()-xOffset, rectImage.height()/2, xOffset, 1)); - // Lower left - p.drawImage(QPoint(-pw/2, height - yOffset + pw/2), rectImage, QRect(0, rectImage.height() - yOffset, xOffset, yOffset)); - - // Lower Middle - if (xMiddles) - p.drawImage(QRect(xOffset-pw/2, height - yOffset +pw/2, width - xSide + pw, yOffset), rectImage, - QRect(rectImage.width()/2, rectImage.height() - yOffset, 1, yOffset)); - // Lower Right - p.drawImage(QPoint(width-xOffset+pw/2, height - yOffset+pw/2), rectImage, - QRect(rectImage.width()-xOffset, rectImage.height() - yOffset, xOffset, yOffset)); - } - surface.save("rsg.png"); -} - -void tst_QmlPainting::drawScaledScaleGridRoundedRect_data() -{ - QTest::addColumn("scale"); - QTest::addColumn("imageType"); - - for (float i = 0; i < 3; i += .1) - QTest::newRow(QString(QLatin1String("scale=%1; imagetype=ARGB32_Pre")).arg(i).toLatin1()) << i << (int)QImage::Format_ARGB32_Premultiplied; - //for (float i = 0; i < 3; i += .1) - // QTest::newRow(QString(QLatin1String("scale=%1; imagetype=ARGB8565_Pre")).arg(i).toLatin1()) << i << (int)QImage::Format_ARGB8565_Premultiplied; -} - -//code from QmlGraphicsRectangle for drawing rounded rects -void tst_QmlPainting::drawScaledScaleGridRoundedRect() -{ - QFETCH(float, scale); - QFETCH(int, imageType); - - //setup image - const int pw = 1; - const int radius = 10; - QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, (QImage::Format)imageType); - rectImage.fill(0); - QPainter rp(&rectImage); - rp.setRenderHint(QPainter::Antialiasing); - rp.setPen(Qt::black); - rp.setBrush(Qt::red); - if (pw%2) - rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius); - else - rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius); - - //setup surface - QImage surface(400, 400, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - p.scale(scale, scale); - - QBENCHMARK { - const int pw = 2; - int offset = int(radius+1.5+pw); - int width = 80; - int height = 80; - - int w = width+pw; - int h = height+pw; - int xOffset = offset; - int xSide = xOffset * 2; - bool xMiddles=true; - if (xSide > w) { - xMiddles=false; - xOffset = w/2 + 1; - xSide = xOffset * 2; - } - int yOffset = offset; - int ySide = yOffset * 2; - bool yMiddles=true; - if (ySide > h) { - yMiddles = false; - yOffset = h/2 + 1; - ySide = yOffset * 2; - } - - // Upper left - p.drawImage(QRect(10-pw/2, 10-pw/2, xOffset, yOffset), rectImage, QRect(0, 0, xOffset, yOffset)); - - // Upper middle - if (xMiddles) - p.drawImage(QRect(10+xOffset-pw/2, 10+-pw/2, width - xSide + pw, yOffset), rectImage, - QRect(rectImage.width()/2, 0, 1, yOffset)); - // Upper right - p.drawImage(QPoint(10+width-xOffset+pw/2, 10+-pw/2), rectImage, - QRect(rectImage.width()-xOffset, 0, xOffset, yOffset)); - // Middle left - if (yMiddles) - p.drawImage(QRect(10+-pw/2, 10+yOffset-pw/2, xOffset, height - ySide + pw), rectImage, - QRect(0, rectImage.height()/2, xOffset, 1)); - - // Middle - if (xMiddles && yMiddles) - p.drawImage(QRect(10+xOffset-pw/2, 10+yOffset-pw/2, width - xSide + pw, height - ySide + pw), rectImage, - QRect(rectImage.width()/2, rectImage.height()/2, 1, 1)); - // Middle right - if (yMiddles) - p.drawImage(QRect(10+width-xOffset+pw/2, 10+yOffset-pw/2, xOffset, height - ySide + pw), rectImage, - QRect(rectImage.width()-xOffset, rectImage.height()/2, xOffset, 1)); - // Lower left - p.drawImage(QPoint(10+-pw/2, 10+height - yOffset + pw/2), rectImage, QRect(0, rectImage.height() - yOffset, xOffset, yOffset)); - - // Lower Middle - if (xMiddles) - p.drawImage(QRect(10+xOffset-pw/2, 10+height - yOffset +pw/2, width - xSide + pw, yOffset), rectImage, - QRect(rectImage.width()/2, rectImage.height() - yOffset, 1, yOffset)); - // Lower Right - p.drawImage(QPoint(10+width-xOffset+pw/2, 10+height - yOffset+pw/2), rectImage, - QRect(rectImage.width()-xOffset, rectImage.height() - yOffset, xOffset, yOffset)); - } - surface.save("ssg.png"); -} - -void tst_QmlPainting::drawTransformedScaleGridRoundedRect_data() -{ - QTest::addColumn("transform"); - QTest::addColumn("imageType"); - - for (float angle = 0; angle < 360; angle += 10) - QTest::newRow(QString(QLatin1String("angle=%1; imagetype=ARGB32_Pre")).arg(angle).toLatin1()) << transformForAngle(angle) << (int)QImage::Format_ARGB32_Premultiplied; - //for (float angle = 0; angle < 360; angle += 10) - // QTest::newRow(QString(QLatin1String("angle=%1; imagetype=ARGB8565_Pre")).arg(angle).toLatin1()) << transformForAngle(angle) << (int)QImage::Format_ARGB8565_Premultiplied; - -} - -//code from QmlGraphicsRectangle for drawing rounded rects -void tst_QmlPainting::drawTransformedScaleGridRoundedRect() -{ - QFETCH(QTransform, transform); - QFETCH(int, imageType); - - //setup image - const int pw = 1; - const int radius = 10; - QImage rectImage(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2, (QImage::Format)imageType); - rectImage.fill(0); - QPainter rp(&rectImage); - rp.setRenderHint(QPainter::Antialiasing); - rp.setPen(Qt::black); - rp.setBrush(Qt::red); - if (pw%2) - rp.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, rectImage.width()-(pw+1), rectImage.height()-(pw+1)), radius, radius); - else - rp.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, rectImage.width()-pw, rectImage.height()-pw), radius, radius); - - //setup surface - QImage surface(400, 400, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - - QBENCHMARK { - p.setWorldTransform(transform); - const int pw = 2; - int offset = int(radius+1.5+pw); - int width = 80; - int height = 80; - - int w = width+pw; - int h = height+pw; - int xOffset = offset; - int xSide = xOffset * 2; - bool xMiddles=true; - if (xSide > w) { - xMiddles=false; - xOffset = w/2 + 1; - xSide = xOffset * 2; - } - int yOffset = offset; - int ySide = yOffset * 2; - bool yMiddles=true; - if (ySide > h) { - yMiddles = false; - yOffset = h/2 + 1; - ySide = yOffset * 2; - } - - // Upper left - p.drawImage(QRect(100-pw/2, 100-pw/2, xOffset, yOffset), rectImage, QRect(0, 0, xOffset, yOffset)); - - // Upper middle - if (xMiddles) - p.drawImage(QRect(100+xOffset-pw/2, 100+-pw/2, width - xSide + pw, yOffset), rectImage, - QRect(rectImage.width()/2, 0, 1, yOffset)); - // Upper right - p.drawImage(QPoint(100+width-xOffset+pw/2, 100+-pw/2), rectImage, - QRect(rectImage.width()-xOffset, 0, xOffset, yOffset)); - // Middle left - if (yMiddles) - p.drawImage(QRect(100+-pw/2, 100+yOffset-pw/2, xOffset, height - ySide + pw), rectImage, - QRect(0, rectImage.height()/2, xOffset, 1)); - - // Middle - if (xMiddles && yMiddles) - p.drawImage(QRect(100+xOffset-pw/2, 100+yOffset-pw/2, width - xSide + pw, height - ySide + pw), rectImage, - QRect(rectImage.width()/2, rectImage.height()/2, 1, 1)); - // Middle right - if (yMiddles) - p.drawImage(QRect(100+width-xOffset+pw/2, 100+yOffset-pw/2, xOffset, height - ySide + pw), rectImage, - QRect(rectImage.width()-xOffset, rectImage.height()/2, xOffset, 1)); - // Lower left - p.drawImage(QPoint(100+-pw/2, 100+height - yOffset + pw/2), rectImage, QRect(0, rectImage.height() - yOffset, xOffset, yOffset)); - - // Lower Middle - if (xMiddles) - p.drawImage(QRect(100+xOffset-pw/2, 100+height - yOffset +pw/2, width - xSide + pw, yOffset), rectImage, - QRect(rectImage.width()/2, rectImage.height() - yOffset, 1, yOffset)); - // Lower Right - p.drawImage(QPoint(100+width-xOffset+pw/2, 100+height - yOffset+pw/2), rectImage, - QRect(rectImage.width()-xOffset, rectImage.height() - yOffset, xOffset, yOffset)); - } - surface.save("tsg.png"); -} - -void tst_QmlPainting::drawTransformedTransparentImage_data() -{ - QTest::addColumn("imageType"); - - QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; - QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; -} - -void tst_QmlPainting::drawTransformedTransparentImage() -{ - QFETCH(int, imageType); - - //setup image - QImage transImage(200, 200, (QImage::Format)imageType); - transImage.fill(0); - - //setup surface - QImage surface(200, 200, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - - QBENCHMARK { - p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); - p.drawImage(0,0, transImage); - } -} - -void tst_QmlPainting::drawTransformedSemiTransparentImage_data() -{ - QTest::addColumn("imageType"); - - QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; - QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; -} - -void tst_QmlPainting::drawTransformedSemiTransparentImage() -{ - QFETCH(int, imageType); - - //setup image - QImage transImage(200, 200, (QImage::Format)imageType); - transImage.fill(QColor(0,0,0, 128).rgba()); - - //setup surface - QImage surface(200, 200, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - - QBENCHMARK { - p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); - p.drawImage(0,0, transImage); - } -} - -void tst_QmlPainting::drawTransformedFilledImage_data() -{ - QTest::addColumn("imageType"); - - QTest::newRow("imagetype=ARGB32_Pre") << (int)QImage::Format_ARGB32_Premultiplied; - QTest::newRow("imagetype=ARGB8565_Pre") << (int)QImage::Format_ARGB8565_Premultiplied; -} - -void tst_QmlPainting::drawTransformedFilledImage() -{ - QFETCH(int, imageType); - - //setup image - QImage filledImage(200, 200, (QImage::Format)imageType); - filledImage.fill(QColor(0,0,0).rgb()); - - //setup surface - QImage surface(200, 200, QImage::Format_RGB16); - surface.fill(QColor(255,255,255).rgb()); - QPainter p(&surface); - - QBENCHMARK { - p.setWorldTransform(QTransform(0.956957, 0, 0.000704124, 0, 1, 0, 16.141, 0, 0.735953)); - p.drawImage(0,0, filledImage); - } -} - -QTEST_MAIN(tst_QmlPainting) - -#include "tst_qmlpainting.moc" -- cgit v0.12 From e8c0632ba91a08573a0de4dad254ca6476495a12 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 14 Dec 2009 16:04:08 +1000 Subject: Fix leak. --- src/declarative/util/qmlopenmetaobject.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/declarative/util/qmlopenmetaobject.cpp b/src/declarative/util/qmlopenmetaobject.cpp index e66a3e7..373be2d 100644 --- a/src/declarative/util/qmlopenmetaobject.cpp +++ b/src/declarative/util/qmlopenmetaobject.cpp @@ -76,6 +76,8 @@ QmlOpenMetaObjectType::~QmlOpenMetaObjectType() { if (d->mem) qFree(d->mem); + if (d->cache) + d->cache->release(); delete d; } -- cgit v0.12 From 30767891615c1c9fc20e8a26da923f94d1728b4b Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 14 Dec 2009 16:30:07 +1000 Subject: Decode images loaded via network in a separate thread. --- .../graphicsitems/qmlgraphicsborderimage.cpp | 20 +- .../graphicsitems/qmlgraphicsimagebase.cpp | 14 +- .../graphicsitems/qmlgraphicsparticles.cpp | 11 +- src/declarative/util/qmlpixmapcache.cpp | 424 ++++++++++++++------- src/declarative/util/qmlpixmapcache_p.h | 44 ++- 5 files changed, 344 insertions(+), 169 deletions(-) diff --git a/src/declarative/graphicsitems/qmlgraphicsborderimage.cpp b/src/declarative/graphicsitems/qmlgraphicsborderimage.cpp index 01c3e37..877e141 100644 --- a/src/declarative/graphicsitems/qmlgraphicsborderimage.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsborderimage.cpp @@ -79,7 +79,7 @@ QmlGraphicsBorderImage::~QmlGraphicsBorderImage() if (d->sciReply) d->sciReply->deleteLater(); if (d->sciPendingPixmapCache) - QmlPixmapCache::cancelGet(d->sciurl, this); + QmlPixmapCache::cancel(d->sciurl, this); } /*! \qmlproperty enum BorderImage::status @@ -159,11 +159,11 @@ void QmlGraphicsBorderImage::setSource(const QUrl &url) } if (d->pendingPixmapCache) { - QmlPixmapCache::cancelGet(d->url, this); + QmlPixmapCache::cancel(d->url, this); d->pendingPixmapCache = false; } if (d->sciPendingPixmapCache) { - QmlPixmapCache::cancelGet(d->sciurl, this); + QmlPixmapCache::cancel(d->sciurl, this); d->sciPendingPixmapCache = false; } @@ -200,8 +200,9 @@ void QmlGraphicsBorderImage::setSource(const QUrl &url) this, SLOT(sciRequestFinished())); } } else { - QNetworkReply *reply = QmlPixmapCache::get(qmlEngine(this), d->url, &d->pix); - if (reply) { + QmlPixmapReply::Status status = QmlPixmapCache::get(d->url, &d->pix); + if (status != QmlPixmapReply::Ready && status != QmlPixmapReply::Error) { + QmlPixmapReply *reply = QmlPixmapCache::request(qmlEngine(this), d->url); d->pendingPixmapCache = true; connect(reply, SIGNAL(finished()), this, SLOT(requestFinished())); connect(reply, SIGNAL(downloadProgress(qint64,qint64)), @@ -319,8 +320,9 @@ void QmlGraphicsBorderImage::setGridScaledImage(const QmlGraphicsGridScaledImage d->verticalTileMode = sci.verticalTileRule(); d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl())); - QNetworkReply *reply = QmlPixmapCache::get(qmlEngine(this), d->sciurl, &d->pix); - if (reply) { + QmlPixmapReply::Status status = QmlPixmapCache::get(d->sciurl, &d->pix); + if (status != QmlPixmapReply::Ready && status != QmlPixmapReply::Error) { + QmlPixmapReply *reply = QmlPixmapCache::request(qmlEngine(this), d->sciurl); d->sciPendingPixmapCache = true; connect(reply, SIGNAL(finished()), this, SLOT(requestFinished())); connect(reply, SIGNAL(downloadProgress(qint64,qint64)), @@ -349,10 +351,10 @@ void QmlGraphicsBorderImage::requestFinished() if (d->url.path().endsWith(QLatin1String(".sci"))) { d->sciPendingPixmapCache = false; - QmlPixmapCache::find(d->sciurl, &d->pix); + QmlPixmapCache::get(d->sciurl, &d->pix); } else { d->pendingPixmapCache = false; - if (!QmlPixmapCache::find(d->url, &d->pix)) + if (QmlPixmapCache::get(d->url, &d->pix) != QmlPixmapReply::Ready) d->status = Error; } setImplicitWidth(d->pix.width()); diff --git a/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp b/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp index 70ca59c..9dd9f1b 100644 --- a/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsimagebase.cpp @@ -61,7 +61,7 @@ QmlGraphicsImageBase::~QmlGraphicsImageBase() { Q_D(QmlGraphicsImageBase); if (d->pendingPixmapCache) - QmlPixmapCache::cancelGet(d->url, this); + QmlPixmapCache::cancel(d->url, this); } QmlGraphicsImageBase::Status QmlGraphicsImageBase::status() const @@ -91,7 +91,7 @@ void QmlGraphicsImageBase::setSource(const QUrl &url) return; if (d->pendingPixmapCache) { - QmlPixmapCache::cancelGet(d->url, this); + QmlPixmapCache::cancel(d->url, this); d->pendingPixmapCache = false; } @@ -112,16 +112,16 @@ void QmlGraphicsImageBase::setSource(const QUrl &url) update(); } else { d->status = Loading; - bool ok = true; - QNetworkReply *reply = QmlPixmapCache::get(qmlEngine(this), d->url, &d->pix, &ok); - if (reply) { + QmlPixmapReply::Status status = QmlPixmapCache::get(d->url, &d->pix); + if (status != QmlPixmapReply::Ready && status != QmlPixmapReply::Error) { + QmlPixmapReply *reply = QmlPixmapCache::request(qmlEngine(this), d->url); d->pendingPixmapCache = true; connect(reply, SIGNAL(finished()), this, SLOT(requestFinished())); connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(requestProgress(qint64,qint64))); } else { //### should be unified with requestFinished - if (ok) { + if (status == QmlPixmapReply::Ready) { setImplicitWidth(d->pix.width()); setImplicitHeight(d->pix.height()); @@ -148,7 +148,7 @@ void QmlGraphicsImageBase::requestFinished() d->pendingPixmapCache = false; - if (!QmlPixmapCache::find(d->url, &d->pix)) + if (QmlPixmapCache::get(d->url, &d->pix) != QmlPixmapReply::Ready) d->status = Error; setImplicitWidth(d->pix.width()); setImplicitHeight(d->pix.height()); diff --git a/src/declarative/graphicsitems/qmlgraphicsparticles.cpp b/src/declarative/graphicsitems/qmlgraphicsparticles.cpp index 63c7658..8c5fb4f 100644 --- a/src/declarative/graphicsitems/qmlgraphicsparticles.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsparticles.cpp @@ -641,7 +641,7 @@ QmlGraphicsParticles::~QmlGraphicsParticles() { Q_D(QmlGraphicsParticles); if (d->pendingPixmapCache) - QmlPixmapCache::cancelGet(d->url, this); + QmlPixmapCache::cancel(d->url, this); } /*! @@ -663,7 +663,7 @@ void QmlGraphicsParticles::imageLoaded() { Q_D(QmlGraphicsParticles); d->pendingPixmapCache = false; - QmlPixmapCache::find(d->url, &d->image); + QmlPixmapCache::get(d->url, &d->image); d->paintItem->updateSize(); d->paintItem->update(); } @@ -676,7 +676,7 @@ void QmlGraphicsParticles::setSource(const QUrl &name) return; if (d->pendingPixmapCache) { - QmlPixmapCache::cancelGet(d->url, this); + QmlPixmapCache::cancel(d->url, this); d->pendingPixmapCache = false; } if (name.isEmpty()) { @@ -687,8 +687,9 @@ void QmlGraphicsParticles::setSource(const QUrl &name) } else { d->url = name; Q_ASSERT(!name.isRelative()); - QNetworkReply *reply = QmlPixmapCache::get(qmlEngine(this), d->url, &d->image); - if (reply) { + QmlPixmapReply::Status status = QmlPixmapCache::get(d->url, &d->image); + if (status != QmlPixmapReply::Ready && status != QmlPixmapReply::Error) { + QmlPixmapReply *reply = QmlPixmapCache::request(qmlEngine(this), d->url); connect(reply, SIGNAL(finished()), this, SLOT(imageLoaded())); d->pendingPixmapCache = true; } else { diff --git a/src/declarative/util/qmlpixmapcache.cpp b/src/declarative/util/qmlpixmapcache.cpp index 16e3dc8..ef40c7f 100644 --- a/src/declarative/util/qmlpixmapcache.cpp +++ b/src/declarative/util/qmlpixmapcache.cpp @@ -44,81 +44,164 @@ #include "qfxperf_p_p.h" #include +#include +#include #include #include #include #include #include +#include +#include +#include #include +#include QT_BEGIN_NAMESPACE -class QSharedNetworkReply; -typedef QHash QmlGraphicsSharedNetworkReplyHash; -static QmlGraphicsSharedNetworkReplyHash qfxActiveNetworkReplies; +class QmlImageReader : public QThread +{ + Q_OBJECT +public: + QmlImageReader(QObject *parent=0); + ~QmlImageReader(); + + void read(QmlPixmapReply *rep); + void cancel(QmlPixmapReply *rep); + +protected: + void run(); + +private: + struct Job { + Job() : reply(0), error(false) {} + QmlPixmapReply *reply; + QImage img; + bool error; + }; + + void loadImage(Job &job); + + QList jobs; + Job runningJob; + QMutex mutex; + QWaitCondition haveJob; + bool quit; +}; -class QSharedNetworkReply +class QmlImageDecodeEvent : public QCustomEvent { public: - QSharedNetworkReply(QNetworkReply *r) : reply(r), refCount(1) {} - ~QSharedNetworkReply() - { - reply->deleteLater(); + QmlImageDecodeEvent(bool err, QImage &img) : QCustomEvent(QEvent::User), error(err), image(img) {} + + bool error; + QImage image; +}; + +Q_GLOBAL_STATIC(QmlImageReader, qmlImageReader) + + +QmlImageReader::QmlImageReader(QObject *parent) : QThread(parent), quit(false) +{ + start(QThread::LowPriority); +} + +QmlImageReader::~QmlImageReader() +{ + quit = true; + haveJob.wakeOne(); +} + +void QmlImageReader::read(QmlPixmapReply *reply) +{ + mutex.lock(); + Job job; + job.reply = reply; + jobs.append(job); + haveJob.wakeOne(); + mutex.unlock(); +} + +void QmlImageReader::cancel(QmlPixmapReply *reply) +{ + mutex.lock(); + if (runningJob.reply != reply) { + QList::iterator it = jobs.begin(); + while (it != jobs.end()) { + if ((*it).reply == reply) { + jobs.erase(it); + break; + } + ++it; + } } - QNetworkReply *reply; - QPixmap pixmap; // ensure reference to pixmap to QPixmapCache does not discard + mutex.unlock(); +} - int refCount; - void addRef() - { - ++refCount; +void QmlImageReader::loadImage(Job &job) +{ + QImageReader imgio(job.reply->device()); + if (imgio.read(&job.img)) { + job.error = false; + } else { + job.error = true; + qWarning() << imgio.errorString(); } - void release() - { - Q_ASSERT(refCount > 0); - --refCount; - if (refCount == 0) { - QString key = reply->url().toString(); - qfxActiveNetworkReplies.remove(key); - delete this; - } +} + +void QmlImageReader::run() +{ + while (1) { + mutex.lock(); + if (!jobs.count()) + haveJob.wait(&mutex); + if (quit) + break; + runningJob = jobs.takeFirst(); + runningJob.reply->addRef(); + mutex.unlock(); + loadImage(runningJob); + mutex.lock(); + QCoreApplication::postEvent(runningJob.reply, new QmlImageDecodeEvent(runningJob.error, runningJob.img)); + runningJob.reply = 0; + mutex.unlock(); } -}; +} static bool readImage(QIODevice *dev, QPixmap *pixmap) - { - QImageReader imgio(dev); +{ + QImageReader imgio(dev); //#define QT_TEST_SCALED_SIZE #ifdef QT_TEST_SCALED_SIZE - /* - Some mechanism is needed for loading images at a limited size, especially - for remote images. Loading only thumbnails of remote progressive JPEG - images can be efficient. (Qt jpeg handler does not do so currently) - */ - - QSize limit(60,60); - QSize sz = imgio.size(); - if (sz.width() > limit.width() || sz.height() > limit.height()) { - sz.scale(limit,Qt::KeepAspectRatio); - imgio.setScaledSize(sz); - } + /* + Some mechanism is needed for loading images at a limited size, especially + for remote images. Loading only thumbnails of remote progressive JPEG + images can be efficient. (Qt jpeg handler does not do so currently) + */ + + QSize limit(60,60); + QSize sz = imgio.size(); + if (sz.width() > limit.width() || sz.height() > limit.height()) { + sz.scale(limit,Qt::KeepAspectRatio); + imgio.setScaledSize(sz); + } #endif - QImage img; - if (imgio.read(&img)) { + QImage img; + if (imgio.read(&img)) { #ifdef QT_TEST_SCALED_SIZE - if (!sz.isValid()) - img = img.scaled(limit,Qt::KeepAspectRatio); + if (!sz.isValid()) + img = img.scaled(limit,Qt::KeepAspectRatio); #endif - *pixmap = QPixmap::fromImage(img); - return true; - } else { - qWarning() << imgio.errorString(); - return false; - } + *pixmap = QPixmap::fromImage(img); + return true; + } else { + qWarning() << imgio.errorString(); + return false; } +} /*! \internal @@ -136,155 +219,208 @@ static QString toLocalFileOrQrc(const QUrl& url) return r; } -/*! - Finds the cached pixmap corresponding to \a url. - A previous call to get() must have requested the URL, - and the QNetworkReply must have finished before calling - this function. +typedef QHash QmlPixmapReplyHash; +static QmlPixmapReplyHash qmlActivePixmapReplies; - Returns true if the image was loaded without error. -*/ -bool QmlPixmapCache::find(const QUrl& url, QPixmap *pixmap) +class QmlPixmapReplyPrivate : public QObjectPrivate { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QmlPerfTimer perf; -#endif + Q_DECLARE_PUBLIC(QmlPixmapReply) - bool ok = true; -#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - QString lf = toLocalFileOrQrc(url); - if (!lf.isEmpty()) { - if (!QPixmapCache::find(lf,pixmap)) { - QFile f(lf); - if (f.open(QIODevice::ReadOnly)) { - if (!readImage(&f, pixmap)) { - qWarning() << "Format error loading" << url; - *pixmap = QPixmap(); - ok = false; - } else { - QPixmapCache::insert(lf, *pixmap); - ok = !pixmap->isNull(); - } - } else { - *pixmap = QPixmap(); - ok = false; - } - } else { - ok = !pixmap->isNull(); - } - return ok; +public: + QmlPixmapReplyPrivate(const QString &url, QNetworkReply *r) + : QObjectPrivate(), refCount(1), urlKey(url), reply(r), status(QmlPixmapReply::Loading) { } -#endif - QString key = url.toString(); - if (!QPixmapCache::find(key,pixmap)) { - QmlGraphicsSharedNetworkReplyHash::Iterator iter = qfxActiveNetworkReplies.find(key); - if (iter == qfxActiveNetworkReplies.end()) { - // API usage error - qWarning() << "QmlPixmapCache: URL not loaded" << url; - ok = false; - } else { - if ((*iter)->reply->error()) { - qWarning() << "Network error loading" << url << (*iter)->reply->errorString(); - *pixmap = QPixmap(); - ok = false; - } else if (!readImage((*iter)->reply, pixmap)) { - qWarning() << "Format error loading" << url; - *pixmap = QPixmap(); - ok = false; + int refCount; + QString urlKey; + QNetworkReply *reply; + QPixmap pixmap; // ensure reference to pixmap so QPixmapCache does not discard + QImage image; + QmlPixmapReply::Status status; +}; + + +QmlPixmapReply::QmlPixmapReply(const QString &key, QNetworkReply *reply) + : QObject(*new QmlPixmapReplyPrivate(key, reply), 0) +{ + Q_D(QmlPixmapReply); + connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), this, SIGNAL(downloadProgress(qint64,qint64))); + connect(d->reply, SIGNAL(finished()), this, SLOT(networkRequestDone())); +} + +QmlPixmapReply::~QmlPixmapReply() +{ + Q_D(QmlPixmapReply); + if (d->status == Decoding) + qmlImageReader()->cancel(this); + delete d->reply; +} + +void QmlPixmapReply::networkRequestDone() +{ + Q_D(QmlPixmapReply); + if (d->reply->error()) { + d->pixmap = QPixmap(); + d->status = Error; + emit finished(); + } else { + qmlImageReader()->read(this); + d->status = Decoding; + } +} + +bool QmlPixmapReply::event(QEvent *event) +{ + Q_D(QmlPixmapReply); + if (event->type() == QEvent::User) { + if (!release(true)) { + QmlImageDecodeEvent *de = static_cast(event); + d->status = de->error ? Error : Ready; + if (d->status == Ready) { + d->pixmap = QPixmap::fromImage(de->image); + QPixmapCache::insert(d->urlKey, d->pixmap); + d->image = QImage(); } else { - if ((*iter)->refCount > 1) - (*iter)->pixmap = *pixmap; + qWarning() << "Error decoding" << d->urlKey; } - (*iter)->release(); + emit finished(); } - QPixmapCache::insert(key, *pixmap); - } else { - ok = !pixmap->isNull(); - - // We may be the second finder. Still need to check for active replies. - QmlGraphicsSharedNetworkReplyHash::Iterator iter = qfxActiveNetworkReplies.find(key); - if (iter != qfxActiveNetworkReplies.end()) - (*iter)->release(); + return true; } - return ok; + + return QObject::event(event); } -/*! - Starts a network request to load \a url. +QmlPixmapReply::Status QmlPixmapReply::status() const +{ + Q_D(const QmlPixmapReply); + return d->status; +} + +QIODevice *QmlPixmapReply::device() +{ + Q_D(QmlPixmapReply); + return d->reply; +} + +void QmlPixmapReply::addRef() +{ + Q_D(QmlPixmapReply); + ++d->refCount; +} + +bool QmlPixmapReply::release(bool defer) +{ + Q_D(QmlPixmapReply); + Q_ASSERT(d->refCount > 0); + --d->refCount; + if (d->refCount == 0) { + qmlActivePixmapReplies.remove(d->urlKey); + if (defer) + deleteLater(); + else + delete this; + return true; + } - Returns a QNetworkReply if the image is not immediately available, otherwise - returns 0. Caller should connect to QNetworkReply::finished() to then call - find() when the image is available. + return false; +} - The returned QNetworkReply will be deleted when all get() calls are - matched by a corresponding find() call. +/*! + Finds the cached pixmap corresponding to \a url. + If the image is a network resource and has not yet + been retrieved and cached, request() must be called. - If the \a ok parameter is passed and \a url is a local file, - its value will be set to false if the pixmap could not be loaded; - otherwise the pixmap was loaded and *ok will be true. + Returns Ready, or Error if the image has been retrieved, + otherwise the current retrieval status. */ -QNetworkReply *QmlPixmapCache::get(QmlEngine *engine, const QUrl& url, QPixmap *pixmap, bool *ok) +QmlPixmapReply::Status QmlPixmapCache::get(const QUrl& url, QPixmap *pixmap) { + QmlPixmapReply::Status status = QmlPixmapReply::Unrequested; + #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML QString lf = toLocalFileOrQrc(url); if (!lf.isEmpty()) { + status = QmlPixmapReply::Ready; if (!QPixmapCache::find(lf,pixmap)) { - bool loaded = true; QFile f(lf); if (f.open(QIODevice::ReadOnly)) { if (!readImage(&f, pixmap)) { qWarning() << "Format error loading" << url; *pixmap = QPixmap(); - loaded = false; + status = QmlPixmapReply::Error; } } else { qWarning() << "Cannot open" << url; *pixmap = QPixmap(); - loaded = false; + status = QmlPixmapReply::Error; } - if (loaded) + if (status == QmlPixmapReply::Ready) QPixmapCache::insert(lf, *pixmap); - if (ok) *ok = loaded; } - return 0; + return status; } #endif QString key = url.toString(); - if (QPixmapCache::find(key,pixmap)) { - return 0; + QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies.find(key); + if (QPixmapCache::find(key, pixmap)) { + if (iter != qmlActivePixmapReplies.end()) { + status = (*iter)->status(); + (*iter)->release(); + } else { + status = pixmap->isNull() ? QmlPixmapReply::Error : QmlPixmapReply::Ready; + } + } else if (iter != qmlActivePixmapReplies.end()) { + status = QmlPixmapReply::Loading; } - QmlGraphicsSharedNetworkReplyHash::Iterator iter = qfxActiveNetworkReplies.find(key); - if (iter == qfxActiveNetworkReplies.end()) { + return status; +} + +/*! + Starts a network request to load \a url. + + Returns a QmlPixmapReply. Caller should connect to QmlPixmapReply::finished() + and call get() when the image is available. + + The returned QmlPixmapReply will be deleted when all request() calls are + matched by a corresponding get() call. +*/ +QmlPixmapReply *QmlPixmapCache::request(QmlEngine *engine, const QUrl &url) +{ + QString key = url.toString(); + QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies.find(key); + if (iter == qmlActivePixmapReplies.end()) { QNetworkRequest req(url); - QSharedNetworkReply *item = new QSharedNetworkReply(engine->networkAccessManager()->get(req)); - iter = qfxActiveNetworkReplies.insert(key, item); + QmlPixmapReply *item = new QmlPixmapReply(key, engine->networkAccessManager()->get(req)); + iter = qmlActivePixmapReplies.insert(key, item); } else { (*iter)->addRef(); } - return (*iter)->reply; + return (*iter); } /*! - Cancels a previous call to get(). + Cancels a previous call to request(). May also cancel loading (eg. if no other pending request). - Any connections from the QNetworkReply returned by get() to \a obj will be + Any connections from the QmlPixmapReply returned by request() to \a obj will be disconnected. */ -void QmlPixmapCache::cancelGet(const QUrl& url, QObject* obj) +void QmlPixmapCache::cancel(const QUrl& url, QObject *obj) { QString key = url.toString(); - QmlGraphicsSharedNetworkReplyHash::Iterator iter = qfxActiveNetworkReplies.find(key); - if (iter == qfxActiveNetworkReplies.end()) + QmlPixmapReplyHash::Iterator iter = qmlActivePixmapReplies.find(key); + if (iter == qmlActivePixmapReplies.end()) return; + + QmlPixmapReply *reply = *iter; if (obj) - QObject::disconnect((*iter)->reply, 0, obj, 0); - (*iter)->release(); + QObject::disconnect(reply, 0, obj, 0); + reply->release(); } /*! @@ -293,7 +429,9 @@ void QmlPixmapCache::cancelGet(const QUrl& url, QObject* obj) */ int QmlPixmapCache::pendingRequests() { - return qfxActiveNetworkReplies.count(); + return qmlActivePixmapReplies.count(); } +#include + QT_END_NAMESPACE diff --git a/src/declarative/util/qmlpixmapcache_p.h b/src/declarative/util/qmlpixmapcache_p.h index d2e272c..b71873f 100644 --- a/src/declarative/util/qmlpixmapcache_p.h +++ b/src/declarative/util/qmlpixmapcache_p.h @@ -53,17 +53,51 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QmlEngine; class QNetworkReply; -class Q_DECLARATIVE_EXPORT QmlPixmapCache + +class QmlPixmapReplyPrivate; +class QmlPixmapReply : public QObject { + Q_OBJECT public: - static QNetworkReply *get(QmlEngine *, const QUrl& url, QPixmap *pixmap, bool *ok=0); - static void cancelGet(const QUrl& url, QObject* obj); + QmlPixmapReply(const QString &key, QNetworkReply *reply); + ~QmlPixmapReply(); + + enum Status { Ready, Error, Unrequested, Loading, Decoding }; + Status status() const; + +Q_SIGNALS: + void finished(); + void downloadProgress(qint64, qint64); - static bool find(const QUrl& url, QPixmap *pixmap); // url must have been passed to QmlPixmapCache::get, and any returned reply finished. +protected: + bool event(QEvent *event); - static int pendingRequests(); // mainly for test verification +private: + QIODevice *device(); + void addRef(); + bool release(bool defer=false); + +private Q_SLOTS: + void networkRequestDone(); + +private: + Q_DISABLE_COPY(QmlPixmapReply) + Q_DECLARE_PRIVATE(QmlPixmapReply) + friend class QmlImageReader; + friend class QmlPixmapCache; }; +class QmlPixmapCache +{ +public: + static QmlPixmapReply::Status get(const QUrl& url, QPixmap *pixmap); + static QmlPixmapReply *request(QmlEngine *, const QUrl& url); + static void cancel(const QUrl& url, QObject *obj); + static int pendingRequests(); +}; + + + QT_END_NAMESPACE QT_END_HEADER -- cgit v0.12 From 33dd183f27967250a10da235b0269a7af14751e9 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 14 Dec 2009 16:47:55 +1000 Subject: Compile. --- src/declarative/util/qmlpixmapcache.cpp | 1 + src/declarative/util/qmlpixmapcache_p.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/declarative/util/qmlpixmapcache.cpp b/src/declarative/util/qmlpixmapcache.cpp index ef40c7f..85bf53c 100644 --- a/src/declarative/util/qmlpixmapcache.cpp +++ b/src/declarative/util/qmlpixmapcache.cpp @@ -55,6 +55,7 @@ #include #include #include +#include #include #include diff --git a/src/declarative/util/qmlpixmapcache_p.h b/src/declarative/util/qmlpixmapcache_p.h index b71873f..4dcafcf 100644 --- a/src/declarative/util/qmlpixmapcache_p.h +++ b/src/declarative/util/qmlpixmapcache_p.h @@ -55,7 +55,7 @@ class QmlEngine; class QNetworkReply; class QmlPixmapReplyPrivate; -class QmlPixmapReply : public QObject +class Q_DECLARATIVE_EXPORT QmlPixmapReply : public QObject { Q_OBJECT public: @@ -87,7 +87,7 @@ private: friend class QmlPixmapCache; }; -class QmlPixmapCache +class Q_DECLARATIVE_EXPORT QmlPixmapCache { public: static QmlPixmapReply::Status get(const QUrl& url, QPixmap *pixmap); -- cgit v0.12 From 087bfb51618e8a02a3fad263a963c3485d08294a Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 14 Dec 2009 16:52:28 +1000 Subject: Don't rely on Qt3Support --- src/declarative/util/qmlpixmapcache.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/declarative/util/qmlpixmapcache.cpp b/src/declarative/util/qmlpixmapcache.cpp index 85bf53c..0115a7c 100644 --- a/src/declarative/util/qmlpixmapcache.cpp +++ b/src/declarative/util/qmlpixmapcache.cpp @@ -55,7 +55,6 @@ #include #include #include -#include #include #include @@ -91,10 +90,10 @@ private: bool quit; }; -class QmlImageDecodeEvent : public QCustomEvent +class QmlImageDecodeEvent : public QEvent { public: - QmlImageDecodeEvent(bool err, QImage &img) : QCustomEvent(QEvent::User), error(err), image(img) {} + QmlImageDecodeEvent(bool err, QImage &img) : QEvent(QEvent::User), error(err), image(img) {} bool error; QImage image; -- cgit v0.12 From 690b72b7c3707f3a8f0120c35f3a4c34b58ff596 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 14 Dec 2009 17:33:04 +1000 Subject: Fix image and pixmapcache tests. --- src/declarative/util/qmlpixmapcache.cpp | 4 ++- .../qmlgraphicsimage/tst_qmlgraphicsimage.cpp | 2 +- .../qmlpixmapcache/tst_qmlpixmapcache.cpp | 32 +++++++++++++--------- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/declarative/util/qmlpixmapcache.cpp b/src/declarative/util/qmlpixmapcache.cpp index 0115a7c..99bcb7b 100644 --- a/src/declarative/util/qmlpixmapcache.cpp +++ b/src/declarative/util/qmlpixmapcache.cpp @@ -262,6 +262,8 @@ void QmlPixmapReply::networkRequestDone() if (d->reply->error()) { d->pixmap = QPixmap(); d->status = Error; + QPixmapCache::insert(d->urlKey, d->pixmap); + qWarning() << "Network error loading" << d->urlKey << d->reply->errorString(); emit finished(); } else { qmlImageReader()->read(this); @@ -278,11 +280,11 @@ bool QmlPixmapReply::event(QEvent *event) d->status = de->error ? Error : Ready; if (d->status == Ready) { d->pixmap = QPixmap::fromImage(de->image); - QPixmapCache::insert(d->urlKey, d->pixmap); d->image = QImage(); } else { qWarning() << "Error decoding" << d->urlKey; } + QPixmapCache::insert(d->urlKey, d->pixmap); emit finished(); } return true; diff --git a/tests/auto/declarative/qmlgraphicsimage/tst_qmlgraphicsimage.cpp b/tests/auto/declarative/qmlgraphicsimage/tst_qmlgraphicsimage.cpp index c8a2d3f..26f5175 100644 --- a/tests/auto/declarative/qmlgraphicsimage/tst_qmlgraphicsimage.cpp +++ b/tests/auto/declarative/qmlgraphicsimage/tst_qmlgraphicsimage.cpp @@ -118,7 +118,7 @@ void tst_qmlgraphicsimage::imageSource_data() << "Cannot open QUrl( \"file://" SRCDIR "/data/no-such-file.png\" ) "; QTest::newRow("remote") << SERVER_ADDR "/colors.png" << true << ""; QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << true - << "Network error loading QUrl( \"" SERVER_ADDR "/no-such-file.png\" ) " + << "Network error loading \"" SERVER_ADDR "/no-such-file.png\" " "\"Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found\" "; } diff --git a/tests/auto/declarative/qmlpixmapcache/tst_qmlpixmapcache.cpp b/tests/auto/declarative/qmlpixmapcache/tst_qmlpixmapcache.cpp index a26b097..1951833 100644 --- a/tests/auto/declarative/qmlpixmapcache/tst_qmlpixmapcache.cpp +++ b/tests/auto/declarative/qmlpixmapcache/tst_qmlpixmapcache.cpp @@ -122,8 +122,8 @@ void tst_qmlpixmapcache::single() QFETCH(bool, neterror); if (neterror) { - QString expected = "Network error loading QUrl( \"" - +target.toString()+"\" ) \"Error downloading " + QString expected = "Network error loading \"" + +target.toString()+"\" \"Error downloading " +target.toString()+" - server replied: Not Found\" "; QTest::ignoreMessage(QtWarningMsg, expected.toLatin1()); } else if (!exists) { @@ -133,15 +133,18 @@ void tst_qmlpixmapcache::single() QPixmap pixmap; QVERIFY(pixmap.width() <= 0); // Check Qt assumption - QNetworkReply *reply= QmlPixmapCache::get(&engine, target, &pixmap); + QmlPixmapReply::Status status = QmlPixmapCache::get(target, &pixmap); if (incache) { - QVERIFY(!reply); - if (exists) + if (exists) { + QVERIFY(status == QmlPixmapReply::Ready); QVERIFY(pixmap.width() > 0); - else + } else { + QVERIFY(status == QmlPixmapReply::Error); QVERIFY(pixmap.width() <= 0); + } } else { + QmlPixmapReply *reply = QmlPixmapCache::request(&engine, target); QVERIFY(reply); QVERIFY(pixmap.width() <= 0); @@ -151,10 +154,10 @@ void tst_qmlpixmapcache::single() QVERIFY(!QTestEventLoop::instance().timeout()); QVERIFY(getter.gotslot); if (exists) { - QVERIFY(QmlPixmapCache::find(target, &pixmap)); + QVERIFY(QmlPixmapCache::get(target, &pixmap) == QmlPixmapReply::Ready); QVERIFY(pixmap.width() > 0); } else { - QVERIFY(!QmlPixmapCache::find(target, &pixmap)); + QVERIFY(QmlPixmapCache::get(target, &pixmap) == QmlPixmapReply::Error); QVERIFY(pixmap.width() <= 0); } } @@ -225,12 +228,15 @@ void tst_qmlpixmapcache::parallel() QList targets; targets << target1 << target2; - QList replies; + QList replies; QList getters; for (int i=0; i 0); @@ -246,7 +252,7 @@ void tst_qmlpixmapcache::parallel() QCOMPARE(QmlPixmapCache::pendingRequests(), requests); if (cancel >= 0) { - QmlPixmapCache::cancelGet(targets.at(cancel), getters[cancel]); + QmlPixmapCache::cancel(targets.at(cancel), getters[cancel]); slotters--; } @@ -256,14 +262,14 @@ void tst_qmlpixmapcache::parallel() } for (int i=0; igotslot); } else { QVERIFY(getters[i]->gotslot); QPixmap pixmap; - QVERIFY(QmlPixmapCache::find(targets[i], &pixmap)); + QVERIFY(QmlPixmapCache::get(targets[i], &pixmap) == QmlPixmapReply::Ready); QVERIFY(pixmap.width() > 0); } delete getters[i]; -- cgit v0.12