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 /src | |
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 'src')
-rw-r--r-- | src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp | 2 | ||||
-rw-r--r-- | src/svg/qsvggenerator.cpp | 54 | ||||
-rw-r--r-- | src/svg/qsvggraphics.cpp | 33 | ||||
-rw-r--r-- | src/svg/qsvggraphics_p.h | 5 | ||||
-rw-r--r-- | src/svg/qsvghandler.cpp | 57 | ||||
-rw-r--r-- | src/svg/qsvgstyle.cpp | 11 | ||||
-rw-r--r-- | src/svg/qsvgstyle_p.h | 1 | ||||
-rw-r--r-- | src/svg/qsvgtinydocument.cpp | 50 | ||||
-rw-r--r-- | src/svg/qsvgtinydocument_p.h | 5 |
9 files changed, 144 insertions, 74 deletions
diff --git a/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp b/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp index e23dd9a..09064e3 100644 --- a/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp +++ b/src/plugins/iconengines/svgiconengine/qsvgiconengine.cpp @@ -197,7 +197,7 @@ QPixmap QSvgIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QPixmap pm; QString pmckey(d->pmcKey(size, mode, state)); - if (QPixmapCache::find(pmckey, pm)) + if (QPixmapCache::find(pmckey, &pm)) return pm; if (d->addedPixmaps) { diff --git a/src/svg/qsvggenerator.cpp b/src/svg/qsvggenerator.cpp index 07f8d74..360b02b 100644 --- a/src/svg/qsvggenerator.cpp +++ b/src/svg/qsvggenerator.cpp @@ -227,10 +227,10 @@ public: QString rct(QStringLiteral("<rect x=\"%1\" y=\"%2\" width=\"%3\" height=\"%4\" />")); QTextStream str(&d_func()->defs, QIODevice::Append); str << "<mask id=\"" << maskId << "\" x=\"0\" y=\"0\" width=\"8\" height=\"8\" " - << "stroke=\"none\" fill=\"#ffffff\" patternUnits=\"userSpaceOnUse\" >" << endl; + << "stroke=\"none\" fill=\"#ffffff\" patternUnits=\"userSpaceOnUse\" >" << Qt::endl; for (QRect r : reg) - str << rct.arg(r.x()).arg(r.y()).arg(r.width()).arg(r.height()) << endl; - str << QStringLiteral("</mask>") << endl << endl; + str << rct.arg(r.x()).arg(r.y()).arg(r.width()).arg(r.height()) << Qt::endl; + str << QStringLiteral("</mask>") << Qt::endl << Qt::endl; d_func()->savedPatternMasks.append(maskId); } return maskId; @@ -243,9 +243,9 @@ public: QString maskId = savePatternMask(brush.style()); QString geo(QStringLiteral("x=\"0\" y=\"0\" width=\"8\" height=\"8\"")); QTextStream str(&d_func()->defs, QIODevice::Append); - str << QString(QStringLiteral("<pattern id=\"%1\" %2 patternUnits=\"userSpaceOnUse\" >")).arg(patternId, geo) << endl; - str << QString(QStringLiteral("<rect %1 stroke=\"none\" fill=\"%2\" mask=\"url(#%3);\" />")).arg(geo, color, maskId) << endl; - str << QStringLiteral("</pattern>") << endl << endl; + str << QString(QStringLiteral("<pattern id=\"%1\" %2 patternUnits=\"userSpaceOnUse\" >")).arg(patternId, geo) << Qt::endl; + str << QString(QStringLiteral("<rect %1 stroke=\"none\" fill=\"%2\" mask=\"url(#%3);\" />")).arg(geo, color, maskId) << Qt::endl; + str << QStringLiteral("</pattern>") << Qt::endl << Qt::endl; d_func()->savedPatternBrushes.append(patternId); } return patternId; @@ -266,7 +266,7 @@ public: str << QLatin1String("id=\"") << d_func()->generateGradientName() << QLatin1String("\">\n"); saveGradientStops(str, g); - str << QLatin1String("</linearGradient>") <<endl; + str << QLatin1String("</linearGradient>") <<Qt::endl; } void saveRadialGradientBrush(const QGradient *g) { @@ -283,7 +283,7 @@ public: } str << QLatin1String("id=\"") <<d_func()->generateGradientName()<< QLatin1String("\">\n"); saveGradientStops(str, g); - str << QLatin1String("</radialGradient>") << endl; + str << QLatin1String("</radialGradient>") << Qt::endl; } void saveConicalGradientBrush(const QGradient *) { @@ -544,7 +544,7 @@ public: "font-size=\"" << d->attributes.font_size << "\" " "font-weight=\"" << d->attributes.font_weight << "\" " "font-style=\"" << d->attributes.font_style << "\" " - << endl; + << Qt::endl; } }; @@ -892,29 +892,29 @@ bool QSvgPaintEngine::begin(QPaintDevice *) d->stream = new QTextStream(&d->header); // stream out the header... - *d->stream << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" << endl << "<svg"; + *d->stream << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" << Qt::endl << "<svg"; if (d->size.isValid()) { qreal wmm = d->size.width() * 25.4 / d->resolution; qreal hmm = d->size.height() * 25.4 / d->resolution; - *d->stream << " width=\"" << wmm << "mm\" height=\"" << hmm << "mm\"" << endl; + *d->stream << " width=\"" << wmm << "mm\" height=\"" << hmm << "mm\"" << Qt::endl; } if (d->viewBox.isValid()) { *d->stream << " viewBox=\"" << d->viewBox.left() << ' ' << d->viewBox.top(); - *d->stream << ' ' << d->viewBox.width() << ' ' << d->viewBox.height() << '\"' << endl; + *d->stream << ' ' << d->viewBox.width() << ' ' << d->viewBox.height() << '\"' << Qt::endl; } *d->stream << " xmlns=\"http://www.w3.org/2000/svg\"" " xmlns:xlink=\"http://www.w3.org/1999/xlink\" " - " version=\"1.2\" baseProfile=\"tiny\">" << endl; + " version=\"1.2\" baseProfile=\"tiny\">" << Qt::endl; if (!d->attributes.document_title.isEmpty()) { - *d->stream << "<title>" << d->attributes.document_title << "</title>" << endl; + *d->stream << "<title>" << d->attributes.document_title << "</title>" << Qt::endl; } if (!d->attributes.document_description.isEmpty()) { - *d->stream << "<desc>" << d->attributes.document_description << "</desc>" << endl; + *d->stream << "<desc>" << d->attributes.document_description << "</desc>" << Qt::endl; } d->stream->setString(&d->defs); @@ -924,7 +924,7 @@ bool QSvgPaintEngine::begin(QPaintDevice *) // Start the initial graphics state... *d->stream << "<g "; generateQtDefaults(); - *d->stream << endl; + *d->stream << Qt::endl; return true; } @@ -945,10 +945,10 @@ bool QSvgPaintEngine::end() *d->stream << d->defs; *d->stream << d->body; if (d->afterFirstUpdate) - *d->stream << "</g>" << endl; // close the updateState + *d->stream << "</g>" << Qt::endl; // close the updateState - *d->stream << "</g>" << endl // close the Qt defaults - << "</svg>" << endl; + *d->stream << "</g>" << Qt::endl // close the Qt defaults + << "</svg>" << Qt::endl; delete d->stream; @@ -1009,13 +1009,13 @@ void QSvgPaintEngine::updateState(const QPaintEngineState &state) } if (flags & QPaintEngine::DirtyTransform) { - d->matrix = state.matrix(); + d->matrix = state.transform().toAffine(); *d->stream << "transform=\"matrix(" << d->matrix.m11() << ',' << d->matrix.m12() << ',' << d->matrix.m21() << ',' << d->matrix.m22() << ',' << d->matrix.dx() << ',' << d->matrix.dy() << ")\"" - << endl; + << Qt::endl; } if (flags & QPaintEngine::DirtyFont) { @@ -1027,7 +1027,7 @@ void QSvgPaintEngine::updateState(const QPaintEngineState &state) stream() << "opacity=\""<<state.opacity()<<"\" "; } - *d->stream << '>' << endl; + *d->stream << '>' << Qt::endl; d->afterFirstUpdate = true; } @@ -1046,7 +1046,7 @@ void QSvgPaintEngine::drawEllipse(const QRectF &r) *d->stream << "\" r=\"" << r.width() / qreal(2.0); else *d->stream << "\" rx=\"" << r.width() / qreal(2.0) << "\" ry=\"" << r.height() / qreal(2.0); - *d->stream << "\"/>" << endl; + *d->stream << "\"/>" << Qt::endl; } void QSvgPaintEngine::drawPath(const QPainterPath &p) @@ -1090,7 +1090,7 @@ void QSvgPaintEngine::drawPath(const QPainterPath &p) } } - *d->stream << "\"/>" << endl; + *d->stream << "\"/>" << Qt::endl; } void QSvgPaintEngine::drawPolygon(const QPointF *points, int pointCount, @@ -1112,7 +1112,7 @@ void QSvgPaintEngine::drawPolygon(const QPointF *points, int pointCount, const QPointF &pt = points[i]; stream() << pt.x() << ',' << pt.y() << ' '; } - stream() << "\" />" <<endl; + stream() << "\" />" <<Qt::endl; } else { path.closeSubpath(); drawPath(path); @@ -1130,7 +1130,7 @@ void QSvgPaintEngine::drawRects(const QRectF *rects, int rectCount) *d->stream << " vector-effect=\"non-scaling-stroke\""; *d->stream << " x=\"" << rect.x() << "\" y=\"" << rect.y() << "\" width=\"" << rect.width() << "\" height=\"" << rect.height() - << "\"/>" << endl; + << "\"/>" << Qt::endl; } } @@ -1155,7 +1155,7 @@ void QSvgPaintEngine::drawTextItem(const QPointF &pt, const QTextItem &textItem) *d->stream << " >" << s.toHtmlEscaped() << "</text>" - << endl; + << Qt::endl; } QT_END_NAMESPACE diff --git a/src/svg/qsvggraphics.cpp b/src/svg/qsvggraphics.cpp index 5b273af..bcd2452 100644 --- a/src/svg/qsvggraphics.cpp +++ b/src/svg/qsvggraphics.cpp @@ -41,11 +41,12 @@ #include "qsvgfont_p.h" -#include "qpainter.h" -#include "qtextdocument.h" -#include "qabstracttextdocumentlayout.h" -#include "qtextcursor.h" -#include "qdebug.h" +#include <qabstracttextdocumentlayout.h> +#include <qdebug.h> +#include <qpainter.h> +#include <qscopedvaluerollback.h> +#include <qtextcursor.h> +#include <qtextdocument.h> #include <math.h> #include <limits.h> @@ -121,14 +122,14 @@ void QSvgArc::draw(QPainter *p, QSvgExtraStates &states) } QSvgImage::QSvgImage(QSvgNode *parent, const QImage &image, - const QRect &bounds) + const QRectF &bounds) : QSvgNode(parent), m_image(image), m_bounds(bounds) { - if (m_bounds.width() == 0) - m_bounds.setWidth(m_image.width()); - if (m_bounds.height() == 0) - m_bounds.setHeight(m_image.height()); + if (m_bounds.width() == 0.0) + m_bounds.setWidth(static_cast<qreal>(m_image.width())); + if (m_bounds.height() == 0.0) + m_bounds.setHeight(static_cast<qreal>(m_image.height())); } void QSvgImage::draw(QPainter *p, QSvgExtraStates &states) @@ -458,14 +459,14 @@ void QSvgText::addText(const QString &text) } QSvgUse::QSvgUse(const QPointF &start, QSvgNode *parent, QSvgNode *node) - : QSvgNode(parent), m_link(node), m_start(start) + : QSvgNode(parent), m_link(node), m_start(start), m_recursing(false) { } void QSvgUse::draw(QPainter *p, QSvgExtraStates &states) { - if (Q_UNLIKELY(!m_link || isDescendantOf(m_link))) + if (Q_UNLIKELY(!m_link || isDescendantOf(m_link) || m_recursing)) return; applyStyle(p, states); @@ -473,7 +474,10 @@ void QSvgUse::draw(QPainter *p, QSvgExtraStates &states) if (!m_start.isNull()) { p->translate(m_start); } - m_link->draw(p, states); + { + QScopedValueRollback<bool> guard(m_recursing, true); + m_link->draw(p, states); + } if (!m_start.isNull()) { p->translate(-m_start); } @@ -556,7 +560,8 @@ QSvgNode::Type QSvgVideo::type() const QRectF QSvgUse::bounds(QPainter *p, QSvgExtraStates &states) const { QRectF bounds; - if (Q_LIKELY(m_link && !isDescendantOf(m_link))) { + if (Q_LIKELY(m_link && !isDescendantOf(m_link) && !m_recursing)) { + QScopedValueRollback<bool> guard(m_recursing, true); p->translate(m_start); bounds = m_link->transformedBounds(p, states); p->translate(-m_start); diff --git a/src/svg/qsvggraphics_p.h b/src/svg/qsvggraphics_p.h index 6e5b9d6..8488b33 100644 --- a/src/svg/qsvggraphics_p.h +++ b/src/svg/qsvggraphics_p.h @@ -104,13 +104,13 @@ class Q_SVG_PRIVATE_EXPORT QSvgImage : public QSvgNode { public: QSvgImage(QSvgNode *parent, const QImage &image, - const QRect &bounds); + const QRectF &bounds); void draw(QPainter *p, QSvgExtraStates &states) override; Type type() const override; QRectF bounds(QPainter *p, QSvgExtraStates &states) const override; private: QImage m_image; - QRect m_bounds; + QRectF m_bounds; }; class Q_SVG_PRIVATE_EXPORT QSvgLine : public QSvgNode @@ -251,6 +251,7 @@ private: QSvgNode *m_link; QPointF m_start; QString m_linkId; + mutable bool m_recursing; }; class QSvgVideo : public QSvgNode diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index 0468bbe..fe79977 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -774,21 +774,31 @@ static QVector<qreal> parsePercentageList(const QChar *&str) static QString idFromUrl(const QString &url) { + // The form is url(<IRI>), where IRI can be + // just an ID on #<id> form. QString::const_iterator itr = url.constBegin(); QString::const_iterator end = url.constEnd(); + QString id; while (itr != end && (*itr).isSpace()) ++itr; if (itr != end && (*itr) == QLatin1Char('(')) ++itr; + else + return QString(); while (itr != end && (*itr).isSpace()) ++itr; - if (itr != end && (*itr) == QLatin1Char('#')) + if (itr != end && (*itr) == QLatin1Char('#')) { + id += *itr; ++itr; - QString id; + } else { + return QString(); + } while (itr != end && (*itr) != QLatin1Char(')')) { id += *itr; ++itr; } + if (itr == end || (*itr) != QLatin1Char(')')) + return QString(); return id; } @@ -1596,7 +1606,7 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path) const QChar *end = str + dataStr.size(); while (str != end) { - while (str->isSpace()) + while (str->isSpace() && (str + 1) != end) ++str; QChar pathElem = *str; ++str; @@ -2605,17 +2615,17 @@ static QSvgStyleProperty *createFontNode(QSvgNode *parent, parent = parent->parent(); } - if (parent) { + if (parent && !myId.isEmpty()) { QSvgTinyDocument *doc = static_cast<QSvgTinyDocument*>(parent); - QSvgFont *font = new QSvgFont(horizAdvX); - font->setFamilyName(myId); - if (!font->familyName().isEmpty()) { - if (!doc->svgFont(font->familyName())) - doc->addSvgFont(font); + QSvgFont *font = doc->svgFont(myId); + if (!font) { + font = new QSvgFont(horizAdvX); + font->setFamilyName(myId); + doc->addSvgFont(font); } return new QSvgFontStyle(font, doc); } - return 0; + return nullptr; } static bool parseFontFaceNode(QSvgStyleProperty *parent, @@ -2792,10 +2802,10 @@ static QSvgNode *createImageNode(QSvgNode *parent, QSvgNode *img = new QSvgImage(parent, image, - QRect(int(nx), - int(ny), - int(nwidth), - int(nheight))); + QRectF(nx, + ny, + nwidth, + nheight)); return img; } @@ -3709,14 +3719,20 @@ bool QSvgHandler::startElement(const QString &localName, } break; default: + const QByteArray msg = QByteArrayLiteral("Could not add child element to parent element because the types are incorrect."); + qCWarning(lcSvgHandler, "%s", prefixMessage(msg, xml).constData()); + delete node; + node = 0; break; } } - parseCoreNode(node, attributes); + if (node) { + parseCoreNode(node, attributes); #ifndef QT_NO_CSSPARSER - cssStyleLookup(node, this, m_selector); + cssStyleLookup(node, this, m_selector); #endif - parseStyle(node, attributes, this); + parseStyle(node, attributes, this); + } } else if (FactoryMethod method = findGraphicsFactory(localName)) { //rendering element Q_ASSERT(!m_nodes.isEmpty()); @@ -3728,6 +3744,13 @@ bool QSvgHandler::startElement(const QString &localName, case QSvgNode::DEFS: case QSvgNode::SWITCH: { + if (node->type() == QSvgNode::TSPAN) { + const QByteArray msg = QByteArrayLiteral("\'tspan\' element in wrong context."); + qCWarning(lcSvgHandler, "%s", prefixMessage(msg, xml).constData()); + delete node; + node = 0; + break; + } QSvgStructureNode *group = static_cast<QSvgStructureNode*>(m_nodes.top()); group->addChild(node, someId(attributes)); diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp index 5448797..b934f94 100644 --- a/src/svg/qsvgstyle.cpp +++ b/src/svg/qsvgstyle.cpp @@ -942,13 +942,20 @@ void QSvgGradientStyle::setStopLink(const QString &link, QSvgTinyDocument *doc) void QSvgGradientStyle::resolveStops() { + QStringList visited; + resolveStops_helper(&visited); +} + +void QSvgGradientStyle::resolveStops_helper(QStringList *visited) +{ if (!m_link.isEmpty() && m_doc) { QSvgStyleProperty *prop = m_doc->styleProperty(m_link); - if (prop && prop != this) { + if (prop && !visited->contains(m_link)) { + visited->append(m_link); if (prop->type() == QSvgStyleProperty::GRADIENT) { QSvgGradientStyle *st = static_cast<QSvgGradientStyle*>(prop); - st->resolveStops(); + st->resolveStops_helper(visited); m_gradient->setStops(st->qgradient()->stops()); m_gradientStopsSet = st->gradientStopsSet(); } diff --git a/src/svg/qsvgstyle_p.h b/src/svg/qsvgstyle_p.h index 916c9fa..39aa690 100644 --- a/src/svg/qsvgstyle_p.h +++ b/src/svg/qsvgstyle_p.h @@ -577,6 +577,7 @@ public: void setStopLink(const QString &link, QSvgTinyDocument *doc); QString stopLink() const { return m_link; } void resolveStops(); + void resolveStops_helper(QStringList *visited); void setMatrix(const QMatrix &matrix); QMatrix qmatrix() const diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp index 15351bd..77aafb4 100644 --- a/src/svg/qsvgtinydocument.cpp +++ b/src/svg/qsvgtinydocument.cpp @@ -187,6 +187,7 @@ QSvgTinyDocument * QSvgTinyDocument::load(const QString &fileName) } else { qCWarning(lcSvgHandler, "Cannot read file '%s', because: %s (line %d)", qPrintable(fileName), qPrintable(handler.errorString()), handler.lineNumber()); + delete handler.document(); } return doc; } @@ -207,6 +208,8 @@ QSvgTinyDocument * QSvgTinyDocument::load(const QByteArray &contents) if (handler.ok()) { doc = handler.document(); doc->m_animationDuration = handler.animationDuration(); + } else { + delete handler.document(); } return doc; } @@ -219,6 +222,8 @@ QSvgTinyDocument * QSvgTinyDocument::load(QXmlStreamReader *contents) if (handler.ok()) { doc = handler.document(); doc->m_animationDuration = handler.animationDuration(); + } else { + delete handler.document(); } return doc; } @@ -334,6 +339,7 @@ void QSvgTinyDocument::setHeight(int len, bool percent) void QSvgTinyDocument::setViewBox(const QRectF &rect) { m_viewBox = rect; + m_implicitViewBox = false; } void QSvgTinyDocument::addSvgFont(QSvgFont *font) @@ -358,7 +364,10 @@ QSvgNode *QSvgTinyDocument::namedNode(const QString &id) const void QSvgTinyDocument::addNamedStyle(const QString &id, QSvgFillStyleProperty *style) { - m_namedStyles.insert(id, style); + if (!m_namedStyles.contains(id)) + m_namedStyles.insert(id, style); + else + qCWarning(lcSvgHandler) << "Duplicate unique style id:" << id; } QSvgFillStyleProperty *QSvgTinyDocument::namedStyle(const QString &id) const @@ -412,14 +421,35 @@ void QSvgTinyDocument::mapSourceToTarget(QPainter *p, const QRectF &targetRect, source = viewBox(); if (source != target && !source.isNull()) { - QTransform transform; - transform.scale(target.width() / source.width(), - target.height() / source.height()); - QRectF c2 = transform.mapRect(source); - p->translate(target.x() - c2.x(), - target.y() - c2.y()); - p->scale(target.width() / source.width(), - target.height() / source.height()); + if (m_implicitViewBox) { + QTransform transform; + transform.scale(target.width() / source.width(), + target.height() / source.height()); + QRectF c2 = transform.mapRect(source); + p->translate(target.x() - c2.x(), + target.y() - c2.y()); + p->scale(target.width() / source.width(), + target.height() / source.height()); + } else { + // Code path used when a view box is specified and we're not rendering a specific element by id + // but the entire document. This attempts to emulate the default values of the <preserveAspectRatio> + // tag that's implicitly defined when <viewbox> is used. + + // Apply the view box translation if specified. + p->translate(target.x() - source.x(), + target.y() - source.y()); + + // Scale the view box into the view port (target) by preserve the aspect ratio. + QSizeF viewBoxSize = source.size(); + viewBoxSize.scale(target.width(), target.height(), Qt::KeepAspectRatio); + + // Center the view box in the view port + p->translate((target.width() - viewBoxSize.width()) / 2, + (target.height() - viewBoxSize.height()) / 2); + + p->scale(viewBoxSize.width() / source.width(), + viewBoxSize.height() / source.height()); + } } } @@ -455,7 +485,7 @@ QMatrix QSvgTinyDocument::matrixForElement(const QString &id) const t *= node->m_style.transform->qtransform(); node = node->parent(); } - + return t.toAffine(); } diff --git a/src/svg/qsvgtinydocument_p.h b/src/svg/qsvgtinydocument_p.h index aa51751..5f5d06b 100644 --- a/src/svg/qsvgtinydocument_p.h +++ b/src/svg/qsvgtinydocument_p.h @@ -125,6 +125,7 @@ private: bool m_widthPercent; bool m_heightPercent; + mutable bool m_implicitViewBox = true; mutable QRectF m_viewBox; QHash<QString, QSvgRefCounter<QSvgFont> > m_fonts; @@ -173,8 +174,10 @@ inline bool QSvgTinyDocument::heightPercent() const inline QRectF QSvgTinyDocument::viewBox() const { - if (m_viewBox.isNull()) + if (m_viewBox.isNull()) { m_viewBox = transformedBounds(); + m_implicitViewBox = true; + } return m_viewBox; } |