r21616 by jghali - #14362 related: fix sometime incorrect parsing of svg transform causing incorrect svg import

scribus-commit scribus-commit at lists.scribus.net
Thu Dec 8 23:56:12 UTC 2016


Author: jghali
Date: Thu Dec  8 23:56:12 2016
New Revision: 21616

URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=21616
Log:
#14362 related: fix sometime incorrect parsing of svg transform causing incorrect svg import

Modified:
    trunk/Scribus/scribus/plugins/import/svg/svgplugin.cpp
    trunk/Scribus/scribus/plugins/import/svg/svgplugin.h
    trunk/Scribus/scribus/scclocale.cpp
    trunk/Scribus/scribus/scclocale.h

Modified: trunk/Scribus/scribus/plugins/import/svg/svgplugin.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21616&path=/trunk/Scribus/scribus/plugins/import/svg/svgplugin.cpp
==============================================================================
--- trunk/Scribus/scribus/plugins/import/svg/svgplugin.cpp	(original)
+++ trunk/Scribus/scribus/plugins/import/svg/svgplugin.cpp	Thu Dec  8 23:56:12 2016
@@ -1647,6 +1647,37 @@
 	return LElements;
 }
 
+QVector<double> SVGPlug::parseNumbersList(const QString& numbersStr)
+{
+	QVector<double> numbers;
+	if (numbersStr.isEmpty())
+		return numbers;
+	numbers.reserve(8);
+
+	const QChar* str = numbersStr.data();
+
+	while (str->isSpace())
+		++str;
+	while (ScCLocale::isDigit(str->unicode()) ||
+	       *str == QLatin1Char('-') || *str == QLatin1Char('+') ||
+	       *str == QLatin1Char('.'))
+	{
+
+		numbers.append(ScCLocale::toDoubleC(str));
+
+		while (str->isSpace())
+			++str;
+		if (*str == QLatin1Char(','))
+			++str;
+
+		//eat the rest of space
+		while (str->isSpace())
+			++str;
+	}
+
+	return numbers;
+}
+
 QList<PageItem*> SVGPlug::parsePath(const QDomElement &e)
 {
 	FPointArray pArray;
@@ -2160,57 +2191,56 @@
 	QStringList subtransforms = trans.split(')', QString::SkipEmptyParts);
 	QStringList::ConstIterator it = subtransforms.begin();
 	QStringList::ConstIterator end = subtransforms.end();
-	for(; it != end; ++it)
+	for (; it != end; ++it)
 	{
 		QTransform result;
 		QStringList subtransform = it->split('(', QString::SkipEmptyParts);
 		subtransform[0] = subtransform[0].trimmed().toLower();
 		subtransform[1] = subtransform[1].simplified();
-		QRegExp reg("[,( ]");
-		QStringList params = subtransform[1].split(reg, QString::SkipEmptyParts);
-		if(subtransform[0].startsWith(";") || subtransform[0].startsWith(","))
+		QVector<double> params = parseNumbersList(subtransform[1]);
+		if (subtransform[0].startsWith(";") || subtransform[0].startsWith(","))
 			subtransform[0] = subtransform[0].right(subtransform[0].length() - 1);
-		if(subtransform[0] == "rotate")
-		{
-			if(params.count() == 3)
-			{
-				double x = ScCLocale::toDoubleC(params[1]);
-				double y = ScCLocale::toDoubleC(params[2]);
+		if (subtransform[0] == "rotate")
+		{
+			if (params.count() == 3)
+			{
+				double x = params[1];
+				double y = params[2];
 				result.translate(x, y);
-				result.rotate(ScCLocale::toDoubleC(params[0]));
+				result.rotate(params[0]);
 				result.translate(-x, -y);
 			}
 			else
-				result.rotate(ScCLocale::toDoubleC(params[0]));
-		}
-		else if(subtransform[0] == "translate")
+				result.rotate(params[0]);
+		}
+		else if (subtransform[0] == "translate")
+		{
+			if (params.count() == 2)
+				result.translate(params[0], params[1]);
+			else    // Spec : if only one param given, assume 2nd param to be 0
+				result.translate(params[0], 0);
+		}
+		else if (subtransform[0] == "scale")
 		{
 			if(params.count() == 2)
-				result.translate(ScCLocale::toDoubleC(params[0]), ScCLocale::toDoubleC(params[1]));
-			else    // Spec : if only one param given, assume 2nd param to be 0
-				result.translate(ScCLocale::toDoubleC(params[0]), 0);
-		}
-		else if(subtransform[0] == "scale")
-		{
-			if(params.count() == 2)
-				result.scale(ScCLocale::toDoubleC(params[0]), ScCLocale::toDoubleC(params[1]));
+				result.scale(params[0], params[1]);
 			else    // Spec : if only one param given, assume uniform scaling
-				result.scale(ScCLocale::toDoubleC(params[0]), ScCLocale::toDoubleC(params[0]));
-		}
-		else if(subtransform[0] == "skewx")
-			result.shear(tan(ScCLocale::toDoubleC(params[0]) * 0.01745329251994329576), 0.0F);
-		else if(subtransform[0] == "skewy")
-			result.shear(0.0F, tan(ScCLocale::toDoubleC(params[0]) * 0.01745329251994329576));
-		else if(subtransform[0] == "matrix")
-		{
-			if(params.count() >= 6)
-			{
-				double sx = ScCLocale::toDoubleC(params[0]);
-				double sy = ScCLocale::toDoubleC(params[3]);
-				double p1 = ScCLocale::toDoubleC(params[1]);
-				double p2 = ScCLocale::toDoubleC(params[2]);
-				double p4 = ScCLocale::toDoubleC(params[4]);
-				double p5 = ScCLocale::toDoubleC(params[5]);
+				result.scale(params[0], params[0]);
+		}
+		else if (subtransform[0] == "skewx")
+			result.shear(tan(params[0] * 0.01745329251994329576), 0.0F);
+		else if (subtransform[0] == "skewy")
+			result.shear(0.0F, tan(params[0] * 0.01745329251994329576));
+		else if (subtransform[0] == "matrix")
+		{
+			if (params.count() >= 6)
+			{
+				double sx = params[0];
+				double sy = params[3];
+				double p1 = params[1];
+				double p2 = params[2];
+				double p4 = params[4];
+				double p5 = params[5];
 				result = QTransform(sx, p1, p2, sy, p4, p5);
 			}
 		}

Modified: trunk/Scribus/scribus/plugins/import/svg/svgplugin.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21616&path=/trunk/Scribus/scribus/plugins/import/svg/svgplugin.h
==============================================================================
--- trunk/Scribus/scribus/plugins/import/svg/svgplugin.h	(original)
+++ trunk/Scribus/scribus/plugins/import/svg/svgplugin.h	Thu Dec  8 23:56:12 2016
@@ -334,6 +334,9 @@
 	QMap<QString, filterSpec> filters;
 	QMap<QString, markerDesc> markers;
 	QList<PageItem*> Elements;
+
+protected:
+	QVector<double> parseNumbersList(const QString& numbersStr);
 };
 
 #endif

Modified: trunk/Scribus/scribus/scclocale.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21616&path=/trunk/Scribus/scribus/scclocale.cpp
==============================================================================
--- trunk/Scribus/scribus/scclocale.cpp	(original)
+++ trunk/Scribus/scribus/scclocale.cpp	Thu Dec  8 23:56:12 2016
@@ -13,6 +13,8 @@
 #include "scclocale.h"
 
 #include <cstdlib>
+
+#include <QByteArray>
 #include <QDebug>
 
 ScCLocale * ScCLocale::m_instance = 0;
@@ -49,6 +51,84 @@
 		Q_ASSERT(m_instance);
 	}
 	return m_instance;
+}
+
+// The code of this function has been borrowed
+// from Qt SVG module
+double ScCLocale::toDoubleC(const QChar *&str)
+{
+	const int maxLen = 255;//technically doubles can go til 308+ but whatever
+	char temp[maxLen+1];
+	int pos = 0;
+
+	if (*str == QLatin1Char('-')) {
+		temp[pos++] = '-';
+		++str;
+	} else if (*str == QLatin1Char('+')) {
+		++str;
+	}
+	while (isDigit(str->unicode()) && pos < maxLen) {
+		temp[pos++] = str->toLatin1();
+		++str;
+	}
+	if (*str == QLatin1Char('.') && pos < maxLen) {
+		temp[pos++] = '.';
+		++str;
+	}
+	while (isDigit(str->unicode()) && pos < maxLen) {
+		temp[pos++] = str->toLatin1();
+		++str;
+	}
+	bool exponent = false;
+	if ((*str == QLatin1Char('e') || *str == QLatin1Char('E')) && pos < maxLen) {
+		exponent = true;
+		temp[pos++] = 'e';
+		++str;
+		if ((*str == QLatin1Char('-') || *str == QLatin1Char('+')) && pos < maxLen) {
+			temp[pos++] = str->toLatin1();
+			++str;
+		}
+		while (isDigit(str->unicode()) && pos < maxLen) {
+			temp[pos++] = str->toLatin1();
+			++str;
+		}
+	}
+
+	temp[pos] = '\0';
+
+	double val;
+	if (!exponent && pos < 10) {
+		int ival = 0;
+		const char *t = temp;
+		bool neg = false;
+		if (*t == '-') {
+			neg = true;
+			++t;
+		}
+		while (*t && *t != '.') {
+			ival *= 10;
+			ival += (*t) - '0';
+			++t;
+		}
+		if (*t == '.') {
+			++t;
+			int div = 1;
+			while (*t) {
+				ival *= 10;
+				ival += (*t) - '0';
+				div *= 10;
+				++t;
+			}
+			val = ((double) ival) / ((double) div);
+		} else {
+			val = ival;
+		}
+		if (neg)
+			val = -val;
+	} else {
+		val = QByteArray::fromRawData(temp, pos).toDouble();
+	}
+	return val;
 }
 
 double ScCLocale::toDoubleC(const QString & str, bool * ok) 

Modified: trunk/Scribus/scribus/scclocale.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=21616&path=/trunk/Scribus/scribus/scclocale.h
==============================================================================
--- trunk/Scribus/scribus/scclocale.h	(original)
+++ trunk/Scribus/scribus/scclocale.h	Thu Dec  8 23:56:12 2016
@@ -48,6 +48,8 @@
 	static ScCLocale * that();
 	
 	public:
+		static inline bool isDigit(ushort ch);
+		static double toDoubleC(const QChar *&str);
 		static double toDoubleC(const QString& str, bool * ok = 0);
 		static double toDoubleC(const QString& str, double defValue);
 		static float toFloatC(const QString& str, bool * ok = 0);
@@ -57,6 +59,13 @@
 		
 };
 
+// The code of this function has been borrowed from Qt SVG module
+inline bool ScCLocale::isDigit(ushort ch)
+{
+	static quint16 magic = 0x3ff;
+	return ((ch >> 4) == 3) && (magic >> (ch & 15));
+}
+
 #endif // SCCLOCALE_H
 
 




More information about the scribus-commit mailing list