r19396 by jghali - Allow Type 3 subsetting and embedding of TrueType fonts without Postscript glyph name table.

scribus-commit scribus-commit at lists.scribus.net
Sat Aug 2 15:54:47 UTC 2014


Author: jghali
Date: Sat Aug  2 15:54:47 2014
New Revision: 19396

URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=19396
Log:
Allow Type 3 subsetting and embedding of TrueType fonts without Postscript glyph name table.

Due do unreliable PostScript glyph name tables in TT fonts, we were previously using the 'uniXXXX' glyph name convention to replace the font provided names. This was limited to font providing the 'post' table tho. This behavior is now extended to TT font without glyph name table, hence allowing Type 3 subsetting and embedding of those fonts (vs only outlining previously).

Modified:
    trunk/Scribus/scribus/fonts/ftface.cpp
    trunk/Scribus/scribus/fonts/ftface.h
    trunk/Scribus/scribus/fonts/scface.cpp
    trunk/Scribus/scribus/fonts/scface.h
    trunk/Scribus/scribus/fonts/scface_ttf.cpp
    trunk/Scribus/scribus/fonts/scface_ttf.h
    trunk/Scribus/scribus/fonts/scfontmetrics.cpp
    trunk/Scribus/scribus/scfonts.cpp

Modified: trunk/Scribus/scribus/fonts/ftface.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=19396&path=/trunk/Scribus/scribus/fonts/ftface.cpp
==============================================================================
--- trunk/Scribus/scribus/fonts/ftface.cpp (original)
+++ trunk/Scribus/scribus/fonts/ftface.cpp Sat Aug  2 15:54:47 2014
@@ -305,10 +305,85 @@
 	return error;
 }
 
+QString FtFace::adobeGlyphName(FT_ULong charcode) 
+{
+	static const char HEX[] = "0123456789ABCDEF";
+	QString result;
+	if (charcode < 0x10000) {
+		result = QString("uni") + HEX[charcode>>12 & 0xF] 
+		                        + HEX[charcode>> 8 & 0xF] 
+		                        + HEX[charcode>> 4 & 0xF] 
+		                        + HEX[charcode     & 0xF];
+	}
+	else  {
+		result = QString("u");
+		for (int i= 28; i >= 0; i-=4) {
+			if (charcode & (0xF << i))
+				result += HEX[charcode >> i & 0xF];
+		}
+	}
+	return result;
+}
 
 bool FtFace::glyphNames(QMap<uint, std::pair<QChar, QString> >& GList) const
 {
-	return GlyphNames(*this, GList);
+	char buf[50];
+	FT_ULong  charcode;
+	FT_UInt gindex = 0;
+
+	FT_Face face = ftFace();
+	if (!face)
+		return false;
+	
+	const bool hasPSNames = FT_HAS_GLYPH_NAMES(face);
+	
+//	qDebug() << "reading metrics for" << face->family_name << face->style_name;
+	charcode = FT_Get_First_Char(face, &gindex );
+	while (gindex != 0)
+	{
+		bool notfound = true;
+		if (hasPSNames)
+			notfound = FT_Get_Glyph_Name(face, gindex, &buf, 50);
+
+		// just in case FT gives empty string or ".notdef"
+		// no valid glyphname except ".notdef" starts with '.'		
+//		qDebug() << "\t" << gindex << " '" << charcode << "' --> '" << (notfound? "notfound" : buf) << "'";
+		if (notfound || buf[0] == '\0' || buf[0] == '.')
+			GList.insert(gindex, std::make_pair(QChar(static_cast<uint>(charcode)), adobeGlyphName(charcode)));
+		else
+			GList.insert(gindex, std::make_pair(QChar(static_cast<uint>(charcode)), QString(reinterpret_cast<char*>(buf))));
+
+		charcode = FT_Get_Next_Char(face, charcode, &gindex );
+	}
+
+	if (!hasPSNames)
+		return true;
+
+	// Let's see if we can find some more...
+	int maxSlot1 = face->num_glyphs;
+	for (int gindex = 1; gindex < maxSlot1; ++gindex)
+	{
+		if (GList.contains(gindex))
+			continue;
+		if (FT_Get_Glyph_Name(face, gindex, &buf, 50))
+			continue;
+		QString glyphname(reinterpret_cast<char*>(buf));
+
+		charcode = 0;
+		QMap<uint,std::pair<QChar,QString> >::Iterator gli;
+		for (gli = GList.begin(); gli != GList.end(); ++gli)
+		{
+			if (glyphname == gli.value().second)
+			{
+				charcode = gli.value().first.unicode();
+				break;
+			}
+		}
+//		qDebug() << "\tmore: " << gindex << " '" << charcode << "' --> '" << buf << "'";
+		GList.insert(gindex, std::make_pair(QChar(static_cast<uint>(charcode)), glyphname));
+	}
+
+	return true;
 }
 
 

Modified: trunk/Scribus/scribus/fonts/ftface.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=19396&path=/trunk/Scribus/scribus/fonts/ftface.h
==============================================================================
--- trunk/Scribus/scribus/fonts/ftface.h (original)
+++ trunk/Scribus/scribus/fonts/ftface.h Sat Aug  2 15:54:47 2014
@@ -85,7 +85,10 @@
 //	GlyphMetrics glyphBBox (uint gl,               qreal sz) const;
 
 	void RawData   (QByteArray & bb)            const;
-	bool glyphNames(QMap<uint, std::pair<QChar, QString> >& GList) const;
+
+	static QString adobeGlyphName(FT_ULong charcode);
+	virtual bool glyphNames(QMap<uint, std::pair<QChar, QString> >& GList) const;
+
 	void load      ()                           const;
 	void unload    ()                           const;
 	void loadGlyph (uint ch)                    const;

Modified: trunk/Scribus/scribus/fonts/scface.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=19396&path=/trunk/Scribus/scribus/fonts/scface.cpp
==============================================================================
--- trunk/Scribus/scribus/fonts/scface.cpp (original)
+++ trunk/Scribus/scribus/fonts/scface.cpp Sat Aug  2 15:54:47 2014
@@ -24,7 +24,7 @@
 	subset(false),
 	isStroked(false),
 	isFixedPitch(false),
-	hasNames(false),
+	hasGlyphNames(false),
 	maxGlyph(0),
 	cachedStatus(ScFace::UNKNOWN)
 {

Modified: trunk/Scribus/scribus/fonts/scface.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=19396&path=/trunk/Scribus/scribus/fonts/scface.h
==============================================================================
--- trunk/Scribus/scribus/fonts/scface.h (original)
+++ trunk/Scribus/scribus/fonts/scface.h Sat Aug  2 15:54:47 2014
@@ -121,7 +121,7 @@
 
 		bool isStroked;
 		bool isFixedPitch;
-		bool hasNames;
+		bool hasGlyphNames;
 		uint maxGlyph;
 
 		ScFaceData();
@@ -179,6 +179,8 @@
 		virtual GlyphMetrics glyphBBox(uint gl, qreal sz) const;
 		virtual bool EmbedFont(QString &/*str*/)       const { return false; }
 		virtual void RawData(QByteArray & /*bb*/)      const {}
+
+		virtual bool hasNames() const { return hasGlyphNames; }
 		virtual bool glyphNames(QMap<uint, std::pair<QChar, QString> >& gList) const;
 
 		// these use the cache:
@@ -287,7 +289,7 @@
 	void subset(bool flag)   { m->subset = flag; }
 
 	/// deprecated? tells if the face has PS names
-	bool hasNames()    const { return m->hasNames; }
+	bool hasNames()    const { return m->hasNames(); }
 
 	/// tells if this font is an outline font
 	bool isStroked()   const { return m->isStroked; }

Modified: trunk/Scribus/scribus/fonts/scface_ttf.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=19396&path=/trunk/Scribus/scribus/fonts/scface_ttf.cpp
==============================================================================
--- trunk/Scribus/scribus/fonts/scface_ttf.cpp (original)
+++ trunk/Scribus/scribus/fonts/scface_ttf.cpp Sat Aug  2 15:54:47 2014
@@ -528,6 +528,52 @@
 	if ( kernFeature->isValid() )
 		return kernFeature->getPairValue ( gl1,gl2 ) / m_uniEM * sz;
 	return FtFace::glyphKerning ( gl1, gl2, sz );
+}
+
+bool ScFace_ttf::hasNames() const
+{
+	FT_Face face = ftFace();
+	if (!face)
+		return false;
+
+	// The glyph name table embedded in Truetype fonts is not reliable.
+	// For those fonts we consequently use Adobe Glyph names whenever possible.
+	const bool avoidFntNames = (formatCode != ScFace::TYPE42 && typeCode == ScFace::TTF) &&
+	                           (face->charmap && face->charmap->encoding == FT_ENCODING_UNICODE);
+	if (avoidFntNames)
+		return true; // We use Adobe 'uniXXXX' names in such case
+
+	return FtFace::hasNames();
+}
+
+bool ScFace_ttf::glyphNames(QMap<uint, std::pair<QChar, QString> >& GList) const
+{
+	char buf[50];
+	FT_ULong  charcode;
+	FT_UInt gindex = 0;
+
+	FT_Face face = ftFace();
+	if (!face)
+		return false;
+	
+	// The glyph name table embedded in Truetype fonts is not reliable.
+	// For those fonts we consequently use Adobe Glyph names whenever possible.
+	const bool avoidFntNames = (formatCode != ScFace::TYPE42 && typeCode == ScFace::TTF) &&
+	                           (face->charmap && face->charmap->encoding == FT_ENCODING_UNICODE);
+	if (!avoidFntNames)
+		return FtFace::glyphNames(GList);
+
+	const bool hasPSNames = FT_HAS_GLYPH_NAMES(face);
+	
+//	qDebug() << "reading metrics for" << face->family_name << face->style_name;
+	charcode = FT_Get_First_Char(face, &gindex);
+	while (gindex != 0)
+	{
+		GList.insert(gindex, std::make_pair(QChar(static_cast<uint>(charcode)), adobeGlyphName(charcode)));
+		charcode = FT_Get_Next_Char(face, charcode, &gindex );
+	}
+
+	return true;
 }
 
 void ScFace_ttf::RawData(QByteArray & bb) const {

Modified: trunk/Scribus/scribus/fonts/scface_ttf.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=19396&path=/trunk/Scribus/scribus/fonts/scface_ttf.h
==============================================================================
--- trunk/Scribus/scribus/fonts/scface_ttf.h (original)
+++ trunk/Scribus/scribus/fonts/scface_ttf.h Sat Aug  2 15:54:47 2014
@@ -97,7 +97,9 @@
 	void RawData(QByteArray & bb) const;
 
 	qreal glyphKerning ( uint gl1, uint gl2, qreal sz ) const;
-
+	
+	virtual bool glyphNames(QMap<uint, std::pair<QChar, QString> >& GList) const;
+	virtual bool hasNames() const;
 	virtual bool isSymbolic() const;
 
 private:

Modified: trunk/Scribus/scribus/fonts/scfontmetrics.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=19396&path=/trunk/Scribus/scribus/fonts/scfontmetrics.cpp
==============================================================================
--- trunk/Scribus/scribus/fonts/scfontmetrics.cpp (original)
+++ trunk/Scribus/scribus/fonts/scfontmetrics.cpp Sat Aug  2 15:54:47 2014
@@ -368,8 +368,6 @@
 		if (FT_Get_Glyph_Name(face, gindex, &buf, 50))
 			continue;
 		QString glyphname(reinterpret_cast<char*>(buf));
-		if (avoidFntNames && buf[0] != '.' && buf[0] != '\0')
-			glyphname = adobeGlyphName(charcode);
 
 		charcode = 0;
 		QMap<uint,std::pair<QChar,QString> >::Iterator gli;
@@ -382,6 +380,8 @@
 			}
 		}
 //		qDebug() << "\tmore: " << gindex << " '" << charcode << "' --> '" << buf << "'";
+		if (avoidFntNames && buf[0] != '.' && buf[0] != '\0')
+			glyphname = adobeGlyphName(charcode);
 		GList.insert(gindex, std::make_pair(QChar(static_cast<uint>(charcode)), glyphname));
 	}
 

Modified: trunk/Scribus/scribus/scfonts.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=19396&path=/trunk/Scribus/scribus/scfonts.cpp
==============================================================================
--- trunk/Scribus/scribus/scfonts.cpp (original)
+++ trunk/Scribus/scribus/scfonts.cpp Sat Aug  2 15:54:47 2014
@@ -432,7 +432,7 @@
 			/* catching any types not handled above to silence compiler */
 				break;
 		}
-		t.m->hasNames = HasNames;
+		t.m->hasGlyphNames = HasNames;
 		t.embedPs(true);
 		t.usable(true);
 		t.m->status = ScFace::UNKNOWN;
@@ -661,7 +661,7 @@
 					break;
 			}
 			insert(ts,t);
-			t.m->hasNames = HasNames;
+			t.m->hasGlyphNames = HasNames;
 			t.embedPs(true);
 			t.usable(true);
 			t.m->status = ScFace::UNKNOWN;




More information about the scribus-commit mailing list