summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/imageformats/svg/CMakeLists.txt2
-rw-r--r--src/plugins/imageformats/svg/qsvgiohandler.cpp24
-rw-r--r--src/svg/qsvgtinydocument.cpp53
-rw-r--r--src/svg/qsvgtinydocument_p.h19
-rw-r--r--tests/auto/qsvgplugin/CMakeLists.txt4
-rw-r--r--tests/auto/qsvgplugin/simple_Utf32BE.svg.gzbin0 -> 185 bytes
-rw-r--r--tests/auto/qsvgplugin/simple_Utf8.svgzbin0 -> 141 bytes
-rw-r--r--tests/auto/qsvgplugin/tst_qsvgplugin.cpp2
8 files changed, 70 insertions, 34 deletions
diff --git a/src/plugins/imageformats/svg/CMakeLists.txt b/src/plugins/imageformats/svg/CMakeLists.txt
index 140e281..ec69a02 100644
--- a/src/plugins/imageformats/svg/CMakeLists.txt
+++ b/src/plugins/imageformats/svg/CMakeLists.txt
@@ -14,5 +14,5 @@ qt_internal_add_plugin(QSvgPlugin
LIBRARIES
Qt::Core
Qt::Gui
- Qt::Svg
+ Qt::SvgPrivate
)
diff --git a/src/plugins/imageformats/svg/qsvgiohandler.cpp b/src/plugins/imageformats/svg/qsvgiohandler.cpp
index 570c982..1212f80 100644
--- a/src/plugins/imageformats/svg/qsvgiohandler.cpp
+++ b/src/plugins/imageformats/svg/qsvgiohandler.cpp
@@ -6,6 +6,7 @@
#ifndef QT_NO_SVGRENDERER
#include "qsvgrenderer.h"
+#include "private/qsvgtinydocument_p.h"
#include "qimage.h"
#include "qpixmap.h"
#include "qpainter.h"
@@ -84,25 +85,6 @@ QSvgIOHandler::~QSvgIOHandler()
delete d;
}
-static bool isPossiblySvg(QIODevice *device, bool *isCompressed = nullptr)
-{
- constexpr int bufSize = 64;
- char buf[bufSize];
- const qint64 readLen = device->peek(buf, bufSize);
- if (readLen < 8)
- return false;
-# ifndef QT_NO_COMPRESS
- if (quint8(buf[0]) == 0x1f && quint8(buf[1]) == 0x8b) {
- if (isCompressed)
- *isCompressed = true;
- return true;
- }
-# endif
- QTextStream str(QByteArray::fromRawData(buf, readLen));
- QByteArray ba = str.read(16).trimmed().toLatin1();
- return ba.startsWith("<?xml") || ba.startsWith("<svg") || ba.startsWith("<!--") || ba.startsWith("<!DOCTYPE svg");
-}
-
bool QSvgIOHandler::canRead() const
{
if (!device())
@@ -111,7 +93,7 @@ bool QSvgIOHandler::canRead() const
return true; // Will happen if we have been asked for the size
bool isCompressed = false;
- if (isPossiblySvg(device(), &isCompressed)) {
+ if (QSvgTinyDocument::isLikelySvg(device(), &isCompressed)) {
setFormat(isCompressed ? "svgz" : "svg");
return true;
}
@@ -237,7 +219,7 @@ bool QSvgIOHandler::supportsOption(ImageOption option) const
bool QSvgIOHandler::canRead(QIODevice *device)
{
- return isPossiblySvg(device);
+ return QSvgTinyDocument::isLikelySvg(device);
}
QT_END_NAMESPACE
diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp
index 246df7b..94f21ca 100644
--- a/src/svg/qsvgtinydocument.cpp
+++ b/src/svg/qsvgtinydocument.cpp
@@ -21,6 +21,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
QSvgTinyDocument::QSvgTinyDocument(QtSvg::Options options)
: QSvgStructureNode(0)
, m_widthPercent(false)
@@ -37,6 +39,19 @@ QSvgTinyDocument::~QSvgTinyDocument()
{
}
+static bool hasSvgHeader(const QByteArray &buf)
+{
+ QTextStream s(buf); // Handle multi-byte encodings
+ QString h = s.readAll();
+ QStringView th = QStringView(h).trimmed();
+ bool matched = false;
+ if (th.startsWith("<svg"_L1) || th.startsWith("<!DOCTYPE svg"_L1))
+ matched = true;
+ else if (th.startsWith("<?xml"_L1) || th.startsWith("<!--"_L1))
+ matched = th.contains("<!DOCTYPE svg"_L1) || th.contains("<svg"_L1);
+ return matched;
+}
+
#ifndef QT_NO_COMPRESS
static QByteArray qt_inflateSvgzDataFrom(QIODevice *device, bool doCheckContent = true);
# ifdef QT_BUILD_INTERNAL
@@ -124,8 +139,7 @@ static QByteArray qt_inflateSvgzDataFrom(QIODevice *device, bool doCheckContent)
if (doCheckContent) {
// Quick format check, equivalent to QSvgIOHandler::canRead()
- QByteArray buf = destination.left(16);
- if (!buf.contains("<?xml") && !buf.contains("<svg") && !buf.contains("<!--") && !buf.contains("<!DOCTYPE svg")) {
+ if (!hasSvgHeader(destination)) {
inflateEnd(&zlibStream);
qCWarning(lcSvgHandler, "Error while inflating gzip file: SVG format check failed");
return QByteArray();
@@ -521,4 +535,39 @@ void QSvgTinyDocument::setFramesPerSecond(int num)
m_fps = num;
}
+bool QSvgTinyDocument::isLikelySvg(QIODevice *device, bool *isCompressed)
+{
+ constexpr int bufSize = 4096;
+ char buf[bufSize];
+ char inflateBuf[bufSize];
+ bool useInflateBuf = false;
+ int readLen = device->peek(buf, bufSize);
+ if (readLen < 8)
+ return false;
+#ifndef QT_NO_COMPRESS
+ if (quint8(buf[0]) == 0x1f && quint8(buf[1]) == 0x8b) {
+ // Indicates gzip compressed content, i.e. svgz
+ z_stream zlibStream;
+ zlibStream.avail_in = readLen;
+ zlibStream.next_out = reinterpret_cast<Bytef *>(inflateBuf);
+ zlibStream.avail_out = bufSize;
+ zlibStream.next_in = reinterpret_cast<Bytef *>(buf);
+ zlibStream.zalloc = Z_NULL;
+ zlibStream.zfree = Z_NULL;
+ zlibStream.opaque = Z_NULL;
+ if (inflateInit2(&zlibStream, MAX_WBITS + 16) != Z_OK)
+ return false;
+ int zlibResult = inflate(&zlibStream, Z_NO_FLUSH);
+ inflateEnd(&zlibStream);
+ if ((zlibResult != Z_OK && zlibResult != Z_STREAM_END) || zlibStream.total_out < 8)
+ return false;
+ readLen = zlibStream.total_out;
+ if (isCompressed)
+ *isCompressed = true;
+ useInflateBuf = true;
+ }
+#endif
+ return hasSvgHeader(QByteArray::fromRawData(useInflateBuf ? inflateBuf : buf, readLen));
+}
+
QT_END_NAMESPACE
diff --git a/src/svg/qsvgtinydocument_p.h b/src/svg/qsvgtinydocument_p.h
index 9501a95..a3f5489 100644
--- a/src/svg/qsvgtinydocument_p.h
+++ b/src/svg/qsvgtinydocument_p.h
@@ -39,23 +39,24 @@ public:
static QSvgTinyDocument *load(const QString &file, QtSvg::Options options = {});
static QSvgTinyDocument *load(const QByteArray &contents, QtSvg::Options options = {});
static QSvgTinyDocument *load(QXmlStreamReader *contents, QtSvg::Options options = {});
+ static bool isLikelySvg(QIODevice *device, bool *isCompressed = nullptr);
public:
QSvgTinyDocument(QtSvg::Options options);
~QSvgTinyDocument();
Type type() const override;
- QSize size() const;
+ inline QSize size() const;
void setWidth(int len, bool percent);
void setHeight(int len, bool percent);
- int width() const;
- int height() const;
- bool widthPercent() const;
- bool heightPercent() const;
+ inline int width() const;
+ inline int height() const;
+ inline bool widthPercent() const;
+ inline bool heightPercent() const;
- bool preserveAspectRatio() const;
+ inline bool preserveAspectRatio() const;
void setPreserveAspectRatio(bool on);
- QRectF viewBox() const;
+ inline QRectF viewBox() const;
void setViewBox(const QRectF &rect);
QtSvg::Options options() const;
@@ -79,10 +80,10 @@ public:
QSvgPaintStyleProperty *namedStyle(const QString &id) const;
void restartAnimation();
- int currentElapsed() const;
+ inline int currentElapsed() const;
bool animated() const;
void setAnimated(bool a);
- int animationDuration() const;
+ inline int animationDuration() const;
int currentFrame() const;
void setCurrentFrame(int);
void setFramesPerSecond(int num);
diff --git a/tests/auto/qsvgplugin/CMakeLists.txt b/tests/auto/qsvgplugin/CMakeLists.txt
index ffeef84..e9a516c 100644
--- a/tests/auto/qsvgplugin/CMakeLists.txt
+++ b/tests/auto/qsvgplugin/CMakeLists.txt
@@ -17,7 +17,7 @@ qt_internal_add_test(tst_qsvgplugin
LIBRARIES
Qt::Gui
Qt::GuiPrivate
- Qt::Svg
+ Qt::SvgPrivate
Qt::Widgets
)
@@ -39,10 +39,12 @@ set(resources_resource_files
"wide_size_viewbox.svg"
"wide_viewbox.svg"
"simple_Utf8.svg"
+ "simple_Utf8.svgz"
"simple_Utf16LE.svg"
"simple_Utf16BE.svg"
"simple_Utf32LE.svg"
"simple_Utf32BE.svg"
+ "simple_Utf32BE.svg.gz"
"invalid_xml.svg"
"xml_not_svg.svg"
"invalid_then_valid.svg"
diff --git a/tests/auto/qsvgplugin/simple_Utf32BE.svg.gz b/tests/auto/qsvgplugin/simple_Utf32BE.svg.gz
new file mode 100644
index 0000000..569a73f
--- /dev/null
+++ b/tests/auto/qsvgplugin/simple_Utf32BE.svg.gz
Binary files differ
diff --git a/tests/auto/qsvgplugin/simple_Utf8.svgz b/tests/auto/qsvgplugin/simple_Utf8.svgz
new file mode 100644
index 0000000..a51f38f
--- /dev/null
+++ b/tests/auto/qsvgplugin/simple_Utf8.svgz
Binary files differ
diff --git a/tests/auto/qsvgplugin/tst_qsvgplugin.cpp b/tests/auto/qsvgplugin/tst_qsvgplugin.cpp
index 762d373..0c9796e 100644
--- a/tests/auto/qsvgplugin/tst_qsvgplugin.cpp
+++ b/tests/auto/qsvgplugin/tst_qsvgplugin.cpp
@@ -138,10 +138,12 @@ void tst_QSvgPlugin::encodings_data()
QTest::addColumn<QString>("filename");
QTest::newRow("utf-8") << QFINDTESTDATA("simple_Utf8.svg");
+ QTest::newRow("utf-8_z") << QFINDTESTDATA("simple_Utf8.svgz");
QTest::newRow("utf-16LE") << QFINDTESTDATA("simple_Utf16LE.svg");
QTest::newRow("utf-16BE") << QFINDTESTDATA("simple_Utf16BE.svg");
QTest::newRow("utf-32LE") << QFINDTESTDATA("simple_Utf32LE.svg");
QTest::newRow("utf-32BE") << QFINDTESTDATA("simple_Utf32BE.svg");
+ QTest::newRow("utf-32BE_z") << QFINDTESTDATA("simple_Utf32BE.svg.gz");
}
void tst_QSvgPlugin::encodings()