tests/auto/qsvggenerator/tst_qsvggenerator.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #include <QtTest/QtTest>
       
    44 
       
    45 #include <QDomDocument>
       
    46 #include <QDomElement>
       
    47 #include <QDomNode>
       
    48 
       
    49 #include <qapplication.h>
       
    50 #include <qdebug.h>
       
    51 #include <qpainter.h>
       
    52 #include <qsvggenerator.h>
       
    53 #include <qsvgrenderer.h>
       
    54 
       
    55 //TESTED_CLASS=
       
    56 //TESTED_FILES=
       
    57 
       
    58 #ifdef Q_OS_SYMBIAN
       
    59 #define SRCDIR ""
       
    60 #endif
       
    61 
       
    62 class tst_QSvgGenerator : public QObject
       
    63 {
       
    64 Q_OBJECT
       
    65 
       
    66 public:
       
    67     tst_QSvgGenerator();
       
    68     virtual ~tst_QSvgGenerator();
       
    69 
       
    70 private slots:
       
    71     void construction();
       
    72     void fileName();
       
    73     void outputDevice();
       
    74     void sizeAndViewBox();
       
    75     void metric();
       
    76     void radialGradient();
       
    77     void fileEncoding();
       
    78     void fractionalFontSize();
       
    79     void titleAndDescription();
       
    80     void gradientInterpolation();
       
    81 };
       
    82 
       
    83 tst_QSvgGenerator::tst_QSvgGenerator()
       
    84 {
       
    85 }
       
    86 
       
    87 tst_QSvgGenerator::~tst_QSvgGenerator()
       
    88 {
       
    89     QFile::remove(QLatin1String("fileName_output.svg"));
       
    90     QFile::remove(QLatin1String("outputDevice_output.svg"));
       
    91     QFile::remove(QLatin1String("radial_gradient.svg"));
       
    92 }
       
    93 
       
    94 void tst_QSvgGenerator::construction()
       
    95 {
       
    96     QSvgGenerator generator;
       
    97     QCOMPARE(generator.fileName(), QString());
       
    98     QCOMPARE(generator.outputDevice(), (QIODevice *)0);
       
    99     QCOMPARE(generator.resolution(), 72);
       
   100     QCOMPARE(generator.size(), QSize());
       
   101 }
       
   102 
       
   103 static void removeAttribute(const QDomNode &node, const QString &attribute)
       
   104 {
       
   105     if (node.isNull())
       
   106         return;
       
   107 
       
   108     node.toElement().removeAttribute(attribute);
       
   109 
       
   110     removeAttribute(node.firstChild(), attribute);
       
   111     removeAttribute(node.nextSibling(), attribute);
       
   112 }
       
   113 
       
   114 static void compareWithoutFontInfo(const QByteArray &source, const QByteArray &reference)
       
   115 {
       
   116     QDomDocument sourceDoc;
       
   117     sourceDoc.setContent(source);
       
   118 
       
   119     QDomDocument referenceDoc;
       
   120     referenceDoc.setContent(reference);
       
   121 
       
   122     QList<QString> fontAttributes;
       
   123     fontAttributes << "font-family" << "font-size" << "font-weight" << "font-style";
       
   124 
       
   125     foreach (QString attribute, fontAttributes) {
       
   126         removeAttribute(sourceDoc, attribute);
       
   127         removeAttribute(referenceDoc, attribute);
       
   128     }
       
   129 
       
   130     QCOMPARE(sourceDoc.toByteArray(), referenceDoc.toByteArray());
       
   131 }
       
   132 
       
   133 static void checkFile(const QString &fileName)
       
   134 {
       
   135     QVERIFY(QFile::exists(fileName));;
       
   136 
       
   137     QFile file(fileName);
       
   138     QVERIFY(file.open(QIODevice::ReadOnly));
       
   139 
       
   140     QFile referenceFile(SRCDIR "referenceSvgs/" + fileName);
       
   141     QVERIFY(referenceFile.open(QIODevice::ReadOnly));
       
   142 
       
   143     compareWithoutFontInfo(file.readAll(), referenceFile.readAll());
       
   144 }
       
   145 
       
   146 void tst_QSvgGenerator::fileName()
       
   147 {
       
   148     QString fileName = "fileName_output.svg";
       
   149     QFile::remove(fileName);
       
   150 
       
   151     QSvgGenerator generator;
       
   152     generator.setFileName(fileName);
       
   153     QCOMPARE(generator.fileName(), fileName);
       
   154 
       
   155     QPainter painter(&generator);
       
   156     painter.fillRect(0, 0, 100, 100, Qt::red);
       
   157     painter.end();
       
   158 
       
   159     checkFile(fileName);
       
   160 }
       
   161 
       
   162 void tst_QSvgGenerator::outputDevice()
       
   163 {
       
   164     QString fileName = "outputDevice_output.svg";
       
   165     QFile::remove(fileName);
       
   166 
       
   167     QFile file(fileName);
       
   168 
       
   169     {
       
   170         // Device is not open
       
   171         QSvgGenerator generator;
       
   172         generator.setOutputDevice(&file);
       
   173         QCOMPARE(generator.outputDevice(), (QIODevice *)&file);
       
   174 
       
   175         QPainter painter;
       
   176         QVERIFY(painter.begin(&generator));
       
   177         QCOMPARE(file.openMode(), QIODevice::OpenMode(QIODevice::Text | QIODevice::WriteOnly));
       
   178         file.close();
       
   179     }
       
   180     {
       
   181         // Device is not open, WriteOnly
       
   182         file.open(QIODevice::WriteOnly);
       
   183 
       
   184         QSvgGenerator generator;
       
   185         generator.setOutputDevice(&file);
       
   186         QCOMPARE(generator.outputDevice(), (QIODevice *)&file);
       
   187 
       
   188         QPainter painter;
       
   189         QVERIFY(painter.begin(&generator));
       
   190         QCOMPARE(file.openMode(), QIODevice::OpenMode(QIODevice::WriteOnly));
       
   191         file.close();
       
   192     }
       
   193     {
       
   194         // Device is not open, ReadOnly
       
   195         file.open(QIODevice::ReadOnly);
       
   196 
       
   197         QSvgGenerator generator;
       
   198         generator.setOutputDevice(&file);
       
   199         QCOMPARE(generator.outputDevice(), (QIODevice *)&file);
       
   200 
       
   201         QPainter painter;
       
   202         QTest::ignoreMessage(QtWarningMsg, "QSvgPaintEngine::begin(), could not write to read-only output device: 'Unknown error'");
       
   203         QVERIFY(!painter.begin(&generator));
       
   204         QCOMPARE(file.openMode(), QIODevice::OpenMode(QIODevice::ReadOnly));
       
   205         file.close();
       
   206     }
       
   207 }
       
   208 
       
   209 void tst_QSvgGenerator::sizeAndViewBox()
       
   210 {
       
   211     { // Setting neither properties should result in
       
   212       // none of the attributes written to the SVG
       
   213         QSvgGenerator generator;
       
   214         QByteArray byteArray;
       
   215         QBuffer buffer(&byteArray);
       
   216         generator.setOutputDevice(&buffer);
       
   217         QPainter painter(&generator);
       
   218         painter.end();
       
   219 
       
   220         QVERIFY(!byteArray.contains("<svg width=\""));
       
   221         QVERIFY(!byteArray.contains("viewBox=\""));
       
   222     }
       
   223 
       
   224     { // Setting size only should write size only
       
   225         QSvgGenerator generator;
       
   226         QByteArray byteArray;
       
   227         QBuffer buffer(&byteArray);
       
   228         generator.setOutputDevice(&buffer);
       
   229         generator.setResolution(254);
       
   230         generator.setSize(QSize(100, 100));
       
   231         QPainter painter(&generator);
       
   232         painter.end();
       
   233 
       
   234         QVERIFY(byteArray.contains("<svg width=\"10mm\" height=\"10mm\""));
       
   235         QVERIFY(!byteArray.contains("viewBox=\""));
       
   236     }
       
   237 
       
   238     { // Setting viewBox only should write viewBox only
       
   239         QSvgGenerator generator;
       
   240         QByteArray byteArray;
       
   241         QBuffer buffer(&byteArray);
       
   242         generator.setOutputDevice(&buffer);
       
   243         generator.setViewBox(QRectF(20, 20, 50.666, 50.666));
       
   244         QPainter painter(&generator);
       
   245         painter.end();
       
   246 
       
   247         QVERIFY(!byteArray.contains("<svg width=\""));
       
   248         QVERIFY(byteArray.contains("<svg viewBox=\"20 20 50.666 50.666\""));
       
   249     }
       
   250 
       
   251     { // Setting both properties should result in
       
   252       // both of the attributes written to the SVG
       
   253         QSvgGenerator generator;
       
   254         QByteArray byteArray;
       
   255         QBuffer buffer(&byteArray);
       
   256         generator.setOutputDevice(&buffer);
       
   257         generator.setResolution(254);
       
   258         generator.setSize(QSize(500, 500));
       
   259         generator.setViewBox(QRectF(20.666, 20.666, 50, 50));
       
   260         QPainter painter(&generator);
       
   261         painter.end();
       
   262 
       
   263         QVERIFY(byteArray.contains("<svg width=\"50mm\" height=\"50mm\""));
       
   264         QVERIFY(byteArray.contains("viewBox=\"20.666 20.666 50 50\""));
       
   265     }
       
   266 }
       
   267 
       
   268 void tst_QSvgGenerator::metric()
       
   269 {
       
   270     QSvgGenerator generator;
       
   271     generator.setSize(QSize(100, 100));
       
   272     generator.setResolution(254); // 254 dots per inch == 10 dots per mm
       
   273 
       
   274     QCOMPARE(generator.widthMM(), 10);
       
   275     QCOMPARE(generator.heightMM(), 10);
       
   276 }
       
   277 
       
   278 void tst_QSvgGenerator::radialGradient()
       
   279 {
       
   280     QString fileName = "radial_gradient.svg";
       
   281     QFile::remove(fileName);
       
   282 
       
   283     QSvgGenerator generator;
       
   284     generator.setSize(QSize(200, 100));
       
   285     generator.setFileName(fileName);
       
   286     QCOMPARE(generator.fileName(), fileName);
       
   287 
       
   288     QRadialGradient gradient(QPointF(0.5, 0.5), 0.5, QPointF(0.5, 0.5));
       
   289     gradient.setInterpolationMode(QGradient::ComponentInterpolation);
       
   290     gradient.setColorAt(0, Qt::red);
       
   291     gradient.setColorAt(1, Qt::blue);
       
   292     gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
       
   293 
       
   294     QPainter painter(&generator);
       
   295     painter.fillRect(0, 0, 100, 100, gradient);
       
   296 
       
   297     gradient = QRadialGradient(QPointF(150, 50), 50, QPointF(150, 50));
       
   298     gradient.setInterpolationMode(QGradient::ComponentInterpolation);
       
   299     gradient.setColorAt(0, Qt::red);
       
   300     gradient.setColorAt(1, Qt::blue);
       
   301     painter.fillRect(100, 0, 100, 100, gradient);
       
   302     painter.end();
       
   303 
       
   304     checkFile(fileName);
       
   305 }
       
   306 
       
   307 void tst_QSvgGenerator::fileEncoding()
       
   308 {
       
   309     QTextCodec::setCodecForLocale(QTextCodec::codecForName("ISO-8859-1"));
       
   310 
       
   311     QByteArray byteArray;
       
   312     QBuffer buffer(&byteArray);
       
   313 
       
   314     QSvgGenerator generator;
       
   315     generator.setOutputDevice(&buffer);
       
   316 
       
   317     static const QChar unicode[] = { 'f', 'o', 'o',
       
   318             0x00F8, 'b', 'a', 'r'};
       
   319 
       
   320     int size = sizeof(unicode) / sizeof(QChar);
       
   321     QString unicodeString = QString::fromRawData(unicode, size);
       
   322 
       
   323     QPainter painter(&generator);
       
   324     painter.drawText(100, 100, unicodeString);
       
   325     painter.end();
       
   326 
       
   327     QVERIFY(byteArray.contains(unicodeString.toUtf8()));
       
   328 }
       
   329 
       
   330 void tst_QSvgGenerator::fractionalFontSize()
       
   331 {
       
   332     QByteArray byteArray;
       
   333     QBuffer buffer(&byteArray);
       
   334 
       
   335     QSvgGenerator generator;
       
   336     generator.setResolution(72);
       
   337     generator.setOutputDevice(&buffer);
       
   338 
       
   339     QPainter painter(&generator);
       
   340     QFont fractionalFont = painter.font();
       
   341     fractionalFont.setPointSizeF(7.5);
       
   342     painter.setFont(fractionalFont);
       
   343     painter.drawText(100, 100, "foo");
       
   344     painter.end();
       
   345 
       
   346     QVERIFY(byteArray.contains("7.5"));
       
   347 }
       
   348 
       
   349 void tst_QSvgGenerator::titleAndDescription()
       
   350 {
       
   351     QByteArray byteArray;
       
   352     QBuffer buffer(&byteArray);
       
   353 
       
   354     QSvgGenerator generator;
       
   355     generator.setTitle("foo");
       
   356     QCOMPARE(generator.title(), QString("foo"));
       
   357     generator.setDescription("bar");
       
   358     QCOMPARE(generator.description(), QString("bar"));
       
   359     generator.setOutputDevice(&buffer);
       
   360 
       
   361     QPainter painter(&generator);
       
   362     painter.end();
       
   363 
       
   364     QVERIFY(byteArray.contains("<title>foo</title>"));
       
   365     QVERIFY(byteArray.contains("<desc>bar</desc>"));
       
   366 }
       
   367 
       
   368 static void drawTestGradients(QPainter &painter)
       
   369 {
       
   370     int w = painter.device()->width();
       
   371     int h = painter.device()->height();
       
   372     if (w <= 0 || h <= 0)
       
   373         h = w = 72;
       
   374 
       
   375     QLinearGradient gradient(QPoint(0, 0), QPoint(1, 1));
       
   376     gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
       
   377     gradient.setColorAt(0, QColor(255, 0, 0, 0));
       
   378     gradient.setColorAt(1, QColor(0, 0, 255, 255));
       
   379     painter.fillRect(QRectF(0, 0, w/2, h/2), gradient);
       
   380 
       
   381     gradient.setInterpolationMode(QGradient::ComponentInterpolation);
       
   382     painter.fillRect(QRectF(0, h/2, w/2, h - h/2), gradient);
       
   383 
       
   384     gradient.setInterpolationMode(QGradient::ColorInterpolation);
       
   385     gradient.setColorAt(0, QColor(255, 0, 0, 123));
       
   386     gradient.setColorAt(1, QColor(0, 0, 255, 123));
       
   387     painter.fillRect(QRectF(w/2, 0, w - w/2, h/2), gradient);
       
   388 
       
   389     gradient.setInterpolationMode(QGradient::ComponentInterpolation);
       
   390     painter.fillRect(QRectF(w/2, h/2, w - w/2, h - h/2), gradient);
       
   391 }
       
   392 
       
   393 static qreal sqrImageDiff(const QImage &image1, const QImage &image2)
       
   394 {
       
   395     if (image1.size() != image2.size())
       
   396         return 1e30;
       
   397     quint64 sum = 0;
       
   398     for (int y = 0; y < image1.height(); ++y) {
       
   399         const quint8 *line1 = reinterpret_cast<const quint8 *>(image1.scanLine(y));
       
   400         const quint8 *line2 = reinterpret_cast<const quint8 *>(image2.scanLine(y));
       
   401         for (int x = 0; x < image1.width() * 4; ++x)
       
   402             sum += quint64((int(line1[x]) - int(line2[x])) * (int(line1[x]) - int(line2[x])));
       
   403     }
       
   404     return qreal(sum) / qreal(image1.width() * image1.height());
       
   405 }
       
   406 
       
   407 void tst_QSvgGenerator::gradientInterpolation()
       
   408 {
       
   409     QByteArray byteArray;
       
   410     QPainter painter;
       
   411     QImage image(576, 576, QImage::Format_ARGB32_Premultiplied);
       
   412     QImage refImage(576, 576, QImage::Format_ARGB32_Premultiplied);
       
   413     image.fill(0x80208050);
       
   414     refImage.fill(0x80208050);
       
   415 
       
   416     {
       
   417         QSvgGenerator generator;
       
   418         QBuffer buffer(&byteArray);
       
   419         generator.setOutputDevice(&buffer);
       
   420 
       
   421         QVERIFY(painter.begin(&generator));
       
   422         drawTestGradients(painter);
       
   423         painter.end();
       
   424     }
       
   425 
       
   426     {
       
   427         QVERIFY(painter.begin(&image));
       
   428         QSvgRenderer renderer(byteArray);
       
   429         renderer.render(&painter, image.rect());
       
   430         painter.end();
       
   431     }
       
   432 
       
   433     {
       
   434         QVERIFY(painter.begin(&refImage));
       
   435         drawTestGradients(painter);
       
   436         painter.end();
       
   437     }
       
   438 
       
   439     QVERIFY(sqrImageDiff(image, refImage) < 2); // pixel error < 1.41 (L2-norm)
       
   440 }
       
   441 
       
   442 QTEST_MAIN(tst_QSvgGenerator)
       
   443 #include "tst_qsvggenerator.moc"