diff options
author | Alexandru Croitor <alexandru.croitor@qt.io> | 2019-06-17 13:28:57 +0200 |
---|---|---|
committer | Alexandru Croitor <alexandru.croitor@qt.io> | 2019-06-17 13:29:56 +0200 |
commit | f33a29a8dbe03cbe9e59f9e5124f15e90b6336fc (patch) | |
tree | 09ba56a3338604358e53c7a33c35d29dc32860a6 /tests | |
parent | 3864601f76e0b212ec69ad64409d939fd021fbd2 (diff) | |
parent | 5c298ef5bea0930b68263ba84194250dbb9d26a9 (diff) | |
download | qtsvg-f33a29a8dbe03cbe9e59f9e5124f15e90b6336fc.tar.gz |
Merge remote-tracking branch 'origin/wip/qt6' into wip/cmake
Change-Id: Icb0da709c1cb8d2bdc2f33edfe656b7821cb148a
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp | 110 | ||||
-rw-r--r-- | tests/libfuzzer/svg/qsvgrenderer/render/main.cpp | 42 | ||||
-rw-r--r-- | tests/libfuzzer/svg/qsvgrenderer/render/render.pro | 3 | ||||
-rw-r--r-- | tests/manual/rendertestsuite/.gitignore | 2 | ||||
-rw-r--r-- | tests/manual/rendertestsuite/README | 32 | ||||
-rw-r--r-- | tests/manual/rendertestsuite/main.cpp | 139 | ||||
-rw-r--r-- | tests/manual/rendertestsuite/rendertestsuite.pro | 3 |
7 files changed, 315 insertions, 16 deletions
diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp index 553838e..cf19213 100644 --- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp @@ -67,6 +67,8 @@ private slots: void boundsOnElement() const; void gradientStops() const; void gradientRefs(); + void recursiveRefs_data(); + void recursiveRefs(); void fillRule(); void opacity(); void paths(); @@ -77,6 +79,7 @@ private slots: void testUseElement(); void smallFont(); void styleSheet(); + void duplicateStyleId(); #ifndef QT_NO_COMPRESS void testGzLoading(); @@ -139,22 +142,28 @@ void tst_QSvgRenderer::invalidUrl_data() { QTest::addColumn<QByteArray>("svg"); - QTest::newRow("00") << QByteArray("<svg><circle fill=\"url\" /></svg>"); - QTest::newRow("01") << QByteArray("<svg><circle fill=\"url0\" /></svg>"); - QTest::newRow("02") << QByteArray("<svg><circle fill=\"url(0\" /></svg>"); - QTest::newRow("03") << QByteArray("<svg><circle fill=\"url (0\" /></svg>"); - QTest::newRow("04") << QByteArray("<svg><circle fill=\"url ( 0\" /></svg>"); - QTest::newRow("05") << QByteArray("<svg><circle fill=\"url#\" /></svg>"); - QTest::newRow("06") << QByteArray("<svg><circle fill=\"url#(\" /></svg>"); - QTest::newRow("07") << QByteArray("<svg><circle fill=\"url(#\" /></svg>"); - QTest::newRow("08") << QByteArray("<svg><circle fill=\"url(# \" /></svg>"); - QTest::newRow("09") << QByteArray("<svg><circle fill=\"url(# 0\" /></svg>"); + QTest::newRow("01") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url0\" /></svg>"); + QTest::newRow("02") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url(0\" /></svg>"); + QTest::newRow("03") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url (0\" /></svg>"); + QTest::newRow("04") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url ( 0\" /></svg>"); + QTest::newRow("05") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url#\" /></svg>"); + QTest::newRow("06") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url#(\" /></svg>"); + QTest::newRow("07") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url(#\" /></svg>"); + QTest::newRow("08") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url(# \" /></svg>"); + QTest::newRow("09") << QByteArray("<svg><linearGradient id=\"0\"/><circle fill=\"url(# 0\" /></svg>"); + QTest::newRow("10") << QByteArray("<svg><linearGradient id=\"blabla\"/><circle fill=\"urlblabla\" /></svg>"); + QTest::newRow("11") << QByteArray("<svg><linearGradient id=\"blabla\"/><circle fill=\"url(blabla\" /></svg>"); + QTest::newRow("12") << QByteArray("<svg><linearGradient id=\"blabla\"/><circle fill=\"url(blabla)\" /></svg>"); + QTest::newRow("13") << QByteArray("<svg><linearGradient id=\"blabla\"/><circle fill=\"url(#blabla\" /></svg>"); } void tst_QSvgRenderer::invalidUrl() { QFETCH(QByteArray, svg); +#if QT_CONFIG(regularexpression) + QTest::ignoreMessage(QtWarningMsg, QRegularExpression("Could not resolve property")); +#endif QSvgRenderer renderer(svg); QVERIFY(renderer.isValid()); } @@ -259,6 +268,16 @@ void tst_QSvgRenderer::testMapViewBoxToTarget() QCOMPARE(picture.boundingRect(), QRect(125, 125, 250, 250)); } + { // Viewport and viewBox specified -> scale 500x500 square to 1000x750 while preserving aspect ratio gives 750x750 + // however the box is centered at 375, 250 + data = "<svg width=\"1000\" height=\"750\" viewBox=\"-250 -250 500 500\"><g><rect x=\"0\" y=\"0\" width=\"500\" height=\"500\" /></g></svg>"; + QPicture picture; + QPainter painter(&picture); + QSvgRenderer rend(data); + rend.render(&painter); + painter.end(); + QCOMPARE(picture.boundingRect(), QRect(375, 250, 750, 750)); + } } void tst_QSvgRenderer::testRenderElement() @@ -476,15 +495,15 @@ void tst_QSvgRenderer::matrixForElement() const QPainter painter(&image); QSvgRenderer renderer(data); - compareTransforms(QTransform(painter.worldMatrix()), QTransform(renderer.matrixForElement(QLatin1String("ichi")))); + compareTransforms(painter.worldTransform(), QTransform(renderer.matrixForElement(QLatin1String("ichi")))); painter.translate(-3, 1); - compareTransforms(QTransform(painter.worldMatrix()), QTransform(renderer.matrixForElement(QLatin1String("ni")))); + compareTransforms(painter.worldTransform(), QTransform(renderer.matrixForElement(QLatin1String("ni")))); painter.rotate(45); - compareTransforms(QTransform(painter.worldMatrix()), QTransform(renderer.matrixForElement(QLatin1String("san")))); + compareTransforms(painter.worldTransform(), QTransform(renderer.matrixForElement(QLatin1String("san")))); painter.scale(4, 2); - compareTransforms(QTransform(painter.worldMatrix()), QTransform(renderer.matrixForElement(QLatin1String("yon")))); - painter.setWorldMatrix(QMatrix(1, 2, 3, 4, 5, 6), true); - compareTransforms(QTransform(painter.worldMatrix()), QTransform(renderer.matrixForElement(QLatin1String("firkant")))); + compareTransforms(painter.worldTransform(), QTransform(renderer.matrixForElement(QLatin1String("yon")))); + painter.setWorldTransform(QTransform(1, 2, 3, 4, 5, 6), true); + compareTransforms(painter.worldTransform(), QTransform(renderer.matrixForElement(QLatin1String("firkant")))); } void tst_QSvgRenderer::boundsOnElement() const @@ -667,6 +686,43 @@ void tst_QSvgRenderer::gradientRefs() } } +void tst_QSvgRenderer::recursiveRefs_data() +{ + QTest::addColumn<QByteArray>("svg"); + + QTest::newRow("single") << QByteArray("<svg>" + "<linearGradient id='0' xlink:href='#0'/>" + "<rect x='0' y='0' width='20' height='20' fill='url(#0)'/>" + "</svg>"); + + QTest::newRow("double") << QByteArray("<svg>" + "<linearGradient id='0' xlink:href='#1'/>" + "<linearGradient id='1' xlink:href='#0'/>" + "<rect x='0' y='0' width='20' height='20' fill='url(#0)'/>" + "</svg>"); + + QTest::newRow("triple") << QByteArray("<svg>" + "<linearGradient id='0' xlink:href='#1'/>" + "<linearGradient id='1' xlink:href='#2'/>" + "<linearGradient id='2' xlink:href='#0'/>" + "<rect x='0' y='0' width='20' height='20' fill='url(#0)'/>" + "</svg>"); +} + +void tst_QSvgRenderer::recursiveRefs() +{ + QFETCH(QByteArray, svg); + + QImage image(20, 20, QImage::Format_ARGB32_Premultiplied); + image.fill(Qt::green); + QImage refImage = image.copy(); + + QSvgRenderer renderer(svg); + QPainter painter(&image); + renderer.render(&painter); + QCOMPARE(image, refImage); +} + #ifndef QT_NO_COMPRESS void tst_QSvgRenderer::testGzLoading() @@ -1377,6 +1433,16 @@ void tst_QSvgRenderer::testUseElement() " <circle fill=\"#a6ce39\" cx=\"0\" cy=\"0\" r=\"33\" />" " </g>" " </defs>" + "</svg>", + // 17 - Indirect self referral + "<svg>" + " <defs>" + " <g id=\"g0\">" + " <g id=\"g1\"><use href=\"#g2\"/></g>" + " <g id=\"g2\"><use href=\"#g1\"/></g>" + " </g>" + " </defs>" + " <use xlink:href=\"#g0\" fill=\"black\"/>" "</svg>" }; @@ -1459,5 +1525,17 @@ void tst_QSvgRenderer::styleSheet() QCOMPARE(images[0], images[1]); } +void tst_QSvgRenderer::duplicateStyleId() +{ + QByteArray svg = QByteArrayLiteral("<svg><linearGradient id=\"a\"/>" + "<rect style=\"fill:url(#a)\"/>" + "<linearGradient id=\"a\"/></svg>"); + QTest::ignoreMessage(QtWarningMsg, "Duplicate unique style id: \"a\""); + QImage image(200, 200, QImage::Format_RGB32); + QPainter painter(&image); + QSvgRenderer renderer(svg); + renderer.render(&painter); +} + QTEST_MAIN(tst_QSvgRenderer) #include "tst_qsvgrenderer.moc" diff --git a/tests/libfuzzer/svg/qsvgrenderer/render/main.cpp b/tests/libfuzzer/svg/qsvgrenderer/render/main.cpp new file mode 100644 index 0000000..0197115 --- /dev/null +++ b/tests/libfuzzer/svg/qsvgrenderer/render/main.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> +#include <QImage> +#include <QPainter> +#include <QSvgRenderer> + +extern "C" int LLVMFuzzerTestOneInput(const char *Data, size_t Size) { + static int c = 0; + static QApplication a(c, nullptr); + static QImage image(377, 233, QImage::Format_RGB32); + static QPainter painter(&image); + QSvgRenderer renderer(QByteArray(Data, Size)); + renderer.render(&painter); + return 0; +} diff --git a/tests/libfuzzer/svg/qsvgrenderer/render/render.pro b/tests/libfuzzer/svg/qsvgrenderer/render/render.pro new file mode 100644 index 0000000..be94755 --- /dev/null +++ b/tests/libfuzzer/svg/qsvgrenderer/render/render.pro @@ -0,0 +1,3 @@ +QT += svg +SOURCES += main.cpp +LIBS += -fsanitize=fuzzer diff --git a/tests/manual/rendertestsuite/.gitignore b/tests/manual/rendertestsuite/.gitignore new file mode 100644 index 0000000..54f7094 --- /dev/null +++ b/tests/manual/rendertestsuite/.gitignore @@ -0,0 +1,2 @@ +baseline +difference diff --git a/tests/manual/rendertestsuite/README b/tests/manual/rendertestsuite/README new file mode 100644 index 0000000..0609d4f --- /dev/null +++ b/tests/manual/rendertestsuite/README @@ -0,0 +1,32 @@ +This little helper program can be used together with the SVG Tiny 1.2 test +suite to determine the visual impact of changes to the renderer on the basis of +the test suite. + +Suppose you have the test suite installed in ~/tests, then you can create a +base line of renderings of all the SVG images by running + + mkdir baseline + ./rendertestsuite create-baseline ~/tests + +and the output will be stored in the 'baseline/' sub-directory. + +After making changes to the renderer, you can create a new set of images by running + + mkdir difference + ./rendertestsuite diff ~/tests + +and side-by-side images of the old and the new images in case they differ will +be stored in the sub-directory 'difference/'. + +An easy way to inspect the output is by using KDE's gwenview: + + gwenview difference/ + + +Note that due to rounding errors there will always be subtle differences, even +when not doing any changes to the renderer. + + +You can find the test suite at + + https://www.w3.org/Graphics/SVG/WG/wiki/Test_Suite_Overview#SVG_1.2_Tiny_Test_Suite:_12_September_2008 diff --git a/tests/manual/rendertestsuite/main.cpp b/tests/manual/rendertestsuite/main.cpp new file mode 100644 index 0000000..dfdf88c --- /dev/null +++ b/tests/manual/rendertestsuite/main.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt SVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore> +#include <QtSvg> +#include <QtGui> +#include <stdlib.h> + +static QImage render(const QString &filePath) +{ + fprintf(stdout, "Rendering %s\n", qPrintable(filePath)); + QSvgRenderer renderer(filePath); + if (!renderer.isValid()) { + fprintf(stderr, "Could not load SVG file %s\n", qPrintable(filePath)); + return QImage(); + } + QImage image(480, 360, QImage::Format_ARGB32); + image.fill(Qt::transparent); + { + QPainter p(&image); + renderer.render(&p); + } + return image; +} + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + QCommandLineParser parser; + parser.addHelpOption(); + parser.addPositionalArgument(QLatin1String("command"), QLatin1String("[create-baseline,diff]")); + parser.addPositionalArgument(QLatin1String("path-to-svg-testsuite"), QLatin1String("Path to the svg/ sub-directory of the test suite")); + + parser.process(app); + + const auto args = parser.positionalArguments(); + + if (args.count() != 2) { + parser.showHelp(EXIT_FAILURE); + return EXIT_FAILURE; // never reached + } + + const QString commandAsString = args.at(0); + const QString sourcePath = args.at(1); + + QDirIterator sourceFileIterator(sourcePath, QStringList(QLatin1String("*.svg")), QDir::Files); + const QString baselinePath = "baseline"; + + const auto referenceFilePath = [baselinePath](const QFileInfo &testCaseFileInfo) -> QString { + return baselinePath + QLatin1Char('/') + testCaseFileInfo.baseName() + QLatin1String(".png"); + }; + + if (commandAsString == "create-baseline") { + while (sourceFileIterator.hasNext()) { + sourceFileIterator.next(); + + QImage image = render(sourceFileIterator.filePath()); + if (image.isNull()) + return EXIT_FAILURE; + QString outputFileName = referenceFilePath(sourceFileIterator.fileInfo()); + if (!image.save(outputFileName)) { + fprintf(stderr, "Could not save PNG file %s\n", qPrintable(outputFileName)); + return EXIT_FAILURE; + } + } + } else if (commandAsString == "diff") { + while (sourceFileIterator.hasNext()) { + sourceFileIterator.next(); + + QImage actual = render(sourceFileIterator.filePath()); + const QString referencePath = referenceFilePath(sourceFileIterator.fileInfo()); + QImage reference; + if (!reference.load(referencePath)) { + fprintf(stderr, "Could not load reference file %s\n", qPrintable(referencePath)); + return EXIT_FAILURE; + } + + if (actual == reference) + continue; + + QImage sideBySideImage(actual.width() * 2, actual.height(), QImage::Format_ARGB32); + sideBySideImage.fill(Qt::transparent); + { + QPainter p(&sideBySideImage); + p.drawImage(0, 0, actual); + p.drawImage(actual.width(), 0, reference); + } + + const QString sideBySideFileName = "difference/" + sourceFileIterator.fileInfo().baseName() + QLatin1String(".png"); + if (!sideBySideImage.save(sideBySideFileName)) { + fprintf(stderr, "Could not save side-by-side image at %s\n", qPrintable(sideBySideFileName)); + return EXIT_FAILURE; + } + } + } else { + fprintf(stderr, "Unknown command %s\n", qPrintable(commandAsString)); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + diff --git a/tests/manual/rendertestsuite/rendertestsuite.pro b/tests/manual/rendertestsuite/rendertestsuite.pro new file mode 100644 index 0000000..855d3fc --- /dev/null +++ b/tests/manual/rendertestsuite/rendertestsuite.pro @@ -0,0 +1,3 @@ +TEMPLATE = app +QT = core gui svg +SOURCES = main.cpp |