r24370 by jghali - #15682: Scribus crashes when checking fonts on startup

scribus-commit scribus-commit at lists.scribus.net
Mon Jan 4 17:02:06 UTC 2021


Author: jghali
Date: Mon Jan  4 17:02:06 2021
New Revision: 24370

URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=24370
Log:
#15682: Scribus crashes when checking fonts on startup

Modified:
    trunk/Scribus/scribus/scfonts.cpp

Modified: trunk/Scribus/scribus/scfonts.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24370&path=/trunk/Scribus/scribus/scfonts.cpp
==============================================================================
--- trunk/Scribus/scribus/scfonts.cpp	(original)
+++ trunk/Scribus/scribus/scfonts.cpp	Mon Jan  4 17:02:06 2021
@@ -247,20 +247,20 @@
 	type = ScFace::UNKNOWN_TYPE;
 	if (ftIOFunc(fts, 0L, reinterpret_cast<FT_Byte *>(buf), 128) == FONT_NO_ERROR) 
 	{
-		if (strncmp(buf,T42_HEAD,strlen(T42_HEAD)) == 0) 
+		if (strncmp(buf, T42_HEAD, strlen(T42_HEAD)) == 0) 
 		{
 			fmt = ScFace::TYPE42;
 			type = ScFace::TTF;
 		}
-		else if (strncmp(buf,T1_HEAD,strlen(T1_HEAD)) == 0 ||
-			     strncmp(buf,T1_ADOBE_HEAD,strlen(T1_ADOBE_HEAD)) == 0) 
+		else if (strncmp(buf, T1_HEAD, strlen(T1_HEAD)) == 0 ||
+			     strncmp(buf, T1_ADOBE_HEAD, strlen(T1_ADOBE_HEAD)) == 0) 
 		{
 			fmt = ScFace::PFA;
 			type = ScFace::TYPE1;
 		}
-		else if (strncmp(buf,PSFONT_ADOBE2_HEAD,strlen(PSFONT_ADOBE2_HEAD)) == 0 ||
-			     strncmp(buf,PSFONT_ADOBE21_HEAD,strlen(PSFONT_ADOBE21_HEAD)) == 0 ||
-			     strncmp(buf,PSFONT_ADOBE3_HEAD,strlen(PSFONT_ADOBE3_HEAD)) ==0) 
+		else if (strncmp(buf, PSFONT_ADOBE2_HEAD, strlen(PSFONT_ADOBE2_HEAD)) == 0 ||
+			     strncmp(buf, PSFONT_ADOBE21_HEAD, strlen(PSFONT_ADOBE21_HEAD)) == 0 ||
+			     strncmp(buf, PSFONT_ADOBE3_HEAD, strlen(PSFONT_ADOBE3_HEAD)) == 0) 
 		{
 			// Type2(CFF), Type0(Composite/CID), Type 3, Type 14 etc would end here
 			fmt = ScFace::PFA;
@@ -277,17 +277,17 @@
 			fmt = ScFace::SFNT;
 			type = ScFace::TTF;
 		}
-		else if (strncmp(buf,"true",4) == 0)
+		else if (strncmp(buf, "true", 4) == 0)
 		{
 			fmt = ScFace::SFNT;
 			type = ScFace::TTF;
 		}
-		else if (strncmp(buf,"ttcf",4) == 0)
+		else if (strncmp(buf, "ttcf", 4) == 0)
 		{
 			fmt = ScFace::TTCF;
 			type = ScFace::OTF;
 		}
-		else if (strncmp(buf,"OTTO",4) == 0)
+		else if (strncmp(buf, "OTTO", 4) == 0)
 		{
 			fmt = ScFace::SFNT;
 			type = ScFace::OTF;
@@ -378,7 +378,9 @@
 
 static QString decodeNameRecord(FT_SfntName name)
 {
-	QString string;
+	if (!name.string || name.string_len == 0)
+		return QString();
+
 	QByteArray encoding;
 	if (name.platform_id == TT_PLATFORM_APPLE_UNICODE)
 	{
@@ -396,7 +398,7 @@
 			encoding = "Shift-JIS";
 			break;
 		case TT_MS_ID_GB2312:
-			encoding = "GB18030-0";
+			encoding = "GB18030";
 			break;
 		case TT_MS_ID_BIG_5:
 			encoding = "Big5";
@@ -406,13 +408,24 @@
 		}
 	}
 
-	if (!encoding.isEmpty())
-	{
-		QTextCodec* codec = QTextCodec::codecForName(encoding);
-		QByteArray bytes((const char*) name.string, name.string_len);
-		string = codec->toUnicode(bytes);
-	}
-
+	if (encoding.isEmpty())
+		return QString();
+
+	QTextCodec* codec = QTextCodec::codecForName(encoding);
+	if (!codec)
+		return QString();
+
+	QByteArray bytes((const char*) name.string, name.string_len);
+	if (name.encoding_id == TT_MS_ID_GB2312 && bytes.startsWith('\0'))
+	{
+		// 16 bytes chars appears to be used as transport type for 8 bytes values.
+		// We have to fix this so that Qt GB18030 codec process strings correctly
+		for (int i = 0; i < (int) name.string_len / 2; ++i)
+			bytes[i] = bytes[2 * i + 1];
+		bytes.resize(name.string_len / 2);
+	}
+
+	QString string = codec->toUnicode(bytes);
 	return string;
 }
 
@@ -442,7 +455,7 @@
 	if (!names.isEmpty())
 	{
 		std::sort(names.begin(), names.end(), nameComp);
-		foreach (const FT_SfntName& name, names)
+		for (const FT_SfntName& name : qAsConst(names))
 		{
 			QString string(decodeNameRecord(name));
 			if (!string.isEmpty())
@@ -665,6 +678,15 @@
 		addRejectedFont(filename, QObject::tr("Font is broken: \"%1\"").arg(getFtError(error)));
 		if (m_showFontInfo)
 			sDebug(QObject::tr("Font %1 is broken, discarding it. Error message: \"%2\"").arg(filename, getFtError(error)));
+		return true;
+	}
+	if (face->family_name == nullptr)
+	{
+		addRejectedFont(filename, QObject::tr("Failed to load font: font family unspecified"));
+		if (m_showFontInfo)
+			sDebug(QObject::tr("Failed to load font %1 - font family unspecified").arg(filename));
+		FT_Done_Face(face);
+		m_checkedFonts.insert(filename, foCache);
 		return true;
 	}
 	getFontFormat(face, format, type);
@@ -783,11 +805,12 @@
 		QString fam(getFamilyName(face));
 		QStringList features(getFontFeatures(face));
 		QString sty(face->style_name);
-		if (sty == "Regular")
+		if ((sty == "Regular" && face->style_flags != 0) || sty.isEmpty())
 		{
 			switch (face->style_flags)
 			{
 				case 0:
+					sty = "Regular";
 					break;
 				case 1:
 					sty = "Italic";
@@ -802,52 +825,53 @@
 					break;
 			}
 		}
-		QString ts(fam + " " + sty);
-		QString alt("");
+		QString fullName(fam);
+		if (!sty.isEmpty())
+			fullName += " " + sty;
 		const char* psName = FT_Get_Postscript_Name(face);
 		QString qpsName;
 		if (psName)
 			qpsName = QString(psName);
 		else
-			qpsName = ts;
+			qpsName = fullName;
 		ScFace t;
-		if (contains(ts))
-		{
-			t = (*this)[ts];
+		if (contains(fullName))
+		{
+			t = (*this)[fullName];
 			if (t.psName() != qpsName)
 			{
-				alt = " ("+qpsName+")";
-				ts += alt;
+				QString alt = " (" + qpsName + ")";
+				fullName += alt;
 				sty += alt;
 			}
 		}
-		t = (*this)[ts];
+		t = (*this)[fullName];
 		if (t.isNone())
 		{
 			switch (format) 
 			{
 				case ScFace::PFA:
-					t = ScFace(new ScFace_PFA(fam, sty, "", ts, qpsName, filename, faceIndex, features));
+					t = ScFace(new ScFace_PFA(fam, sty, "", fullName, qpsName, filename, faceIndex, features));
 					t.subset(Subset);
 					break;
 				case ScFace::PFB:
-					t = ScFace(new ScFace_PFB(fam, sty, "", ts, qpsName, filename, faceIndex, features));
+					t = ScFace(new ScFace_PFB(fam, sty, "", fullName, qpsName, filename, faceIndex, features));
 					t.subset(Subset);
 					break;
 				case ScFace::SFNT:
-					t = ScFace(new ScFace_ttf(fam, sty, "", ts, qpsName, filename, faceIndex, features));
+					t = ScFace(new ScFace_ttf(fam, sty, "", fullName, qpsName, filename, faceIndex, features));
 					getSFontType(face, t.m_m->typeCode);
 					t.subset(Subset);
 					break;
 				case ScFace::TTCF:
-					t = ScFace(new ScFace_ttf(fam, sty, "", ts, qpsName, filename, faceIndex, features));
+					t = ScFace(new ScFace_ttf(fam, sty, "", fullName, qpsName, filename, faceIndex, features));
 					t.m_m->formatCode = ScFace::TTCF;
 					t.m_m->typeCode = ScFace::TTF;
 					getSFontType(face, t.m_m->typeCode);
 					t.subset(Subset);
 					break;
 				case ScFace::TYPE42:
-					t = ScFace(new ScFace_ttf(fam, sty, "", ts, qpsName, filename, faceIndex, features));
+					t = ScFace(new ScFace_ttf(fam, sty, "", fullName, qpsName, filename, faceIndex, features));
 					getSFontType(face, t.m_m->typeCode);
 					t.subset(Subset);
 					break;
@@ -855,7 +879,7 @@
 				/* catching any types not handled above to silence compiler */
 					break;
 			}
-			insert(ts,t);
+			insert(fullName, t);
 			t.m_m->hasGlyphNames = HasNames;
 			t.embedPs(true);
 			t.usable(true);
@@ -871,7 +895,7 @@
 //debug
 			QByteArray bb;
 			t->rawData(bb);
-			QFile dump(QString("/tmp/fonts/%1-%2").arg(ts, psName));
+			QFile dump(QString("/tmp/fonts/%1-%2").arg(fullName, psName));
 			dump.open(IO_WriteOnly);
 			QDataStream os(&dump);
 			os.writeRawBytes(bb.data(), bb.size());
@@ -881,7 +905,7 @@
 		else 
 		{
 			if (m_showFontInfo)
-				sDebug(QObject::tr("Font %1(%2) is duplicate of %3").arg(filename).arg(faceIndex+1).arg(t.fontPath()));
+				sDebug(QObject::tr("Font %1(%2) is duplicate of %3").arg(filename).arg(faceIndex + 1).arg(t.fontPath()));
 			// this is needed since eg. AppleSymbols will happily return a face for *any* face_index
 			if (faceIndex > 0) {
 				break;




More information about the scribus-commit mailing list