diff options
-rw-r--r-- | .qmake.conf | 2 | ||||
-rw-r--r-- | LGPL_EXCEPTION.txt | 22 | ||||
-rw-r--r-- | examples/svg/network/bearercloud/bearercloud.cpp | 2 | ||||
-rw-r--r-- | examples/svg/network/bearercloud/cloud.cpp | 2 | ||||
-rw-r--r-- | examples/svg/network/bearercloud/cloud.h | 2 | ||||
-rw-r--r-- | src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp | 95 | ||||
-rw-r--r-- | src/plugins/imageformats/svg/qsvgiohandler.cpp | 7 | ||||
-rw-r--r-- | src/svg/qsvggenerator.cpp | 2 | ||||
-rw-r--r-- | src/svg/qsvggraphics_p.h | 7 | ||||
-rw-r--r-- | src/svg/qsvghandler.cpp | 86 | ||||
-rw-r--r-- | src/svg/qsvghandler_p.h | 1 | ||||
-rw-r--r-- | tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp | 45 |
12 files changed, 188 insertions, 85 deletions
diff --git a/.qmake.conf b/.qmake.conf index b952473..bc074d5 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -3,4 +3,4 @@ load(qt_build_config) CONFIG += warning_clean DEFINES += QT_NO_FOREACH -MODULE_VERSION = 5.11.3 +MODULE_VERSION = 5.12.0 diff --git a/LGPL_EXCEPTION.txt b/LGPL_EXCEPTION.txt deleted file mode 100644 index 5cdacb9..0000000 --- a/LGPL_EXCEPTION.txt +++ /dev/null @@ -1,22 +0,0 @@ -The Qt Company Qt LGPL Exception version 1.1 - -As an additional permission to the GNU Lesser General Public License version -2.1, the object code form of a "work that uses the Library" may incorporate -material from a header file that is part of the Library. You may distribute -such object code under terms of your choice, provided that: - (i) the header files of the Library have not been modified; and - (ii) the incorporated material is limited to numerical parameters, data - structure layouts, accessors, macros, inline functions and - templates; and - (iii) you comply with the terms of Section 6 of the GNU Lesser General - Public License version 2.1. - -Moreover, you may apply this exception to a modified version of the Library, -provided that such modification does not involve copying material from the -Library into the modified Library's header files unless such material is -limited to (i) numerical parameters; (ii) data structure layouts; -(iii) accessors; and (iv) small macros, templates and inline functions of -five lines or less in length. - -Furthermore, you are not required to apply this additional permission to a -modified version of the Library. diff --git a/examples/svg/network/bearercloud/bearercloud.cpp b/examples/svg/network/bearercloud/bearercloud.cpp index 610764a..0f08aec 100644 --- a/examples/svg/network/bearercloud/bearercloud.cpp +++ b/examples/svg/network/bearercloud/bearercloud.cpp @@ -131,7 +131,7 @@ void BearerCloud::timerEvent(QTimerEvent *) bool cloudsMoved = false; for (Cloud *cloud : clouds) - cloudsMoved |= cloud->advance(); + cloudsMoved |= cloud->advanceAnimation(); if (!cloudsMoved) { killTimer(timerId); diff --git a/examples/svg/network/bearercloud/cloud.cpp b/examples/svg/network/bearercloud/cloud.cpp index 43f6379..4e0313a 100644 --- a/examples/svg/network/bearercloud/cloud.cpp +++ b/examples/svg/network/bearercloud/cloud.cpp @@ -170,7 +170,7 @@ void Cloud::calculateForces() newPos.setY(qMin(qMax(newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10)); } -bool Cloud::advance() +bool Cloud::advanceAnimation() { static const qreal scaleDelta = 0.01; diff --git a/examples/svg/network/bearercloud/cloud.h b/examples/svg/network/bearercloud/cloud.h index 2a728d1..a91b994 100644 --- a/examples/svg/network/bearercloud/cloud.h +++ b/examples/svg/network/bearercloud/cloud.h @@ -76,7 +76,7 @@ public: void calculateForces(); - bool advance(); + bool advanceAnimation(); QRectF boundingRect() const override; void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override; diff --git a/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp b/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp index 0c54e0e..e23dd9a 100644 --- a/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp +++ b/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp @@ -74,7 +74,8 @@ public: void stepSerialNum() { serialNum = lastSerialNum.fetchAndAddRelaxed(1); } - void loadDataForModeAndState(QSvgRenderer *renderer, QIcon::Mode mode, QIcon::State state); + bool tryLoad(QSvgRenderer *renderer, QIcon::Mode mode, QIcon::State state); + QIcon::Mode loadDataForModeAndState(QSvgRenderer *renderer, QIcon::Mode mode, QIcon::State state); QHash<int, QString> svgFiles; QHash<int, QByteArray> *svgBuffers; @@ -121,31 +122,73 @@ QSize QSvgIconEngine::actualSize(const QSize &size, QIcon::Mode mode, return pm.size(); } -void QSvgIconEnginePrivate::loadDataForModeAndState(QSvgRenderer *renderer, QIcon::Mode mode, QIcon::State state) +static QByteArray maybeUncompress(const QByteArray &ba) { - QByteArray buf; - const QIcon::State oppositeState = state == QIcon::Off ? QIcon::On : QIcon::Off; - if (svgBuffers) { - buf = svgBuffers->value(hashKey(mode, state)); - if (buf.isEmpty()) - buf = svgBuffers->value(hashKey(QIcon::Normal, state)); - if (buf.isEmpty()) - buf = svgBuffers->value(hashKey(QIcon::Normal, oppositeState)); - } - if (!buf.isEmpty()) { #ifndef QT_NO_COMPRESS - buf = qUncompress(buf); + return qUncompress(ba); +#else + return ba; #endif - renderer->load(buf); +} + +bool QSvgIconEnginePrivate::tryLoad(QSvgRenderer *renderer, QIcon::Mode mode, QIcon::State state) +{ + if (svgBuffers) { + QByteArray buf = svgBuffers->value(hashKey(mode, state)); + if (!buf.isEmpty()) { + buf = maybeUncompress(buf); + renderer->load(buf); + return true; + } + } + QString svgFile = svgFiles.value(hashKey(mode, state)); + if (!svgFile.isEmpty()) { + renderer->load(svgFile); + return true; + } + return false; +} + +QIcon::Mode QSvgIconEnginePrivate::loadDataForModeAndState(QSvgRenderer *renderer, QIcon::Mode mode, QIcon::State state) +{ + if (tryLoad(renderer, mode, state)) + return mode; + + const QIcon::State oppositeState = (state == QIcon::On) ? QIcon::Off : QIcon::On; + if (mode == QIcon::Disabled || mode == QIcon::Selected) { + const QIcon::Mode oppositeMode = (mode == QIcon::Disabled) ? QIcon::Selected : QIcon::Disabled; + if (tryLoad(renderer, QIcon::Normal, state)) + return QIcon::Normal; + if (tryLoad(renderer, QIcon::Active, state)) + return QIcon::Active; + if (tryLoad(renderer, mode, oppositeState)) + return mode; + if (tryLoad(renderer, QIcon::Normal, oppositeState)) + return QIcon::Normal; + if (tryLoad(renderer, QIcon::Active, oppositeState)) + return QIcon::Active; + if (tryLoad(renderer, oppositeMode, state)) + return oppositeMode; + if (tryLoad(renderer, oppositeMode, oppositeState)) + return oppositeMode; } else { - QString svgFile = svgFiles.value(hashKey(mode, state)); - if (svgFile.isEmpty()) - svgFile = svgFiles.value(hashKey(QIcon::Normal, state)); - if (svgFile.isEmpty()) - svgFile = svgFiles.value(hashKey(QIcon::Normal, oppositeState)); - if (!svgFile.isEmpty()) - renderer->load(svgFile); + const QIcon::Mode oppositeMode = (mode == QIcon::Normal) ? QIcon::Active : QIcon::Normal; + if (tryLoad(renderer, oppositeMode, state)) + return oppositeMode; + if (tryLoad(renderer, mode, oppositeState)) + return mode; + if (tryLoad(renderer, oppositeMode, oppositeState)) + return oppositeMode; + if (tryLoad(renderer, QIcon::Disabled, state)) + return QIcon::Disabled; + if (tryLoad(renderer, QIcon::Selected, state)) + return QIcon::Selected; + if (tryLoad(renderer, QIcon::Disabled, oppositeState)) + return QIcon::Disabled; + if (tryLoad(renderer, QIcon::Selected, oppositeState)) + return QIcon::Selected; } + return QIcon::Normal; } QPixmap QSvgIconEngine::pixmap(const QSize &size, QIcon::Mode mode, @@ -164,7 +207,7 @@ QPixmap QSvgIconEngine::pixmap(const QSize &size, QIcon::Mode mode, } QSvgRenderer renderer; - d->loadDataForModeAndState(&renderer, mode, state); + const QIcon::Mode loadmode = d->loadDataForModeAndState(&renderer, mode, state); if (!renderer.isValid()) return pm; @@ -182,9 +225,11 @@ QPixmap QSvgIconEngine::pixmap(const QSize &size, QIcon::Mode mode, p.end(); pm = QPixmap::fromImage(img); if (qobject_cast<QGuiApplication *>(QCoreApplication::instance())) { - const QPixmap generated = QGuiApplicationPrivate::instance()->applyQIconStyleHelper(mode, pm); - if (!generated.isNull()) - pm = generated; + if (loadmode != mode && mode != QIcon::Normal) { + const QPixmap generated = QGuiApplicationPrivate::instance()->applyQIconStyleHelper(mode, pm); + if (!generated.isNull()) + pm = generated; + } } if (!pm.isNull()) diff --git a/src/plugins/imageformats/svg/qsvgiohandler.cpp b/src/plugins/imageformats/svg/qsvgiohandler.cpp index 457c79e..a999d47 100644 --- a/src/plugins/imageformats/svg/qsvgiohandler.cpp +++ b/src/plugins/imageformats/svg/qsvgiohandler.cpp @@ -176,8 +176,13 @@ bool QSvgIOHandler::read(QImage *image) t.translate(tr1.x(), tr1.y()); bounds = t.mapRect(bounds); } - if (image->size() != finalSize || !image->reinterpretAsFormat(QImage::Format_ARGB32_Premultiplied)) + if (image->size() != finalSize || !image->reinterpretAsFormat(QImage::Format_ARGB32_Premultiplied)) { *image = QImage(finalSize, QImage::Format_ARGB32_Premultiplied); + if (!finalSize.isEmpty() && image->isNull()) { + qWarning("QSvgIOHandler: QImage allocation failed (size %i x %i)", finalSize.width(), finalSize.height()); + return false; + } + } if (!finalSize.isEmpty()) { image->fill(d->backColor.rgba()); QPainter p(image); diff --git a/src/svg/qsvggenerator.cpp b/src/svg/qsvggenerator.cpp index 424cc76..07f8d74 100644 --- a/src/svg/qsvggenerator.cpp +++ b/src/svg/qsvggenerator.cpp @@ -334,7 +334,7 @@ public: void saveGradientUnits(QTextStream &str, const QGradient *gradient) { str << QLatin1String("gradientUnits=\""); - if (gradient && gradient->coordinateMode() == QGradient::ObjectBoundingMode) + if (gradient && (gradient->coordinateMode() == QGradient::ObjectBoundingMode || gradient->coordinateMode() == QGradient::ObjectMode)) str << QLatin1String("objectBoundingBox"); else str << QLatin1String("userSpaceOnUse"); diff --git a/src/svg/qsvggraphics_p.h b/src/svg/qsvggraphics_p.h index 33b5154..6e5b9d6 100644 --- a/src/svg/qsvggraphics_p.h +++ b/src/svg/qsvggraphics_p.h @@ -237,13 +237,20 @@ class QSvgUse : public QSvgNode { public: QSvgUse(const QPointF &start, QSvgNode *parent, QSvgNode *link); + QSvgUse(const QPointF &start, QSvgNode *parent, const QString &linkId) + : QSvgUse(start, parent, nullptr) + { m_linkId = linkId; } void draw(QPainter *p, QSvgExtraStates &states) override; Type type() const override; QRectF bounds(QPainter *p, QSvgExtraStates &states) const override; + bool isResolved() const { return m_link != nullptr; } + QString linkId() const { return m_linkId; } + void setLink(QSvgNode *link) { m_link = link; } private: QSvgNode *m_link; QPointF m_start; + QString m_linkId; }; class QSvgVideo : public QSvgNode diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index fe07d0e..5242ffe 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -59,6 +59,7 @@ #include "qdebug.h" #include "qmath.h" #include "qnumeric.h" +#include <qregularexpression.h> #include "qvarlengtharray.h" #include "private/qmath_p.h" @@ -2865,7 +2866,7 @@ static void parseBaseGradient(QSvgNode *node, } if (units.isEmpty() || units == QLatin1String("objectBoundingBox")) { - grad->setCoordinateMode(QGradient::ObjectBoundingMode); + grad->setCoordinateMode(QGradient::ObjectMode); } } @@ -3358,29 +3359,30 @@ static QSvgNode *createUseNode(QSvgNode *parent, } if (group) { + QPointF pt; + if (!xStr.isNull() || !yStr.isNull()) { + QSvgHandler::LengthType type; + qreal nx = parseLength(xStr, type, handler); + nx = convertToPixels(nx, true, type); + + qreal ny = parseLength(yStr, type, handler); + ny = convertToPixels(ny, true, type); + pt = QPointF(nx, ny); + } + QSvgNode *link = group->scopeNode(linkId); if (link) { if (parent->isDescendantOf(link)) qCWarning(lcSvgHandler, "link #%s is recursive!", qPrintable(linkId)); - QPointF pt; - if (!xStr.isNull() || !yStr.isNull()) { - QSvgHandler::LengthType type; - qreal nx = parseLength(xStr, type, handler); - nx = convertToPixels(nx, true, type); - - qreal ny = parseLength(yStr, type, handler); - ny = convertToPixels(ny, true, type); - pt = QPointF(nx, ny); - } - //delay link resolving till the first draw call on - //use nodes, link 2might have not been created yet - QSvgUse *node = new QSvgUse(pt, parent, link); - return node; + return new QSvgUse(pt, parent, link); } + + //delay link resolving, link might have not been created yet + return new QSvgUse(pt, parent, linkId); } - qCWarning(lcSvgHandler, "link %s hasn't been detected!", qPrintable(linkId)); + qCWarning(lcSvgHandler, "<use> element %s in wrong context!", qPrintable(linkId)); return 0; } @@ -3646,6 +3648,7 @@ void QSvgHandler::parse() } } resolveGradients(m_doc); + resolveNodes(); } bool QSvgHandler::startElement(const QString &localName, @@ -3750,6 +3753,9 @@ bool QSvgHandler::startElement(const QString &localName, static_cast<QSvgText *>(node)->setWhitespaceMode(m_whitespaceMode.top()); } else if (node->type() == QSvgNode::TSPAN) { static_cast<QSvgTspan *>(node)->setWhitespaceMode(m_whitespaceMode.top()); + } else if (node->type() == QSvgNode::USE) { + if (!static_cast<QSvgUse *>(node)->isResolved()) + m_resolveNodes.append(node); } } } @@ -3852,6 +3858,33 @@ void QSvgHandler::resolveGradients(QSvgNode *node) } } +void QSvgHandler::resolveNodes() +{ + for (QSvgNode *node : qAsConst(m_resolveNodes)) { + if (!node || !node->parent() || node->type() != QSvgNode::USE) + continue; + QSvgUse *useNode = static_cast<QSvgUse *>(node); + if (useNode->isResolved()) + continue; + QSvgNode::Type t = useNode->parent()->type(); + if (!(t == QSvgNode::DOC || t == QSvgNode::DEFS || t == QSvgNode::G || t == QSvgNode::SWITCH)) + continue; + + QSvgStructureNode *group = static_cast<QSvgStructureNode *>(useNode->parent()); + QSvgNode *link = group->scopeNode(useNode->linkId()); + if (!link) { + qCWarning(lcSvgHandler, "link #%s is undefined!", qPrintable(useNode->linkId())); + continue; + } + + if (useNode->parent()->isDescendantOf(link)) + qCWarning(lcSvgHandler, "link #%s is recursive!", qPrintable(useNode->linkId())); + + useNode->setLink(link); + } + m_resolveNodes.clear(); +} + bool QSvgHandler::characters(const QStringRef &str) { #ifndef QT_NO_CSSPARSER @@ -3948,24 +3981,23 @@ bool QSvgHandler::processingInstruction(const QString &target, const QString &da Q_UNUSED(data) #else if (target == QLatin1String("xml-stylesheet")) { - QRegExp rx(QLatin1String("type=\\\"(.+)\\\"")); - rx.setMinimal(true); + QRegularExpression rx(QLatin1String("type=\\\"(.+)\\\""), + QRegularExpression::InvertedGreedinessOption); + QRegularExpressionMatchIterator iter = rx.globalMatch(data); bool isCss = false; - int pos = 0; - while ((pos = rx.indexIn(data, pos)) != -1) { - QString type = rx.cap(1); + while (iter.hasNext()) { + QRegularExpressionMatch match = iter.next(); + QString type = match.captured(1); if (type.toLower() == QLatin1String("text/css")) { isCss = true; } - pos += rx.matchedLength(); } if (isCss) { - QRegExp rx(QLatin1String("href=\\\"(.+)\\\"")); - rx.setMinimal(true); - pos = 0; - pos = rx.indexIn(data, pos); - QString addr = rx.cap(1); + QRegularExpression rx(QLatin1String("href=\\\"(.+)\\\""), + QRegularExpression::InvertedGreedinessOption); + QRegularExpressionMatch match = rx.match(data); + QString addr = match.captured(1); QFileInfo fi(addr); //qDebug()<<"External CSS file "<<fi.absoluteFilePath()<<fi.exists(); if (fi.exists()) { diff --git a/src/svg/qsvghandler_p.h b/src/svg/qsvghandler_p.h index 2c06cb4..5c13003 100644 --- a/src/svg/qsvghandler_p.h +++ b/src/svg/qsvghandler_p.h @@ -178,6 +178,7 @@ private: #endif void parse(); void resolveGradients(QSvgNode *node); + void resolveNodes(); QPen m_defaultPen; /** diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp index a8fc9de..5e13bee 100644 --- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp @@ -1261,32 +1261,36 @@ void tst_QSvgRenderer::testStopOffsetOpacity() void tst_QSvgRenderer::testUseElement() { static const char *svgs[] = { - //Use referring to non group node (1) + // 0 - Use referring to non group node (1) "<svg viewBox = \"0 0 200 200\">" " <polygon points=\"20,20 50,120 100,10 40,80 50,80\"/>" " <polygon points=\"20,80 50,180 100,70 40,140 50,140\" fill= \"red\" stroke = \"blue\" fill-opacity = \"0.7\" fill-rule = \"evenodd\" stroke-width = \"3\"/>" "</svg>", + // 1 "<svg viewBox = \"0 0 200 200\">" " <polygon id = \"usedPolyline\" points=\"20,20 50,120 100,10 40,80 50,80\"/>" " <use y = \"60\" xlink:href = \"#usedPolyline\" fill= \"red\" stroke = \"blue\" fill-opacity = \"0.7\" fill-rule = \"evenodd\" stroke-width = \"3\"/>" "</svg>", + // 2 "<svg viewBox = \"0 0 200 200\">" " <polygon id = \"usedPolyline\" points=\"20,20 50,120 100,10 40,80 50,80\"/>" " <g fill = \" red\" fill-opacity =\"0.2\">" "<use y = \"60\" xlink:href = \"#usedPolyline\" stroke = \"blue\" fill-opacity = \"0.7\" fill-rule = \"evenodd\" stroke-width = \"3\"/>" "</g>" "</svg>", + // 3 "<svg viewBox = \"0 0 200 200\">" " <polygon id = \"usedPolyline\" points=\"20,20 50,120 100,10 40,80 50,80\"/>" " <g stroke-width = \"3\" stroke = \"yellow\">" " <use y = \"60\" xlink:href = \"#usedPolyline\" fill = \" red\" stroke = \"blue\" fill-opacity = \"0.7\" fill-rule = \"evenodd\"/>" " </g>" "</svg>", - //Use referring to non group node (2) + // 4 - Use referring to non group node (2) "<svg viewBox = \"0 0 200 200\">" " <polygon points=\"20,20 50,120 100,10 40,80 50,80\" fill = \"green\" fill-rule = \"nonzero\" stroke = \"purple\" stroke-width = \"4\" stroke-dasharray = \"1,1,3,1\" stroke-offset = \"3\" stroke-miterlimit = \"6\" stroke-linecap = \"butt\" stroke-linejoin = \"round\"/>" " <polygon points=\"20,80 50,180 100,70 40,140 50,140\" fill= \"red\" stroke = \"blue\" fill-opacity = \"0.7\" fill-rule = \"evenodd\" stroke-width = \"3\" stroke-dasharray = \"1,1,1,1\" stroke-offset = \"5\" stroke-miterlimit = \"3\" stroke-linecap = \"butt\" stroke-linejoin = \"square\"/>" "</svg>", + // 5 "<svg viewBox = \"0 0 200 200\">" " <g fill = \"green\" fill-rule = \"nonzero\" stroke = \"purple\" stroke-width = \"4\" stroke-dasharray = \"1,1,3,1\" stroke-offset = \"3\" stroke-miterlimit = \"6\" stroke-linecap = \"butt\" stroke-linejoin = \"round\">" " <polygon id = \"usedPolyline\" points=\"20,20 50,120 100,10 40,80 50,80\" />" @@ -1295,6 +1299,7 @@ void tst_QSvgRenderer::testUseElement() " <use y = \"60\" xlink:href = \"#usedPolyline\" fill-opacity = \"0.7\" fill= \"red\" stroke = \"blue\" fill-rule = \"evenodd\"/>" " </g>" "</svg>", + // 6 "<svg viewBox = \"0 0 200 200\">" " <g fill = \"green\" fill-rule = \"nonzero\" stroke = \"purple\" stroke-width = \"4\" stroke-dasharray = \"1,1,3,1\" stroke-offset = \"3\" stroke-miterlimit = \"6\" stroke-linecap = \"butt\" stroke-linejoin = \"round\">" " <polygon id = \"usedPolyline\" points=\"20,20 50,120 100,10 40,80 50,80\" />" @@ -1303,7 +1308,7 @@ void tst_QSvgRenderer::testUseElement() " <use y = \"60\" xlink:href = \"#usedPolyline\" fill= \"red\" stroke = \"blue\" fill-opacity = \"0.7\" fill-rule = \"evenodd\" />" " </g>" "</svg>", - //Use referring to group node + // 7 - Use referring to group node "<svg viewBox = \"0 0 200 200\">" " <g>" " <circle cx=\"0\" cy=\"0\" r=\"100\" fill = \"red\" fill-opacity = \"0.6\"/>" @@ -1311,6 +1316,7 @@ void tst_QSvgRenderer::testUseElement() " <circle fill=\"#a6ce39\" cx=\"0\" cy=\"0\" r=\"33\" fill-opacity = \"0.5\"/>" " </g>" "</svg>", + // 8 "<svg viewBox = \"0 0 200 200\">" " <defs>" " <g id=\"usedG\">" @@ -1321,6 +1327,7 @@ void tst_QSvgRenderer::testUseElement() " </defs>" " <use xlink:href =\"#usedG\" fill = \"red\" fill-opacity =\"0.5\"/>" "</svg>", + // 9 "<svg viewBox = \"0 0 200 200\">" " <defs>" " <g fill = \"blue\" fill-opacity = \"0.3\">" @@ -1335,16 +1342,40 @@ void tst_QSvgRenderer::testUseElement() " <use xlink:href =\"#usedG\" />" " </g>" "</svg>", - // Self referral, should be ignored + // 10 - Self referral, should be ignored "<svg><g id=\"0\"><use xlink:href=\"#0\" /></g></svg>", + // 11 "<svg width=\"200\" height=\"200\">" " <rect width=\"100\" height=\"50\"/>" "</svg>", + // 12 "<svg width=\"200\" height=\"200\">" " <g id=\"0\"><use xlink:href=\"#0\" /><rect width=\"100\" height=\"50\"/></g>" "</svg>", + // 13 "<svg width=\"200\" height=\"200\">" " <g id=\"0\"><g><use xlink:href=\"#0\" /><rect width=\"100\" height=\"50\"/></g></g>" + "</svg>", + // 14 (undefined) + "<svg width=\"200\" height=\"200\">" + " <rect width=\"100\" height=\"50\"/>" + " <use x=\"100\" y=\"100\" opacity=\"0.5\" xlink:href=\"#nosuch\" />" + "</svg>", + // 15 - Forward references + "<svg viewBox = \"0 0 200 200\">" + " <use y = \"60\" xlink:href = \"#usedPolyline\" fill= \"red\" stroke = \"blue\" fill-opacity = \"0.7\" fill-rule = \"evenodd\" stroke-width = \"3\"/>" + " <polygon id = \"usedPolyline\" points=\"20,20 50,120 100,10 40,80 50,80\"/>" + "</svg>", + // 16 + "<svg viewBox = \"0 0 200 200\">" + " <use xlink:href =\"#usedG\" fill = \"red\" fill-opacity =\"0.5\"/>" + " <defs>" + " <g id=\"usedG\">" + " <circle cx=\"0\" cy=\"0\" r=\"100\" fill-opacity = \"0.6\"/>" + " <rect x = \"10\" y = \"10\" width = \"30\" height = \"30\"/>" + " <circle fill=\"#a6ce39\" cx=\"0\" cy=\"0\" r=\"33\" />" + " </g>" + " </defs>" "</svg>" }; @@ -1373,8 +1404,12 @@ void tst_QSvgRenderer::testUseElement() } } else if (i > 7 && i < 10) { QCOMPARE(images[8], images[i]); - } else if (i > 11) { + } else if (i > 11 && i < 15) { QCOMPARE(images[11], images[i]); + } else if (i == 15) { + QCOMPARE(images[0], images[i]); + } else if (i == 16) { + QCOMPARE(images[8], images[i]); } } } |