summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/svg/qsvgtinydocument.cpp38
-rw-r--r--src/svg/qsvgtinydocument_p.h5
-rw-r--r--tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp10
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()