diff options
-rw-r--r-- | src/svg/qsvgtinydocument.cpp | 38 | ||||
-rw-r--r-- | src/svg/qsvgtinydocument_p.h | 5 | ||||
-rw-r--r-- | tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp | 10 |
3 files changed, 44 insertions, 9 deletions
diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp index da464cc..77aafb4 100644 --- a/src/svg/qsvgtinydocument.cpp +++ b/src/svg/qsvgtinydocument.cpp @@ -339,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) @@ -420,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()); + } } } 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; } diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp index e0646f2..cf19213 100644 --- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp @@ -268,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() |