597 lines
21 KiB
Diff
597 lines
21 KiB
Diff
diff --git a/src/plugins/imageformats/svg/qsvgiohandler.cpp b/src/plugins/imageformats/svg/qsvgiohandler.cpp
|
||
index bd39b2a..fd3529a 100644
|
||
--- a/src/plugins/imageformats/svg/qsvgiohandler.cpp
|
||
+++ b/src/plugins/imageformats/svg/qsvgiohandler.cpp
|
||
@@ -118,6 +118,24 @@ 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
|
||
{
|
||
@@ -126,15 +144,9 @@ bool QSvgIOHandler::canRead() const
|
||
if (d->loaded && !d->readDone)
|
||
return true; // Will happen if we have been asked for the size
|
||
|
||
- QByteArray buf = device()->peek(16);
|
||
-#ifndef QT_NO_COMPRESS
|
||
- if (buf.startsWith("\x1f\x8b")) {
|
||
- setFormat("svgz");
|
||
- return true;
|
||
- } else
|
||
-#endif
|
||
- if (buf.contains("<?xml") || buf.contains("<svg") || buf.contains("<!--") || buf.contains("<!DOCTYPE svg")) {
|
||
- setFormat("svg");
|
||
+ bool isCompressed = false;
|
||
+ if (isPossiblySvg(device(), &isCompressed)) {
|
||
+ setFormat(isCompressed ? "svgz" : "svg");
|
||
return true;
|
||
}
|
||
return false;
|
||
@@ -177,6 +189,8 @@ bool QSvgIOHandler::read(QImage *image)
|
||
}
|
||
}
|
||
if (!finalSize.isEmpty()) {
|
||
+ if (qMax(finalSize.width(), finalSize.height()) > 0xffff)
|
||
+ return false; // Assume corrupted file
|
||
image->fill(d->backColor.rgba());
|
||
QPainter p(image);
|
||
d->r.render(&p, bounds);
|
||
@@ -260,12 +274,7 @@ bool QSvgIOHandler::supportsOption(ImageOption option) const
|
||
|
||
bool QSvgIOHandler::canRead(QIODevice *device)
|
||
{
|
||
- QByteArray buf = device->peek(16);
|
||
- return
|
||
-#ifndef QT_NO_COMPRESS
|
||
- buf.startsWith("\x1f\x8b") ||
|
||
-#endif
|
||
- buf.contains("<?xml") || buf.contains("<svg") || buf.contains("<!--") || buf.contains("<!DOCTYPE svg");
|
||
+ return isPossiblySvg(device);
|
||
}
|
||
|
||
QT_END_NAMESPACE
|
||
diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp
|
||
index b3d9aaf..f2653af 100644
|
||
--- a/src/svg/qsvghandler.cpp
|
||
+++ b/src/svg/qsvghandler.cpp
|
||
@@ -673,7 +673,8 @@ static qreal toDouble(const QChar *&str)
|
||
val = -val;
|
||
} else {
|
||
val = QByteArray::fromRawData(temp, pos).toDouble();
|
||
- if (qFpClassify(val) != FP_NORMAL)
|
||
+ // Do not tolerate values too wild to be represented normally by floats
|
||
+ if (qFpClassify(float(val)) != FP_NORMAL)
|
||
val = 0;
|
||
}
|
||
return val;
|
||
@@ -727,15 +728,25 @@ static QVector<qreal> parseNumbersList(const QChar *&str)
|
||
return points;
|
||
}
|
||
|
||
-static inline void parseNumbersArray(const QChar *&str, QVarLengthArray<qreal, 8> &points)
|
||
+static inline void parseNumbersArray(const QChar *&str, QVarLengthArray<qreal, 8> &points,
|
||
+ const char *pattern = nullptr)
|
||
{
|
||
+ const size_t patternLen = qstrlen(pattern);
|
||
while (str->isSpace())
|
||
++str;
|
||
while (isDigit(str->unicode()) ||
|
||
*str == QLatin1Char('-') || *str == QLatin1Char('+') ||
|
||
*str == QLatin1Char('.')) {
|
||
|
||
- points.append(toDouble(str));
|
||
+ if (patternLen && pattern[points.size() % patternLen] == 'f') {
|
||
+ // flag expected, may only be 0 or 1
|
||
+ if (*str != QLatin1Char('0') && *str != QLatin1Char('1'))
|
||
+ return;
|
||
+ points.append(*str == QLatin1Char('0') ? 0.0 : 1.0);
|
||
+ ++str;
|
||
+ } else {
|
||
+ points.append(toDouble(str));
|
||
+ }
|
||
|
||
while (str->isSpace())
|
||
++str;
|
||
@@ -1382,8 +1393,10 @@ static void parseFont(QSvgNode *node,
|
||
case FontSizeNone:
|
||
break;
|
||
case FontSizeValue: {
|
||
- QSvgHandler::LengthType dummy; // should always be pixel size
|
||
- fontStyle->setSize(parseLength(attributes.fontSize, dummy, handler));
|
||
+ QSvgHandler::LengthType type;
|
||
+ qreal fs = parseLength(attributes.fontSize, type, handler);
|
||
+ fs = convertToPixels(fs, true, type);
|
||
+ fontStyle->setSize(qMin(fs, qreal(0xffff)));
|
||
}
|
||
break;
|
||
default:
|
||
@@ -1614,6 +1627,7 @@ static void pathArc(QPainterPath &path,
|
||
|
||
static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
{
|
||
+ const int maxElementCount = 0x7fff; // Assume file corruption if more path elements than this
|
||
qreal x0 = 0, y0 = 0; // starting point
|
||
qreal x = 0, y = 0; // current point
|
||
char lastMode = 0;
|
||
@@ -1621,28 +1635,31 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
const QChar *str = dataStr.constData();
|
||
const QChar *end = str + dataStr.size();
|
||
|
||
- while (str != end) {
|
||
+ bool ok = true;
|
||
+ while (ok && str != end) {
|
||
while (str->isSpace() && (str + 1) != end)
|
||
++str;
|
||
QChar pathElem = *str;
|
||
++str;
|
||
QChar endc = *end;
|
||
*const_cast<QChar *>(end) = 0; // parseNumbersArray requires 0-termination that QStringRef cannot guarantee
|
||
+ const char *pattern = nullptr;
|
||
+ if (pathElem == QLatin1Char('a') || pathElem == QLatin1Char('A'))
|
||
+ pattern = "rrrffrr";
|
||
QVarLengthArray<qreal, 8> arg;
|
||
- parseNumbersArray(str, arg);
|
||
+ parseNumbersArray(str, arg, pattern);
|
||
*const_cast<QChar *>(end) = endc;
|
||
if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z'))
|
||
arg.append(0);//dummy
|
||
const qreal *num = arg.constData();
|
||
int count = arg.count();
|
||
- while (count > 0) {
|
||
+ while (ok && count > 0) {
|
||
qreal offsetX = x; // correction offsets
|
||
qreal offsetY = y; // for relative commands
|
||
switch (pathElem.unicode()) {
|
||
case 'm': {
|
||
if (count < 2) {
|
||
- num++;
|
||
- count--;
|
||
+ ok = false;
|
||
break;
|
||
}
|
||
x = x0 = num[0] + offsetX;
|
||
@@ -1659,8 +1676,7 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
break;
|
||
case 'M': {
|
||
if (count < 2) {
|
||
- num++;
|
||
- count--;
|
||
+ ok = false;
|
||
break;
|
||
}
|
||
x = x0 = num[0];
|
||
@@ -1686,8 +1702,7 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
break;
|
||
case 'l': {
|
||
if (count < 2) {
|
||
- num++;
|
||
- count--;
|
||
+ ok = false;
|
||
break;
|
||
}
|
||
x = num[0] + offsetX;
|
||
@@ -1700,8 +1715,7 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
break;
|
||
case 'L': {
|
||
if (count < 2) {
|
||
- num++;
|
||
- count--;
|
||
+ ok = false;
|
||
break;
|
||
}
|
||
x = num[0];
|
||
@@ -1741,8 +1755,7 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
break;
|
||
case 'c': {
|
||
if (count < 6) {
|
||
- num += count;
|
||
- count = 0;
|
||
+ ok = false;
|
||
break;
|
||
}
|
||
QPointF c1(num[0] + offsetX, num[1] + offsetY);
|
||
@@ -1758,8 +1771,7 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
}
|
||
case 'C': {
|
||
if (count < 6) {
|
||
- num += count;
|
||
- count = 0;
|
||
+ ok = false;
|
||
break;
|
||
}
|
||
QPointF c1(num[0], num[1]);
|
||
@@ -1775,8 +1787,7 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
}
|
||
case 's': {
|
||
if (count < 4) {
|
||
- num += count;
|
||
- count = 0;
|
||
+ ok = false;
|
||
break;
|
||
}
|
||
QPointF c1;
|
||
@@ -1797,8 +1808,7 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
}
|
||
case 'S': {
|
||
if (count < 4) {
|
||
- num += count;
|
||
- count = 0;
|
||
+ ok = false;
|
||
break;
|
||
}
|
||
QPointF c1;
|
||
@@ -1819,8 +1829,7 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
}
|
||
case 'q': {
|
||
if (count < 4) {
|
||
- num += count;
|
||
- count = 0;
|
||
+ ok = false;
|
||
break;
|
||
}
|
||
QPointF c(num[0] + offsetX, num[1] + offsetY);
|
||
@@ -1835,8 +1844,7 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
}
|
||
case 'Q': {
|
||
if (count < 4) {
|
||
- num += count;
|
||
- count = 0;
|
||
+ ok = false;
|
||
break;
|
||
}
|
||
QPointF c(num[0], num[1]);
|
||
@@ -1851,8 +1859,7 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
}
|
||
case 't': {
|
||
if (count < 2) {
|
||
- num += count;
|
||
- count = 0;
|
||
+ ok = false;
|
||
break;
|
||
}
|
||
QPointF e(num[0] + offsetX, num[1] + offsetY);
|
||
@@ -1872,8 +1879,7 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
}
|
||
case 'T': {
|
||
if (count < 2) {
|
||
- num += count;
|
||
- count = 0;
|
||
+ ok = false;
|
||
break;
|
||
}
|
||
QPointF e(num[0], num[1]);
|
||
@@ -1893,8 +1899,7 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
}
|
||
case 'a': {
|
||
if (count < 7) {
|
||
- num += count;
|
||
- count = 0;
|
||
+ ok = false;
|
||
break;
|
||
}
|
||
qreal rx = (*num++);
|
||
@@ -1916,8 +1921,7 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
break;
|
||
case 'A': {
|
||
if (count < 7) {
|
||
- num += count;
|
||
- count = 0;
|
||
+ ok = false;
|
||
break;
|
||
}
|
||
qreal rx = (*num++);
|
||
@@ -1938,12 +1942,15 @@ static bool parsePathDataFast(const QStringRef &dataStr, QPainterPath &path)
|
||
}
|
||
break;
|
||
default:
|
||
- return false;
|
||
+ ok = false;
|
||
+ break;
|
||
}
|
||
lastMode = pathElem.toLatin1();
|
||
+ if (path.elementCount() > maxElementCount)
|
||
+ ok = false;
|
||
}
|
||
}
|
||
- return true;
|
||
+ return ok;
|
||
}
|
||
|
||
static bool parseStyle(QSvgNode *node,
|
||
@@ -2357,6 +2364,27 @@ static bool parseAnimateNode(QSvgNode *parent,
|
||
return true;
|
||
}
|
||
|
||
+static int parseClockValue(QString str, bool *ok)
|
||
+{
|
||
+ int res = 0;
|
||
+ int ms = 1000;
|
||
+ str = str.trimmed();
|
||
+ if (str.endsWith(QLatin1String("ms"))) {
|
||
+ str.chop(2);
|
||
+ ms = 1;
|
||
+ } else if (str.endsWith(QLatin1String("s"))) {
|
||
+ str.chop(1);
|
||
+ }
|
||
+ double val = ms * toDouble(str, ok);
|
||
+ if (ok) {
|
||
+ if (val > std::numeric_limits<int>::min() && val < std::numeric_limits<int>::max())
|
||
+ res = static_cast<int>(val);
|
||
+ else
|
||
+ *ok = false;
|
||
+ }
|
||
+ return res;
|
||
+}
|
||
+
|
||
static bool parseAnimateColorNode(QSvgNode *parent,
|
||
const QXmlStreamAttributes &attributes,
|
||
QSvgHandler *handler)
|
||
@@ -2390,23 +2418,13 @@ static bool parseAnimateColorNode(QSvgNode *parent,
|
||
}
|
||
}
|
||
|
||
- int ms = 1000;
|
||
- beginStr = beginStr.trimmed();
|
||
- if (beginStr.endsWith(QLatin1String("ms"))) {
|
||
- beginStr.chop(2);
|
||
- ms = 1;
|
||
- } else if (beginStr.endsWith(QLatin1String("s"))) {
|
||
- beginStr.chop(1);
|
||
- }
|
||
- durStr = durStr.trimmed();
|
||
- if (durStr.endsWith(QLatin1String("ms"))) {
|
||
- durStr.chop(2);
|
||
- ms = 1;
|
||
- } else if (durStr.endsWith(QLatin1String("s"))) {
|
||
- durStr.chop(1);
|
||
- }
|
||
- int begin = static_cast<int>(toDouble(beginStr) * ms);
|
||
- int end = static_cast<int>((toDouble(durStr) + begin) * ms);
|
||
+ bool ok = true;
|
||
+ int begin = parseClockValue(beginStr, &ok);
|
||
+ if (!ok)
|
||
+ return false;
|
||
+ int end = begin + parseClockValue(durStr, &ok);
|
||
+ if (!ok || end <= begin)
|
||
+ return false;
|
||
|
||
QSvgAnimateColor *anim = new QSvgAnimateColor(begin, end, 0);
|
||
anim->setArgs((targetStr == QLatin1String("fill")), colors);
|
||
@@ -2496,24 +2514,13 @@ static bool parseAnimateTransformNode(QSvgNode *parent,
|
||
}
|
||
}
|
||
|
||
- int ms = 1000;
|
||
- beginStr = beginStr.trimmed();
|
||
- if (beginStr.endsWith(QLatin1String("ms"))) {
|
||
- beginStr.chop(2);
|
||
- ms = 1;
|
||
- } else if (beginStr.endsWith(QLatin1String("s"))) {
|
||
- beginStr.chop(1);
|
||
- }
|
||
- int begin = static_cast<int>(toDouble(beginStr) * ms);
|
||
- durStr = durStr.trimmed();
|
||
- if (durStr.endsWith(QLatin1String("ms"))) {
|
||
- durStr.chop(2);
|
||
- ms = 1;
|
||
- } else if (durStr.endsWith(QLatin1String("s"))) {
|
||
- durStr.chop(1);
|
||
- ms = 1000;
|
||
- }
|
||
- int end = static_cast<int>(toDouble(durStr)*ms) + begin;
|
||
+ bool ok = true;
|
||
+ int begin = parseClockValue(beginStr, &ok);
|
||
+ if (!ok)
|
||
+ return false;
|
||
+ int end = begin + parseClockValue(durStr, &ok);
|
||
+ if (!ok || end <= begin)
|
||
+ return false;
|
||
|
||
QSvgAnimateTransform::TransformType type = QSvgAnimateTransform::Empty;
|
||
if (typeStr == QLatin1String("translate")) {
|
||
@@ -2569,6 +2576,8 @@ static QSvgNode *createCircleNode(QSvgNode *parent,
|
||
qreal ncx = toDouble(cx);
|
||
qreal ncy = toDouble(cy);
|
||
qreal nr = toDouble(r);
|
||
+ if (nr < 0.0)
|
||
+ return nullptr;
|
||
|
||
QRectF rect(ncx-nr, ncy-nr, nr*2, nr*2);
|
||
QSvgNode *circle = new QSvgCircle(parent, rect);
|
||
@@ -2979,8 +2988,8 @@ static QSvgNode *createPathNode(QSvgNode *parent,
|
||
|
||
QPainterPath qpath;
|
||
qpath.setFillRule(Qt::WindingFill);
|
||
- //XXX do error handling
|
||
- parsePathDataFast(data, qpath);
|
||
+ if (!parsePathDataFast(data, qpath))
|
||
+ qCWarning(lcSvgHandler, "Invalid path data; path truncated.");
|
||
|
||
QSvgNode *path = new QSvgPath(parent, qpath);
|
||
return path;
|
||
@@ -3039,13 +3048,16 @@ static QSvgStyleProperty *createRadialGradientNode(QSvgNode *node,
|
||
|
||
qreal ncx = 0.5;
|
||
qreal ncy = 0.5;
|
||
- qreal nr = 0.5;
|
||
if (!cx.isEmpty())
|
||
ncx = toDouble(cx);
|
||
if (!cy.isEmpty())
|
||
ncy = toDouble(cy);
|
||
+
|
||
+ qreal nr = 0.0;
|
||
if (!r.isEmpty())
|
||
nr = toDouble(r);
|
||
+ if (nr <= 0.0)
|
||
+ return nullptr;
|
||
|
||
qreal nfx = ncx;
|
||
if (!fx.isEmpty())
|
||
@@ -3341,7 +3353,9 @@ static QSvgNode *createTextNode(QSvgNode *parent,
|
||
//### editable and rotate not handled
|
||
QSvgHandler::LengthType type;
|
||
qreal nx = parseLength(x, type, handler);
|
||
+ nx = convertToPixels(nx, true, type);
|
||
qreal ny = parseLength(y, type, handler);
|
||
+ ny = convertToPixels(ny, true, type);
|
||
|
||
QSvgNode *text = new QSvgText(parent, QPointF(nx, ny));
|
||
return text;
|
||
@@ -3682,9 +3696,7 @@ void QSvgHandler::parse()
|
||
case QXmlStreamReader::EndElement:
|
||
endElement(xml->name());
|
||
++remainingUnfinishedElements;
|
||
- // if we are using somebody else's qxmlstreamreader
|
||
- // we should not read until the end of the stream
|
||
- done = !m_ownsReader && (xml->name() == QLatin1String("svg"));
|
||
+ done = (xml->name() == QLatin1String("svg"));
|
||
break;
|
||
case QXmlStreamReader::Characters:
|
||
characters(xml->text());
|
||
diff --git a/src/svg/qsvgstructure.cpp b/src/svg/qsvgstructure.cpp
|
||
index b89608b..89c9e4e 100644
|
||
--- a/src/svg/qsvgstructure.cpp
|
||
+++ b/src/svg/qsvgstructure.cpp
|
||
@@ -255,9 +255,13 @@ inline static bool isSupportedSvgFeature(const QString &str)
|
||
};
|
||
|
||
if (str.length() <= MAX_WORD_LENGTH && str.length() >= MIN_WORD_LENGTH) {
|
||
+ const char16_t unicode44 = str.at(44).unicode();
|
||
+ const char16_t unicode45 = str.at(45).unicode();
|
||
+ if (unicode44 >= sizeof(asso_values) || unicode45 >= sizeof(asso_values))
|
||
+ return false;
|
||
const int key = str.length()
|
||
- + asso_values[str.at(45).unicode()]
|
||
- + asso_values[str.at(44).unicode()];
|
||
+ + asso_values[unicode45]
|
||
+ + asso_values[unicode44];
|
||
if (key <= MAX_HASH_VALUE && key >= 0)
|
||
return str == QLatin1String(wordlist[key]);
|
||
}
|
||
diff --git a/tests/auto/qsvgplugin/simple_Utf16BE.svg b/tests/auto/qsvgplugin/simple_Utf16BE.svg
|
||
new file mode 100644
|
||
index 0000000..c3312cb
|
||
Binary files /dev/null and b/tests/auto/qsvgplugin/simple_Utf16BE.svg differ
|
||
diff --git a/tests/auto/qsvgplugin/simple_Utf16LE.svg b/tests/auto/qsvgplugin/simple_Utf16LE.svg
|
||
new file mode 100644
|
||
index 0000000..cdbeda9
|
||
Binary files /dev/null and b/tests/auto/qsvgplugin/simple_Utf16LE.svg differ
|
||
diff --git a/tests/auto/qsvgplugin/simple_Utf32BE.svg b/tests/auto/qsvgplugin/simple_Utf32BE.svg
|
||
new file mode 100644
|
||
index 0000000..0d5d02c
|
||
Binary files /dev/null and b/tests/auto/qsvgplugin/simple_Utf32BE.svg differ
|
||
diff --git a/tests/auto/qsvgplugin/simple_Utf32LE.svg b/tests/auto/qsvgplugin/simple_Utf32LE.svg
|
||
new file mode 100644
|
||
index 0000000..58a7159
|
||
Binary files /dev/null and b/tests/auto/qsvgplugin/simple_Utf32LE.svg differ
|
||
diff --git a/tests/auto/qsvgplugin/simple_Utf8.svg b/tests/auto/qsvgplugin/simple_Utf8.svg
|
||
new file mode 100644
|
||
index 0000000..2052c48
|
||
--- /dev/null
|
||
+++ b/tests/auto/qsvgplugin/simple_Utf8.svg
|
||
@@ -0,0 +1,3 @@
|
||
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg">
|
||
+ <circle cx="50" cy="50" r="25" fill="#00ff00" />
|
||
+</svg>
|
||
diff --git a/tests/auto/qsvgplugin/tst_qsvgplugin.cpp b/tests/auto/qsvgplugin/tst_qsvgplugin.cpp
|
||
index e1f84f3..73bbe8b 100644
|
||
--- a/tests/auto/qsvgplugin/tst_qsvgplugin.cpp
|
||
+++ b/tests/auto/qsvgplugin/tst_qsvgplugin.cpp
|
||
@@ -61,6 +61,8 @@ private slots:
|
||
void checkSize_data();
|
||
void checkSize();
|
||
void checkImageInclude();
|
||
+ void encodings_data();
|
||
+ void encodings();
|
||
};
|
||
|
||
|
||
@@ -145,6 +147,36 @@ void tst_QSvgPlugin::checkImageInclude()
|
||
logMessages.clear();
|
||
}
|
||
|
||
+void tst_QSvgPlugin::encodings_data()
|
||
+{
|
||
+ QTest::addColumn<QString>("filename");
|
||
+
|
||
+ QTest::newRow("utf-8") << QFINDTESTDATA("simple_Utf8.svg");
|
||
+ 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");
|
||
+}
|
||
+
|
||
+void tst_QSvgPlugin::encodings()
|
||
+{
|
||
+ QFETCH(QString, filename);
|
||
+
|
||
+ {
|
||
+ QFile file(filename);
|
||
+ file.open(QIODevice::ReadOnly);
|
||
+ QVERIFY(QSvgIOHandler::canRead(&file));
|
||
+ }
|
||
+
|
||
+ QFile file(filename);
|
||
+ file.open(QIODevice::ReadOnly);
|
||
+ QSvgIOHandler plugin;
|
||
+ plugin.setDevice(&file);
|
||
+ QVERIFY(plugin.canRead());
|
||
+ QImage img;
|
||
+ QVERIFY(plugin.read(&img));
|
||
+ QCOMPARE(img.size(), QSize(50, 50));
|
||
+}
|
||
|
||
QTEST_MAIN(tst_QSvgPlugin)
|
||
#include "tst_qsvgplugin.moc"
|
||
diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
|
||
index 8f1f03b..36c76ec 100644
|
||
--- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
|
||
+++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp
|
||
@@ -74,6 +74,7 @@ private slots:
|
||
void fillRule();
|
||
void opacity();
|
||
void paths();
|
||
+ void paths2();
|
||
void displayMode();
|
||
void strokeInherit();
|
||
void testFillInheritance();
|
||
@@ -1047,6 +1048,19 @@ void tst_QSvgRenderer::paths()
|
||
}
|
||
}
|
||
|
||
+void tst_QSvgRenderer::paths2()
|
||
+{
|
||
+ const char *svg =
|
||
+ "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\">"
|
||
+ "<path d=\"M 3 8 A 5 5 0 1013 8\" id=\"path1\"/>"
|
||
+ "</svg>";
|
||
+
|
||
+ QByteArray data(svg);
|
||
+ QSvgRenderer renderer(data);
|
||
+ QVERIFY(renderer.isValid());
|
||
+ QCOMPARE(renderer.boundsOnElement(QLatin1String("path1")).toRect(), QRect(3, 8, 10, 5));
|
||
+}
|
||
+
|
||
void tst_QSvgRenderer::displayMode()
|
||
{
|
||
static const char *svgs[] = {
|