diff options
Diffstat (limited to 'src/svg')
-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 |
4 files changed, 68 insertions, 28 deletions
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; /** |