View Issue Details

IDProjectCategoryView StatusLast Update
0001816ScribusFontspublic2005-06-01 17:42
Reporteravox Assigned Tocbradney  
PrioritynormalSeverityfeatureReproducibilityalways
Status closedResolutionfixed 
Product Version1.3 
Fixed in Version1.3.0cvs 
Summary0001816: Fonts are only recognized in 'pfa', 'pfb', 'ttf' and 'otf' files.
DescriptionFreetype has the ability to open most font files including Mac resource forks, *.dfont files and TrueType collections (*.ttc).
Scribus should:
* recognize any font which freetype can open
* recognize all fonts in a collection
* identify font types by content instead of by extension
* look for fonts in the std Mac directories (Library/Fonts etc.)

The following patch provides this.
TagsNo tags attached.
Patch

Relationships

related to 0002015 closedavox This issue lists all known regressions of the Aqua port compared with the 13 Linux version 

Activities

avox

2005-04-06 14:44

updater   ~0004097

Changes:

* extracts TTF from TTC files for embedding
* uses Adobe Glyphnames if FT says PS Glyphnames isn't reliable

Needs additional file scribus/glyphnames.txt.q
which unfortunately produces lots of warnings ATM

cbradney

2005-04-06 18:40

administrator   ~0004099

Why does it need this text file?

avox

2005-04-06 19:05

updater   ~0004100

Last edited: 2005-04-06 19:21

glyphnames.txt.q is #included in util.cpp.
Without it the array of glyphnames will be empty and
PS and PDF export will not work for some TTF/OTF fonts
(symptom: all chars have undefined glyphs)

It's the file "glyphlist.txt" from Adobe with added quotes and commas.
See http://partners.adobe.com/public/developer/en/opentype/glyphlist.txt

cbradney

2005-04-06 20:01

administrator   ~0004102

We need confirmation on licensing of the glyph list in its current format, otherwise we need something from unicode.org I assume.

avox

2005-04-06 23:58

updater   ~0004105

Ok, last patch doesn't need glyphnames any more but finds glyphnames like this:

1. if FT_HAS_GLYPH_NAMES(face) is true, use FT_Get_Glyph_Name()
2. Otherwise, OR if FT returned ".notdef", OR if FT returned an empty name:
3a. if unicode is 16bit, use "uni1234" name
3b. if unicode is more than 16 bit, use "u12345" name

Now works with MS Mincho, MS Gothic and Papyrus in one document

avox

2005-05-26 20:15

updater   ~0004793

Updated the patch with a version against current CVS

cbradney

2005-05-27 20:56

administrator   ~0004813

Uploaded new version of morefonts4.diff with fix for #endif in the wrong place.

2005-05-27 23:20

 

morefonts5.diff (68,950 bytes)   
Index: scribus/charselect.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/Attic/charselect.cpp,v
retrieving revision 1.1.2.17
diff -u -p -r1.1.2.17 charselect.cpp
--- scribus/charselect.cpp	25 May 2005 10:54:20 -0000	1.1.2.17
+++ scribus/charselect.cpp	26 May 2005 21:50:33 -0000
@@ -30,7 +30,7 @@
 #include FT_GLYPH_H
 
 extern QPixmap loadIcon(QString nam);
-extern QPixmap FontSample(QString da, int s, QString ts, QColor back, bool force = false);
+extern QPixmap FontSample(Foi *font, int s, QString ts, QColor back, bool force = false);
 extern int setBestEncoding(FT_Face face);
 
 #ifdef QT_MAC
@@ -658,7 +660,7 @@ void CharSelect::newChar(uint r, uint c)
 	if ((r*16+c) < maxCount)
 	{
 		chToIns += QChar(characters[r*16+c]);
-		sample->setPixmap(FontSample((*ap->doc->AllFonts)[fontInUse]->Datei, 28, chToIns, paletteBackgroundColor(), true));
+		sample->setPixmap(FontSample((*ap->doc->AllFonts)[fontInUse], 28, chToIns, paletteBackgroundColor(), true));
 		insertButton->setEnabled(true);
 	}
 }
@@ -673,7 +675,7 @@ void CharSelect::delChar()
 		return;
 	}
 	chToIns.truncate(chToIns.length() - 1);
-	sample->setPixmap(FontSample((*ap->doc->AllFonts)[fontInUse]->Datei, 28, chToIns, paletteBackgroundColor(), true));
+	sample->setPixmap(FontSample((*ap->doc->AllFonts)[fontInUse], 28, chToIns, paletteBackgroundColor(), true));
 	insertButton->setEnabled(true);
 }
 
Index: scribus/fontprefs.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/fontprefs.cpp,v
retrieving revision 1.24.2.8
diff -u -p -r1.24.2.8 fontprefs.cpp
--- scribus/fontprefs.cpp	10 Apr 2005 23:39:44 -0000	1.24.2.8
+++ scribus/fontprefs.cpp	26 May 2005 21:50:35 -0000
@@ -72,9 +72,8 @@ FontPrefs::FontPrefs( QWidget* parent,  
 			foS.FlagPS = false;
 			row->setPixmap(2, empty);
 		}
-		QFileInfo fi = QFileInfo(it.current()->Datei);
-		QString ext = fi.extension(false).lower();
-		if (ext == "otf")
+		Foi::FontType type = it.current()->typeCode;
+		if (type == Foi::OTF)
 			foS.FlagOTF = true;
 		else
 			foS.FlagOTF = false;
@@ -88,16 +87,16 @@ FontPrefs::FontPrefs( QWidget* parent,  
 			foS.FlagSub = false;
 			row->setPixmap(3, empty);
 		}
-		if ((ext == "pfa") || (ext == "pfb"))
+		if (type == Foi::TYPE1)
 			row->setPixmap(0, psFont);
 		else
 		{
-			if (ext == "ttf")
+			if (type == Foi::TTF)
 				row->setPixmap(0, ttfFont);
-			if (ext == "otf")
+			if (type == Foi::OTF)
 				row->setPixmap(0, otfFont);
 		}
-		row->setText(4, it.current()->Datei);
+		row->setText(4, it.current()->fontPath());
 		fontFlags.insert(it.currentKey(), foS);
 	}
 	fontList->setSorting(0);
@@ -404,9 +403,8 @@ void FontPrefs::RebuildDialog()
 			foS.FlagPS = false;
 			row->setPixmap(2, empty);
 		}
-		QFileInfo fi = QFileInfo(it.current()->Datei);
-		QString ext = fi.extension(false).lower();
-		if (ext == "otf")
+		Foi::FontType type = it.current()->typeCode;
+		if (type == Foi::OTF)
 			foS.FlagOTF = true;
 		else
 			foS.FlagOTF = false;
@@ -420,16 +418,16 @@ void FontPrefs::RebuildDialog()
 			foS.FlagSub = false;
 			row->setPixmap(3, empty);
 		}
-		if ((ext == "pfa") || (ext == "pfb"))
+		if (type == Foi::TYPE1)
 			row->setPixmap(0, psFont);
 		else
 		{
-			if (ext == "ttf")
+			if (type == Foi::TTF)
 				row->setPixmap(0, ttfFont);
-			if (ext == "otf")
+			if (type == Foi::OTF)
 				row->setPixmap(0, otfFont);
 		}
-		row->setText(4, it.current()->Datei);
+		row->setText(4, it.current()->fontPath());
 		fontFlags.insert(it.currentKey(), foS);
 	}
 	fontList->setSorting(0);
Index: scribus/scfonts.h
===================================================================
RCS file: /cvs/Scribus/scribus/scfonts.h,v
retrieving revision 1.4.2.5
diff -u -p -r1.4.2.5 scfonts.h
--- scribus/scfonts.h	11 May 2005 23:26:59 -0000	1.4.2.5
+++ scribus/scfonts.h	26 May 2005 21:50:41 -0000
@@ -42,15 +42,25 @@
 class Foi
 {
 	public:
+		enum FontType { TYPE0, TYPE1, TYPE3, TTF, CFF, OTF, UNKNOWN_TYPE };
+		enum FontFormat { PFA, PFB, TYPE2, TYPE42,
+		// handled by freetype:	PFB_MAC, DFONT, HQX, MACBIN,
+		                  SFNT, TTCF, UNKNOWN_FORMAT };
+		
 		Foi(QString scname, QString path, bool embedps);
 		virtual ~Foi() {};
 		virtual QString RealName();
 		virtual bool EmbedFont(QString &str);
+		virtual void RawData(QByteArray & bb);
 		virtual bool ReadMetrics();
 		virtual bool GlNames(QMap<uint, QString> *GList);
 //		virtual void FontBez();
 		QString SCName;
+//private:
 		QString Datei;
+		int     faceIndex;
+public:
+		QString fontPath() { return faceIndex >= 0 ? QString("%1(%2)").arg(Datei).arg(faceIndex+1) : Datei; }
 		QString cached_RealName;
 		QString Family;
 		QString Effect;
@@ -85,7 +95,8 @@ class Foi
 		double underline_pos;
 		double strikeout_pos;
 		double strokeWidth;
-		int typeCode;
+		Foi::FontType typeCode;
+		Foi::FontFormat formatCode;
 //		QPixmap Appearance;
 };
 
@@ -117,9 +128,11 @@ class SCFonts : public QDict<Foi>
 #ifdef HAVE_FONTCONFIG
 		void AddFontconfigFonts();
 #else
+#ifndef QT_MAC
 		void AddXFontServerPath();
 		void AddXFontPath();
 #endif
+#endif
 		QStrList FontPath;
 		QString ExtraPath;
 };
Index: scribus/scfonts_ttf.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/scfonts_ttf.cpp,v
retrieving revision 1.12.2.8
diff -u -p -r1.12.2.8 scfonts_ttf.cpp
--- scribus/scfonts_ttf.cpp	13 May 2005 21:42:32 -0000	1.12.2.8
+++ scribus/scfonts_ttf.cpp	26 May 2005 21:50:41 -0000
@@ -19,6 +19,8 @@
 #include FT_FREETYPE_H
 #include FT_OUTLINE_H
 #include FT_GLYPH_H
+#include FT_INTERNAL_STREAM_H
+
 extern FPointArray traceChar(FT_Face face, uint chr, int chs, double *x, double *y, bool *err);
 extern int setBestEncoding(FT_Face face);
 
@@ -56,14 +58,14 @@ bool Foi_ttf::ReadMetrics()
 	if (error)
 	{
 		UseFont = false;
-		qDebug(QObject::tr("Font %1 is broken, discarding it").arg(Datei));
+		qDebug(QObject::tr("Font %1 is broken (FreeType), discarding it").arg(Datei));
 		return false;
 	}
-	error = FT_New_Face( library, Datei, 0, &face );
+	error = FT_New_Face( library, Datei, faceIndex, &face );
 	if (error)
 	{
 		UseFont = false;
-		qDebug(QObject::tr("Font %1 is broken, discarding it").arg(Datei));
+		qDebug(QObject::tr("Font %1 is broken (no Face), discarding it").arg(Datei));
 		return false;
 	}
 	uniEM = static_cast<double>(face->units_per_EM);
@@ -84,15 +86,18 @@ bool Foi_ttf::ReadMetrics()
 	setBestEncoding(face);
 	gindex = 0;
 	charcode = FT_Get_First_Char( face, &gindex );
+	int invalidGlyphs = 0;
+	int goodGlyphs = 0;
 	while ( gindex != 0 )
 	{
 		error = FT_Load_Glyph( face, gindex, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP );
 		if (error)
 		{
-			UseFont = false;
-			qDebug(QObject::tr("Font %1 is broken, discarding it").arg(Datei));
+			++invalidGlyphs;
+			qDebug(QObject::tr("Font %1  has invalid glyph %2 (charcode %3), discarding it").arg(Datei).arg(gindex).arg(charcode));
 			break;
 		}
+		++goodGlyphs;
 		double ww = face->glyph->metrics.horiAdvance / uniEM;
 		if (face->glyph->format == FT_GLYPH_FORMAT_PLOTTER)
 			isStroked = true;
@@ -114,17 +119,116 @@ bool Foi_ttf::ReadMetrics()
 		glyName = newName;
 		charcode = FT_Get_Next_Char( face, charcode, &gindex );
 	}
+	UseFont = goodGlyphs > invalidGlyphs;
 	FT_Done_FreeType( library );
 	HasMetrics=UseFont;
 	metricsread=UseFont;
 	return(HasMetrics);
 }
 
+
+namespace {
+uint word(QByteArray const & bb, uint pos) 
+{
+	unsigned char * pp = reinterpret_cast<unsigned char*>(bb.data()) + pos;
+	return pp[0] << 24 | pp[1] << 16 | pp[2] << 8 | pp[3];
+}
+uint word16(QByteArray const & bb, uint pos) 
+{
+	unsigned char * pp = reinterpret_cast<unsigned char*>(bb.data()) + pos;
+	return pp[0] << 8 | pp[1];
+}
+QString tag(QByteArray const & bb, uint pos)
+{
+	char buf[5] = "1234";
+	buf[0] = bb.data()[pos];
+	buf[1] = bb.data()[pos+1];
+	buf[2] = bb.data()[pos+2];
+	buf[3] = bb.data()[pos+3];
+	return buf;
+}
+bool copy(QByteArray & dst, uint to, QByteArray & src, uint from, uint len) 
+{
+	if (!dst.data())
+		return false;
+	if (!src.data())
+		return false;
+	if (to + len > dst.size())
+		return false;
+	if (from + len > src.size())
+		return false;
+	
+	memcpy(dst.data() + to, src.data() + from, len);
+	return true;
+}
+} //namespace
+
+
+void Foi_ttf::RawData(QByteArray & bb) {
+	if (formatCode == TTCF) {
+		QByteArray coll;
+		Foi::RawData(coll);
+		// access table for faceIndex
+		if (faceIndex >= word(coll, 8))
+		{
+			bb.resize(0);
+			return;
+		}
+		static const uint OFFSET_TABLE_LEN = 12;
+		static const uint   TDIR_ENTRY_LEN = 16;
+		uint faceOffset = word(coll, 12 + 4 * faceIndex);
+		uint nTables    = word16(coll, faceOffset + 4);
+		qDebug(QObject::tr("extracting face %1 from font %2 (offset=%3, nTables=%4)").arg(faceIndex).arg(Datei).arg(faceOffset).arg(nTables));
+		uint headerLength = OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * nTables;   
+		uint tableLengths = 0;
+		// sum table lengths incl padding
+		for (uint i=0; i < nTables; ++i)
+		{
+			tableLengths += word(coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12);
+			tableLengths = (tableLengths+3) & ~3;
+		}
+		bb.resize(headerLength + tableLengths);
+		if (! bb.data())
+			return;
+		// write header
+		qDebug(QObject::tr("memcpy header: %1 %2 %3").arg(0).arg(faceOffset).arg(headerLength));
+		if (!copy(bb, 0, coll, faceOffset, headerLength))
+			return;
+
+		uint pos = headerLength;
+		for (uint i=0; i < nTables; ++i)
+		{
+			uint tableSize  = word(coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12);
+			uint tableStart = word(coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 8);
+			qDebug(QObject::tr("table '%1'").arg(tag(coll, tableStart)));
+			qDebug(QObject::tr("memcpy table: %1 %2 %3").arg(pos).arg(tableStart).arg(tableSize));
+			if (!copy(bb, pos, coll, tableStart, tableSize)) break;
+			// write new offset to table entry
+			qDebug(QObject::tr("memcpy offset: %1 %2 %3").arg(OFFSET_TABLE_LEN + TDIR_ENTRY_LEN*i + 8).arg(pos).arg(4));
+			memcpy(bb.data() + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 8, &pos, 4);
+			pos += tableSize;
+			// pad
+			while (pos & 3 != 0)
+				bb.data()[pos++] = '\0';
+		}
+	}	
+	else if (formatCode == TYPE42) {
+		Foi::RawData(bb);
+	}
+	else {
+		Foi::RawData(bb);
+	}
+}
+
 bool Foi_ttf::EmbedFont(QString &str)
 {
-	QFile file(Datei);
-	if(!(file.open(IO_ReadOnly)))
-		return(false);
+	if (formatCode == Foi::TYPE42) {
+		//easy:
+		QByteArray bb;
+		Foi::RawData(bb);
+		str += bb;
+		return true;
+	}
 	QString tmp4;
 	QString tmp2 = "";
 	QString tmp3 = "";
@@ -135,7 +239,12 @@ bool Foi_ttf::EmbedFont(QString &str)
 	FT_ULong  charcode;
 	FT_UInt   gindex;
 	FT_Init_FreeType(&library);
-	FT_New_Face(library, file.name(), 0, &face);
+	FT_New_Face(library, Datei, faceIndex, &face);
+	const FT_Stream fts = face->stream;
+	if (FT_Stream_Seek(fts, 0L)) {
+		FT_Done_FreeType( library );
+		return(false);
+	}
 	str+="%!PS-TrueTypeFont\n";
 	str+="11 dict begin\n";
 	str+="/FontName /" + RealName() + " def\n";
@@ -146,21 +255,22 @@ bool Foi_ttf::EmbedFont(QString &str)
 	str+="/FontInfo 8 dict dup begin\n";
 	str+="/FamilyName (" + RealName() + ") def\n";
 	str+="end readonly def\n";
-	char *tmp = new char[65535];
+	unsigned char *tmp = new unsigned char[65535];
 	int length;
 	char linebuf[80];
 	str += "/sfnts [";
-	file.at(0);
 	int poso=0;
-	do
-		{
+	do {
 		int posi=0;
-		length=file.readBlock(tmp,65534);
-		if(length)
-			{
+		length= fts->size - fts->pos;
+		if (length > 65534) {
+			length = 65534;
+		}
+		if (!FT_Stream_Read(fts,tmp,length))
+		{
 			str+="\n<\n";
 			for (int j = 0; j < length; j++)
-				{
+			{
 				unsigned char u=tmp[posi];
 				linebuf[poso]=((u >> 4) & 15) + '0';
 				if(u>0x9f) linebuf[poso]+='a'-':';
@@ -170,19 +280,24 @@ bool Foi_ttf::EmbedFont(QString &str)
 				++posi;
 				++poso;
 				if (poso > 70)
-					{
+				{
 					linebuf[poso++]='\n';
 					linebuf[poso++]=0;
 					str += linebuf;
 					poso = 0;
-					}
 				}
+			}
 			linebuf[poso++]=0;
 			str += linebuf;
 			poso = 0;
 			str += "00\n>";
-			}
 		}
+		else {
+			qDebug(QObject::tr("Font %1 is broken (read stream), no embedding").arg(Datei).arg(gindex));
+			str += "\n] def\n";
+			return false;
+		}
+	}
 	while (length==65534);
 	str += "\n] def\n";
 	delete tmp;
@@ -201,7 +316,6 @@ bool Foi_ttf::EmbedFont(QString &str)
 	str += "/CharStrings " + tmp4 + " dict dup begin\n"+tmp2;
 	str += "end readonly def\n";
 	str += "FontName currentdict end definefont pop\n";
-	file.close();
 	return(true);
 }
 
Index: scribus/scfonts_ttf.h
===================================================================
RCS file: /cvs/Scribus/scribus/scfonts_ttf.h,v
retrieving revision 1.2
diff -u -p -r1.2 scfonts_ttf.h
--- scribus/scfonts_ttf.h	1 Oct 2003 20:39:09 -0000	1.2
+++ scribus/scfonts_ttf.h	26 May 2005 21:50:41 -0000
@@ -16,10 +16,12 @@ class Foi_ttf : public Foi
 		Foi(scname,path,embedps), metricsread(false)
 		{
 			HasMetrics=true;
+			formatCode = SFNT;
 		}
 		QString RealName();
 		bool ReadMetrics();
 		virtual bool EmbedFont(QString &str);
+		virtual void RawData(QByteArray & bb);
 	private:
 		bool metricsread;
 };
Index: scribus/scpreview.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/scpreview.cpp,v
retrieving revision 1.17.2.26
diff -u -p -r1.17.2.26 scpreview.cpp
--- scribus/scpreview.cpp	22 May 2005 21:16:03 -0000	1.17.2.26
+++ scribus/scpreview.cpp	26 May 2005 21:50:45 -0000
@@ -124,7 +124,7 @@ QPixmap ScPreview::createPreview(QString
 			if (!DoFonts2.contains(tmpf))
 			{
 				FT_Face      face;
-				error = FT_New_Face( library, Prefs->AvailFonts[tmpf]->Datei, 0, &face );
+				error = FT_New_Face( library, Prefs->AvailFonts[tmpf]->Datei, Prefs->AvailFonts[tmpf]->faceIndex, &face );
 				if (error)
 					tmpf = Prefs->toolSettings.defFont;
 				if (Prefs->AvailFonts[tmpf]->ReadMetrics())
Index: scribus/scribusdoc.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/scribusdoc.cpp,v
retrieving revision 1.25.2.41
diff -u -p -r1.25.2.41 scribusdoc.cpp
--- scribus/scribusdoc.cpp	17 May 2005 23:57:01 -0000	1.25.2.41
+++ scribus/scribusdoc.cpp	26 May 2005 21:50:56 -0000
@@ -525,11 +525,14 @@ bool ScribusDoc::AddFont(QString name, Q
 	bool ret = false;
 	bool error;
 	FT_Face      face;
-	if (UsedFonts.contains(name))
-		return true;
-	error = FT_New_Face( library, (*AllFonts)[name]->Datei, 0, &face );
+
+	if (UsedFonts.contains(name)) 
+		return true; 
+
+	error = FT_New_Face( library, (*AllFonts)[name]->Datei, (*AllFonts)[name]->faceIndex, &face );
 	if (error)
 		return ret;
+
 	if ((*AllFonts)[name]->ReadMetrics())
 	{
 		(*AllFonts)[name]->CharWidth[13] = 0;
Index: scribus/tabpdfoptions.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/Attic/tabpdfoptions.cpp,v
retrieving revision 1.1.2.19
diff -u -p -r1.1.2.19 tabpdfoptions.cpp
--- scribus/tabpdfoptions.cpp	17 May 2005 21:30:02 -0000	1.1.2.19
+++ scribus/tabpdfoptions.cpp	26 May 2005 21:51:12 -0000
@@ -240,11 +240,11 @@ TabPDFOptions::TabPDFOptions(   QWidget*
 		QMap<QString,QFont>::Iterator it;
 		for (it = DocFonts.begin(); it != DocFonts.end(); ++it)
 		{
-			if (AllFonts[it.key()]->typeCode == 1)
+			if (AllFonts[it.key()]->typeCode == Foi::TYPE1)
 				AvailFlist->insertItem(loadIcon("font_type1_16.png"), it.key());
-			else if (AllFonts[it.key()]->typeCode == 2)
+			else if (AllFonts[it.key()]->typeCode == Foi::TTF)
 				AvailFlist->insertItem(loadIcon("font_truetype16.png"), it.key());
-			else if (AllFonts[it.key()]->typeCode == 3)
+			else if (AllFonts[it.key()]->typeCode == Foi::OTF)
 				AvailFlist->insertItem(loadIcon("font_otf16.png"), it.key());
 		}
 		AvailFlist->setMinimumSize(QSize(150, 140));
Index: scribus/tabtools.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/Attic/tabtools.cpp,v
retrieving revision 1.1.2.9
diff -u -p -r1.1.2.9 tabtools.cpp
--- scribus/tabtools.cpp	17 May 2005 23:57:01 -0000	1.1.2.9
+++ scribus/tabtools.cpp	26 May 2005 21:51:13 -0000
@@ -12,7 +12,7 @@
 #include "scribusstructs.h"
 #include "scribus.h"
 extern QPixmap loadIcon(QString nam);
-extern QPixmap fontSamples(QString da, int s, QString ts, QColor back);
+extern QPixmap fontSamples(Foi * fnt, int s, QString ts, QColor back);
 extern ScribusApp* ScApp;
 
 TabTools::TabTools( QWidget* parent, struct toolPrefs *prefsData, int unitIndex, ScribusDoc* doc) : QWidget( parent, "tabtools", 0 )
@@ -676,9 +676,8 @@ void TabTools::changeImageScalingRatio(i
 void TabTools::setSample()
 {
 	QString ts = tr( "Woven silk pyjamas exchanged for blue quartz" );
-	QString da = (*fon)[fontComboText->currentText()]->Datei;
 	int s = sizeComboText->currentText().left(2).toInt();
-	QPixmap pm = fontSamples(da, s, ts, paletteBackgroundColor());
+	QPixmap pm = fontSamples((*fon)[fontComboText->currentText()], s, ts, paletteBackgroundColor());
 	previewText->setPixmap(pm);
 }
 
Index: scribus/util.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/util.cpp,v
retrieving revision 1.52.2.75
diff -u -p -r1.52.2.75 util.cpp
--- scribus/util.cpp	25 May 2005 11:58:50 -0000	1.52.2.75
+++ scribus/util.cpp	26 May 2005 21:51:14 -0000
@@ -25,6 +25,7 @@
 #include <qdatastream.h>
 #include <qstringlist.h>
 #include <qmap.h>
+#include <qregexp.h>
 #include <qdom.h>
 #include <qimage.h>
 #include <qdir.h>
@@ -104,12 +105,12 @@ int setBestEncoding(FT_Face face);
 FPointArray traceChar(FT_Face face, uint chr, int chs, double *x, double *y, bool &err);
 FPoint getMaxClipF(FPointArray* Clip);
 FPoint getMinClipF(FPointArray* Clip);
-QPixmap FontSample(QString da, int s, QString ts, QColor back, bool force = false);
-QPixmap fontSamples(QString da, int s, QString ts, QColor back);
+QPixmap FontSample(Foi * fnt, int s, QString ts, QColor back, bool force = false);
+QPixmap fontSamples(Foi * fnt, int s, QString ts, QColor back);
 QString Path2Relative(QString Path);
 QPixmap LoadPDF(QString fn, int Page, int Size, int *w, int *h);
-bool GlyNames(QMap<uint, QString> *GList, QString Dat);
-bool GlyIndex(QMap<uint, PDFlib::GlNamInd> *GListInd, QString Dat);
+bool GlyNames(Foi * fnt, QMap<uint, QString> *GList);
+bool GlyIndex(Foi * fnt, QMap<uint, PDFlib::GlNamInd> *GListInd);
 QByteArray ComputeMD5Sum(QByteArray *in);
 char *toHex( uchar u );
 QString String2Hex(QString *in, bool lang = true);
@@ -551,9 +554,15 @@ QString CompressStr(QString *in)
 		bb[ax] = uchar(QChar(in->at(ax)));
 	uLong exlen = uint(bb.size() * 0.001 + 16) + bb.size();
 	QByteArray bc(exlen);
-	compress2((Byte *)bc.data(), &exlen, (Byte *)bb.data(), uLong(bb.size()), 9);
-	for (uint cl = 0; cl < exlen; ++cl)
-		out += bc[cl];
+	int errcode = compress2((Byte *)bc.data(), &exlen, (Byte *)bb.data(), uLong(bb.size()), 9);
+	if (errcode != Z_OK) {
+		qDebug(QString("compress2 failed with code %1").arg(errcode));
+		out = *in;
+	}
+	else {
+		for (uint cl = 0; cl < exlen; ++cl)
+			out += bc[cl];
+	}
 #else
 	out = *in;
 #endif
@@ -683,34 +692,86 @@ int setBestEncoding(FT_Face face)
 	return retVal;
 }
 
-bool GlyNames(QMap<uint, QString> *GList, QString Dat)
+
+static QMap<FT_ULong, QString> adobeGlyphNames;
+static const char* table[] = {
+//#include "glyphnames.txt.q"
+					NULL};
+
+/// init the Adobe Glyph List
+void readAdobeGlyphNames() {
+	adobeGlyphNames.clear();
+	QRegExp pattern("(\\w*);([0-9A-Fa-f]{4})");
+	for (uint i=0; table[i]; ++i) {
+		if (pattern.search(table[i]) >= 0) {
+			FT_ULong unicode = pattern.cap(2).toULong(0, 16);
+			qDebug(QString("reading glyph name %1 fo unicode %2(%3)").arg(pattern.cap(1)).arg(unicode).arg(pattern.cap(2)));
+			adobeGlyphNames[unicode] = pattern.cap(1);
+		}
+	}
+}
+
+
+/// if in AGL, use that name, else use "uni1234" or "u12345"
+QString adobeGlyphName(FT_ULong charcode) {
+	static const char HEX[] = "0123456789ABCDEF";
+	QString result = adobeGlyphNames[charcode];
+	if (result.length() == 0 && charcode < 0x10000) {
+		result = QString("uni") + HEX[charcode>>12 & 0xF] 
+		                        + HEX[charcode>> 8 & 0xF] 
+		                        + HEX[charcode>> 4 & 0xF] 
+		                        + HEX[charcode     & 0xF];
+	}
+	else if (result.length() == 0) {
+		result = QString("u");
+		for (int i= 28; i >= 0; i-=4) {
+			if (charcode & (0xF << i))
+				result += HEX[charcode >> i & 0xF];
+		}
+	}
+	return result;
+}
+
+bool GlyNames(Foi * fnt, QMap<uint, QString> *GList)
 {
 	bool error;
-	char *buf[50];
+	char buf[50];
 	FT_Library library;
 	FT_Face face;
 	FT_ULong  charcode;
 	FT_UInt gindex;
 	error = FT_Init_FreeType(&library);
-	error = FT_New_Face(library, Dat, 0, &face);
+	error = FT_New_Face(library, fnt->Datei, fnt->faceIndex, &face);
 	setBestEncoding(face);
 	gindex = 0;
 	charcode = FT_Get_First_Char(face, &gindex );
+	const bool hasPSNames = FT_HAS_GLYPH_NAMES(face);
+	if (adobeGlyphNames.empty())
+		readAdobeGlyphNames();
 	while (gindex != 0)
 	{
-		FT_Get_Glyph_Name(face, gindex, buf, 50);
-		GList->insert(charcode, QString(reinterpret_cast<char*>(buf)));
+		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 '.'		
+		if (notfound || buf[0] == '\0' || buf[0] == '.')
+			GList->insert(charcode, adobeGlyphName(charcode));
+		else
+			GList->insert(charcode, QString(reinterpret_cast<char*>(buf)));
+			
 		charcode = FT_Get_Next_Char(face, charcode, &gindex );
 	}
 	FT_Done_FreeType( library );
 	return true;
 }
 
-bool GlyIndex(QMap<uint, PDFlib::GlNamInd> *GListInd, QString Dat)
+bool GlyIndex(Foi * fnt, QMap<uint, PDFlib::GlNamInd> *GListInd)
 {
 	struct PDFlib::GlNamInd gln;
 	bool error;
-	char *buf[50];
+	char buf[50];
 	FT_Library library;
 	FT_Face face;
 	FT_ULong  charcode;
@@ -718,15 +779,27 @@ bool GlyIndex(QMap<uint, PDFlib::GlNamIn
 	uint counter1 = 32;
 	uint counter2 = 0;
 	error = FT_Init_FreeType(&library);
-	error = FT_New_Face(library, Dat, 0, &face);
+	error = FT_New_Face(library, fnt->Datei, fnt->faceIndex, &face);
 	setBestEncoding(face);
 	gindex = 0;
 	charcode = FT_Get_First_Char(face, &gindex );
+	const bool hasPSNames = FT_HAS_GLYPH_NAMES(face);
+	if (adobeGlyphNames.empty())
+		readAdobeGlyphNames();
 	while (gindex != 0)
 	{
-		error = FT_Get_Glyph_Name(face, gindex, buf, 50);
+		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 '.'		
+		if (notfound || buf[0] == '\0' || buf[0] == '.')
+			gln.Name = "/" + adobeGlyphName(charcode);
+		else
+			gln.Name = "/" + QString(buf);
+
 		gln.Code = counter1 + counter2;
-		gln.Name = "/"+QString(reinterpret_cast<char*>(buf));
 		GListInd->insert(charcode, gln);
 		charcode = FT_Get_Next_Char(face, charcode, &gindex );
 		counter1++;
@@ -891,7 +964,7 @@ FPoint getMinClipF(FPointArray* Clip)
 	return rp;
 }
 
-QPixmap FontSample(QString da, int s, QString ts, QColor back, bool force)
+QPixmap FontSample(Foi * fnt, int s, QString ts, QColor back, bool force)
 {
 	FT_Face face;
 	FT_Library library;
@@ -900,7 +973,7 @@ QPixmap FontSample(QString da, int s, QS
 	int  pen_x;
 	FPoint gp;
 	error = FT_Init_FreeType( &library );
-	error = FT_New_Face( library, da, 0, &face );
+	error = FT_New_Face( library, fnt->Datei, fnt->faceIndex, &face );
 	int encode = setBestEncoding(face);
 	double uniEM = static_cast<double>(face->units_per_EM);
 	int h = qRound(face->height / uniEM) * s + 1;
@@ -979,7 +1052,7 @@ QPixmap FontSample(QString da, int s, QS
 /** Same as FontSample() with \n strings support added.
 09/26/2004 petr vanek
 */
-QPixmap fontSamples(QString da, int s, QString ts, QColor back)
+QPixmap fontSamples(Foi * fnt, int s, QString ts, QColor back)
 {
 	QStringList lines = QStringList::split("\n", ts);
 	QPixmap ret(640, 480);
@@ -990,7 +1063,7 @@ QPixmap fontSamples(QString da, int s, Q
 	ret.fill(back);
 	for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it )
 	{
-		sample = FontSample(da, s, *it, back);
+		sample = FontSample(fnt, s, *it, back);
 		if (!sample.isNull())
 			painter->drawPixmap(0, y, sample, 0, 0);
 		y = y + sample.height();
Index: scribus/libpdf/pdflib.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/libpdf/pdflib.cpp,v
retrieving revision 1.78.2.87
diff -u -p -r1.78.2.87 pdflib.cpp
--- scribus/libpdf/pdflib.cpp	25 May 2005 10:54:21 -0000	1.78.2.87
+++ scribus/libpdf/pdflib.cpp	26 May 2005 21:51:20 -0000
@@ -50,7 +50,7 @@ using namespace std;
 
 extern int callGS(const QStringList & args);
 extern QString Path2Relative(QString Path);
-extern bool GlyIndex(QMap<uint, PDFlib::GlNamInd> *GListInd, QString Dat);
+extern bool GlyIndex(Foi * fnt, QMap<uint, PDFlib::GlNamInd> *GListInd);
 extern QByteArray ComputeMD5Sum(QByteArray *in);
 extern bool loadText(QString nam, QString *Buffer);
 extern void Level2Layer(ScribusDoc *doc, struct Layer *ll, int Level);
@@ -577,8 +577,7 @@ bool PDFlib::PDF_Begin_Doc(QString fn, S
 	a = 0;
 	for (it = ReallyUsed.begin(); it != ReallyUsed.end(); ++it)
 	{
-		fd = QFileInfo(AllFonts[it.key()]->Datei);
-		fext = fd.extension(false).lower();
+		Foi::FontFormat fformat = AllFonts[it.key()]->formatCode;
 		if ((AllFonts[it.key()]->isOTF) || (!AllFonts[it.key()]->HasNames) || (AllFonts[it.key()]->Subset) || (Options->SubsetList.contains(it.key())))
 		{
 			QString fon = "";
@@ -641,17 +640,12 @@ bool PDFlib::PDF_Begin_Doc(QString fn, S
 		else
 		{
 			UsedFontsP.insert(it.key(), "/Fo"+IToStr(a));
-			if ((fext == "pfb") && (Options->EmbedList.contains(it.key())))
+			if ((fformat == Foi::PFB) && (Options->EmbedList.contains(it.key())))
 			{
 				QString fon = "";
 				StartObj(ObjCounter);
-				QFile f(AllFonts[it.key()]->Datei);
-				QByteArray bb(f.size());
-				if (f.open(IO_ReadOnly))
-				{
-					f.readBlock(bb.data(), f.size());
-					f.close();
-				}
+				QByteArray bb;
+				AllFonts[it.key()]->RawData(bb);
 				uint posi;
 				for (posi = 6; posi < bb.size(); ++posi)
 				{
@@ -694,7 +688,7 @@ bool PDFlib::PDF_Begin_Doc(QString fn, S
 				PutDoc(">>\nstream\n"+EncStream(&fon,ObjCounter)+"\nendstream\nendobj\n");
 				ObjCounter++;
 			}
-			if ((fext == "pfa") && (Options->EmbedList.contains(it.key())))
+			if ((fformat == Foi::PFA) && (Options->EmbedList.contains(it.key())))
 			{
 				QString fon = "";
 				QString fon2 = "";
@@ -702,7 +696,7 @@ bool PDFlib::PDF_Begin_Doc(QString fn, S
 				uint value;
 				bool ok = true;
 				StartObj(ObjCounter);
-				loadText(AllFonts[it.key()]->Datei, &fon);
+				AllFonts[it.key()]->EmbedFont(fon);
 				int len1 = fon.find("eexec")+5;
 				fon2 = fon.left(len1)+"\n";
 				int len2 = fon.find("0000000000000000000000000");
@@ -733,22 +727,19 @@ bool PDFlib::PDF_Begin_Doc(QString fn, S
 				PutDoc(">>\nstream\n"+EncStream(&fon2, ObjCounter)+"\nendstream\nendobj\n");
 				ObjCounter++;
 			}
-			if (((fext == "ttf") || (fext == "otf")) && (Options->EmbedList.contains(it.key())))
+			if ((fformat == Foi::SFNT || fformat == Foi::TTCF) && (Options->EmbedList.contains(it.key())))
 			{
-				QString fon = "";
+				QString fon("");
 				StartObj(ObjCounter);
-				QFile f(AllFonts[it.key()]->Datei);
-				QByteArray bb(f.size());
-				if (f.open(IO_ReadOnly))
-				{
-					f.readBlock(bb.data(), f.size());
-					f.close();
-				}
-				for (uint posi = 0; posi < bb.size(); ++posi)
-					fon += bb[posi];
+				QByteArray bb;
+				AllFonts[it.key()]->RawData(bb);
+				//AV: += and append() dont't work because they stop at '\0' :-(
+				for (unsigned int i=0; i < bb.size(); i++)
+					fon += bb[i];
 				int len = fon.length();
 				if ((Options->Compress) && (CompAvail))
 					fon = CompressStr(&fon);
+				qDebug(QString("sfnt data: size=%1 before=%2 compressed=%3").arg(bb.size()).arg(len).arg(fon.length()));
 				PutDoc("<<\n/Length "+IToStr(fon.length()+1)+"\n");
 				PutDoc("/Length1 "+IToStr(len)+"\n");
 				if ((Options->Compress) && (CompAvail))
@@ -775,26 +766,15 @@ bool PDFlib::PDF_Begin_Doc(QString fn, S
 			PutDoc("/CapHeight "+AllFonts[it.key()]->CapHeight+"\n");
 			PutDoc("/ItalicAngle "+AllFonts[it.key()]->ItalicAngle+"\n");
 			PutDoc("/StemV "+AllFonts[it.key()]->StdVW+"\n");
-			if (((fext == "ttf") || (fext == "otf")) && (Options->EmbedList.contains(it.key())))
+			if ((fformat == Foi::SFNT || fformat == Foi::TTCF) && (Options->EmbedList.contains(it.key())))
 				PutDoc("/FontFile2 "+IToStr(ObjCounter-1)+" 0 R\n");
-			if ((fext == "pfb") && (Options->EmbedList.contains(it.key())))
+			if ((fformat == Foi::PFB) && (Options->EmbedList.contains(it.key())))
 				PutDoc("/FontFile "+IToStr(ObjCounter-1)+" 0 R\n");
-			if ((fext == "pfa") && (Options->EmbedList.contains(it.key())))
+			if ((fformat == Foi::PFA) && (Options->EmbedList.contains(it.key())))
 				PutDoc("/FontFile "+IToStr(ObjCounter-1)+" 0 R\n");
 			PutDoc(">>\nendobj\n");
 			ObjCounter++;
-			GListeInd gl;
-			GlyIndex(&gl, AllFonts[it.key()]->Datei);
-			GlyphsIdxOfFont.insert(it.key(), gl);
-			uint FontDes = ObjCounter - 1;
-			GListeInd::Iterator itg;
-			itg = gl.begin();
-			GListeInd::Iterator itg2;
-			itg2 = gl.begin();
-			uint Fcc = gl.count() / 224;
-			if ((gl.count() % 224) != 0)
-				Fcc += 1;
-			for (uint Fc = 0; Fc < Fcc; ++Fc)
+/*			if (!FT_Has_PS_Glyph_Names(AllFonts[it.key()]) 
 			{
 				StartObj(ObjCounter);
 				int chCount = 31;
@@ -810,38 +790,88 @@ bool PDFlib::PDF_Begin_Doc(QString fn, S
 				}
 				PutDoc("]\nendobj\n");
 				ObjCounter++;
-				StartObj(ObjCounter);
-				ObjCounter++;
-				PutDoc("<< /Type /Encoding\n/Differences [ 32\n");
-				int crc = 0;
-				for (int ww2 = 32; ww2 < 256; ++ww2)
-				{
-					PutDoc(itg2.data().Name+" ");
-					if (itg2 == gl.end())
-						break;
-					++itg2;
-					crc++;
-					if (crc > 8)
-					{
-						PutDoc("\n");
-						crc = 0;
-					}
-				}
-				PutDoc("]\n>>\nendobj\n");
+				// put widths object
+				// encoding dictionary w/ base encoding w/o differences
 				StartObj(ObjCounter);
 				PutDoc("<<\n/Type /Font\n/Subtype ");
-				PutDoc(((fext == "ttf") || (fext == "otf")) ? "/TrueType\n" : "/Type1\n");
-				PutDoc("/Name /Fo"+IToStr(a)+"S"+IToStr(Fc)+"\n");
+				PutDoc((fformat == Foi::SFNT || fformat == Foi::TTCF) ? "/TrueType\n" : "/Type1\n");
+				PutDoc("/Name /Fo"+IToStr(a)+"\n");
 				PutDoc("/BaseFont /"+AllFonts[it.key()]->RealName().replace( QRegExp("\\s"), "" )+"\n");
+				//cf. widths:
 				PutDoc("/FirstChar 0\n");
 				PutDoc("/LastChar "+IToStr(chCount-1)+"\n");
-				PutDoc("/Widths "+IToStr(ObjCounter-2)+" 0 R\n");
-				PutDoc("/Encoding "+IToStr(ObjCounter-1)+" 0 R\n");
-				PutDoc("/FontDescriptor "+IToStr(FontDes)+" 0 R\n");
+				PutDoc("/Widths "+IToStr(ObjCounter-1)+" 0 R\n");
+				PutDoc("/FontDescriptor "+IToStr(ObjCounter-2)+" 0 R\n");
 				PutDoc(">>\nendobj\n");
-				Seite.FObjects["Fo"+IToStr(a)+"S"+IToStr(Fc)] = ObjCounter;
+				Seite.FObjects["Fo"+IToStr(a)] = ObjCounter;
 				ObjCounter++;
 			}
+			else */
+			{
+				GListeInd gl;
+				GlyIndex(AllFonts[it.key()], &gl);
+				GlyphsIdxOfFont.insert(it.key(), gl);
+				uint FontDes = ObjCounter - 1;
+				GListeInd::Iterator itg;
+				itg = gl.begin();
+				GListeInd::Iterator itg2;
+				itg2 = gl.begin();
+				uint Fcc = gl.count() / 224;
+				if ((gl.count() % 224) != 0)
+					Fcc += 1;
+				for (uint Fc = 0; Fc < Fcc; ++Fc)
+				{
+					StartObj(ObjCounter);
+					int chCount = 31;
+					PutDoc("[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ");
+					for (int ww = 31; ww < 256; ++ww)
+					{
+						PutDoc(IToStr(static_cast<int>(AllFonts[it.key()]->CharWidth[itg.key()]*
+								1000))+" ");
+						if (itg == gl.end())
+							break;
+						++itg;
+						chCount++;
+					}
+					PutDoc("]\nendobj\n");
+					ObjCounter++;
+					StartObj(ObjCounter);
+					ObjCounter++;
+					PutDoc("<< /Type /Encoding\n");
+					PutDoc("/BaseEncoding /" + AllFonts[it.key()]->FontEnc + "\n");
+					PutDoc("/Differences [ 32\n");
+					int crc = 0;
+					for (int ww2 = 32; ww2 < 256; ++ww2)
+					{
+						PutDoc(itg2.data().Name+" ");
+						if (itg2 == gl.end())
+							break;
+						++itg2;
+						crc++;
+						if (crc > 8)
+						{
+							PutDoc("\n");
+							crc = 0;
+						}
+					}
+					PutDoc("]\n");
+	
+					PutDoc(">>\nendobj\n");
+					StartObj(ObjCounter);
+					PutDoc("<<\n/Type /Font\n/Subtype ");
+					PutDoc((fformat == Foi::SFNT || fformat == Foi::TTCF) ? "/TrueType\n" : "/Type1\n");
+					PutDoc("/Name /Fo"+IToStr(a)+"S"+IToStr(Fc)+"\n");
+					PutDoc("/BaseFont /"+AllFonts[it.key()]->RealName().replace( QRegExp("\\s"), "" )+"\n");
+					PutDoc("/FirstChar 0\n");
+					PutDoc("/LastChar "+IToStr(chCount-1)+"\n");
+					PutDoc("/Widths "+IToStr(ObjCounter-2)+" 0 R\n");
+					PutDoc("/Encoding "+IToStr(ObjCounter-1)+" 0 R\n");
+					PutDoc("/FontDescriptor "+IToStr(FontDes)+" 0 R\n");
+					PutDoc(">>\nendobj\n");
+					Seite.FObjects["Fo"+IToStr(a)+"S"+IToStr(Fc)] = ObjCounter;
+					ObjCounter++;
+				} // for(Fc)
+			} // FT_Has_PS_Glyph_Names
 		}
 		a++;
 	}
Index: scribus/libpostscript/pslib.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/libpostscript/pslib.cpp,v
retrieving revision 1.24.2.56
diff -u -p -r1.24.2.56 pslib.cpp
--- scribus/libpostscript/pslib.cpp	25 May 2005 10:54:22 -0000	1.24.2.56
+++ scribus/libpostscript/pslib.cpp	26 May 2005 21:51:22 -0000
@@ -111,10 +111,9 @@ PSLib::PSLib(bool psart, SCFonts &AllFon
 	for (it = DocFonts.begin(); it != DocFonts.end(); ++it)
 	{
 /* Subset all TTF Fonts until the bug in the TTF-Embedding Code is fixed */
-		QFileInfo fd = QFileInfo(AllFonts[it.key()]->Datei);
-		QString fext = fd.extension(false).lower();
+		Foi::FontType type = AllFonts[it.key()]->typeCode;
 
-		if ((fext == "ttf") || (AllFonts[it.key()]->isOTF) || (AllFonts[it.key()]->Subset))
+		if ((type == Foi::TTF) || (AllFonts[it.key()]->isOTF) || (AllFonts[it.key()]->Subset))
 		{
 			FontDesc += "/"+AllFonts[it.key()]->RealName().simplifyWhiteSpace().replace( QRegExp("\\s"), "" )+
 					" "+IToStr(AllFonts[it.key()]->RealGlyphs.count()+1)+" dict def\n";
@@ -1177,6 +1176,283 @@ void PSLib::CreatePS(ScribusDoc* Doc, Sc
 									PS_translate(0, -ite->Height);
 									PS_scale(1, -1);
 								}
+/* pslib.cpp
+								for (uint d = 0; d < ite->MaxChars; ++d)
+								{
+									hl = ite->itemText.at(d);
+									if ((hl->ch == QChar(13)) || (hl->ch == QChar(10)) || (hl->ch == QChar(9)) || (hl->ch == QChar(28)))
+										continue;
+									if (hl->cstyle & 256)
+										continue;
+									if (hl->yp == 0)
+										continue;
+									tsz = hl->csize;
+									chx = hl->ch;
+									if (hl->ch == QChar(29))
+										chx = " ";
+									if (hl->ch == QChar(0xA0))
+										chx = " ";
+									if (hl->ch == QChar(30))
+									{
+										if (Doc->MasterP)
+											chx = "#";
+										else
+										{
+											uint zae = 0;
+											uint za2 = d;
+											do
+											{
+												if (za2 == 0)
+													break;
+												za2--;
+											}
+											while (ite->itemText.at(za2)->ch == QChar(30));
+											if (ite->itemText.at(za2)->ch != QChar(30))
+												za2++;
+											while (ite->itemText.at(za2+zae)->ch == QChar(30))
+											{
+												zae++;
+												if (za2+zae == ite->MaxChars)
+													break;
+											}
+											QString out="%1";
+											QString out2;
+											out2 = out.arg(a+Doc->FirstPnum, -zae);
+											chx = out2.mid(d-za2, 1);
+										}
+									}
+									if (hl->cstyle & 64)
+									{
+										if (chx.upper() != chx)
+										{
+											tsz = hl->csize * Doc->typographicSetttings.valueSmallCaps / 100;
+											chx = chx.upper();
+										}
+									}
+									if (hl->cstyle & 1)
+										tsz = hl->csize * Doc->typographicSetttings.scalingSuperScript / 100;
+									if (hl->cstyle & 2)
+										tsz = hl->csize * Doc->typographicSetttings.scalingSuperScript / 100;
+									/* Subset all TTF Fonts until the bug in the TTF-Embedding Code is fixed * /
+									Foi::FontType type = hl->cfont->typeCode;
+									if ((type == Foi::TTF) || (hl->cfont->isOTF) || (hl->cfont->Subset))
+									{
+										uint chr = chx[0].unicode();
+										if ((hl->cfont->CharWidth.contains(chr)) && (chr != 32))
+										{
+											PS_save();
+											if (ite->Reverse)
+											{
+												PS_translate(hl->xp, (hl->yp - (tsz / 10.0)) * -1);
+												PS_scale(-1, 1);
+												if (d < ite->MaxChars-1)
+												{
+													QString ctx = ite->itemText.at(d+1)->ch;
+													if (ctx == QChar(29))
+														ctx = " ";
+													if (ctx == QChar(0xA0))
+														ctx = " ";
+													wideR = -Cwidth(Doc, hl->cfont, chx, tsz, ctx) * (hl->cscale / 100.0);
+												}
+												else
+													wideR = -Cwidth(Doc, hl->cfont, chx, tsz) * (hl->cscale / 100.0);
+												PS_translate(wideR, 0);
+											}
+											else
+												PS_translate(hl->xp, (hl->yp - (tsz / 10.0)) * -1);
+											if (hl->cscale != 100)
+												PS_scale(hl->cscale / 100.0, 1);
+											if (hl->ccolor != "None")
+											{
+												SetFarbe(Doc, hl->ccolor, hl->cshade, &h, &s, &v, &k, gcr);
+												PS_setcmykcolor_fill(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
+												PS_showSub(chr, hl->cfont->RealName().simplifyWhiteSpace().replace( QRegExp("\\s"), "" ), tsz / 10.0, false);
+											}
+											PS_restore();
+										}
+									}
+									else
+									{
+										PS_selectfont(hl->cfont->SCName, tsz / 10.0);
+										if (hl->ccolor != "None")
+										{
+											SetFarbe(Doc, hl->ccolor, hl->cshade, &h, &s, &v, &k, gcr);
+											PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
+										}
+										PS_save();
+										if (ite->Reverse)
+										{
+											int chs = hl->csize;
+											ite->SetZeichAttr(hl, &chs, &chx);
+											PS_translate(hl->xp, -hl->yp);
+											PS_scale(-1, 1);
+											if (d < ite->MaxChars-1)
+											{
+												QString ctx = ite->itemText.at(d+1)->ch;
+												if (ctx == QChar(29))
+													ctx = " ";
+												if (ctx == QChar(0xA0))
+													ctx = " ";
+												wideR = -Cwidth(Doc, hl->cfont, chx, chs, ctx) * (hl->cscale / 100.0);
+												PS_translate(wideR, 0);
+											}
+											else
+											{
+												wideR = -Cwidth(Doc, hl->cfont, chx, chs) * (hl->cscale / 100.0);
+												PS_translate(wideR, 0);
+											}
+											if (hl->cscale != 100)
+												PS_scale(hl->cscale / 100.0, 1);
+											PS_show_xyG(hl->cfont->SCName, chx, 0, 0);
+										}
+										else
+										{
+											PS_translate(hl->xp, -hl->yp);
+											if (hl->cscale != 100)
+												PS_scale(hl->cscale / 100.0, 1);
+											PS_show_xyG(hl->cfont->SCName, chx, 0, 0);
+										}
+										PS_restore();
+									}
+									if ((hl->cstyle & 4) && (chx != QChar(13)))
+									{
+										uint chr = chx[0].unicode();
+										if (hl->cfont->CharWidth.contains(chr))
+										{
+											FPointArray gly = hl->cfont->GlyphArray[chr].Outlines.copy();
+											QWMatrix chma;
+											chma.scale(tsz / 100.0, tsz / 100.0);
+											gly.map(chma);
+											chma = QWMatrix();
+											chma.scale(hl->cscale / 100.0, 1);
+											gly.map(chma);
+											if (ite->Reverse)
+											{
+												chma = QWMatrix();
+												chma.scale(-1, 1);
+												chma.translate(wideR, 0);
+												gly.map(chma);
+											}
+											if (hl->cstroke != "None")
+											{
+												PS_save();
+												PS_setlinewidth(QMAX(hl->cfont->strokeWidth / 2 * (tsz / 10.0), 1));
+												PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin);
+												PS_setdash(Qt::SolidLine, 0, dum);
+												PS_translate(hl->xp, (hl->yp - tsz) * -1);
+												SetFarbe(Doc, hl->cstroke, hl->cshade2, &h, &s, &v, &k, gcr);
+												PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
+												SetClipPath(&gly);
+												PS_closepath();
+												PS_stroke();
+												PS_restore();
+											}
+										}
+									}
+									if ((hl->cstyle & 16) && (chx != QChar(13)))
+									{
+										double Ulen = Cwidth(Doc, hl->cfont, chx, hl->csize) * (hl->cscale / 100.0);
+										double Upos, lw, kern;
+										if (hl->cstyle & 1024)
+											kern = 0;
+										else
+											kern = hl->cextra;
+										if ((Doc->typographicSetttings.valueStrikeThruPos != -1) || (Doc->typographicSetttings.valueStrikeThruWidth != -1))
+										{
+											if (Doc->typographicSetttings.valueStrikeThruPos != -1)
+												Upos = (Doc->typographicSetttings.valueStrikeThruPos / 100.0) * (hl->cfont->numAscent * (tsz / 10.0));
+											else
+												Upos = hl->cfont->strikeout_pos * (tsz / 10.0);
+											if (Doc->typographicSetttings.valueStrikeThruWidth != -1)
+												lw = (Doc->typographicSetttings.valueStrikeThruWidth / 100.0) * (tsz / 10.0);
+											else
+												lw = QMAX(hl->cfont->strokeWidth * (tsz / 10.0), 1);
+										}
+										else
+										{
+											Upos = hl->cfont->strikeout_pos * (tsz / 10.0);
+											lw = QMAX(hl->cfont->strokeWidth * (tsz / 10.0), 1);
+										}
+										if (hl->ccolor != "None")
+										{
+											PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin);
+											PS_setdash(Qt::SolidLine, 0, dum);
+											SetFarbe(Doc, hl->ccolor, hl->cshade, &h, &s, &v, &k, gcr);
+											PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
+										}
+										PS_setlinewidth(lw);
+										PS_moveto(hl->xp-kern, -hl->yp+Upos);
+										PS_lineto(hl->xp+Ulen, -hl->yp+Upos);
+										PS_stroke();
+									}
+									if ((hl->cstyle & 8) && (chx != QChar(13)))
+									{
+										double Ulen = Cwidth(Doc, hl->cfont, chx, hl->csize) * (hl->cscale / 100.0);
+										double Upos, lw, kern;
+										if (hl->cstyle & 1024)
+											kern = 0;
+										else
+											kern = hl->cextra;
+										if ((Doc->typographicSetttings.valueUnderlinePos != -1) || (Doc->typographicSetttings.valueUnderlineWidth != -1))
+										{
+											if (Doc->typographicSetttings.valueUnderlinePos != -1)
+												Upos = (Doc->typographicSetttings.valueUnderlinePos / 100.0) * (hl->cfont->numDescender * (tsz / 10.0));
+											else
+												Upos = hl->cfont->underline_pos * (tsz / 10.0);
+											if (Doc->typographicSetttings.valueUnderlineWidth != -1)
+												lw = (Doc->typographicSetttings.valueUnderlineWidth / 100.0) * (tsz / 10.0);
+											else
+												lw = QMAX(hl->cfont->strokeWidth * (tsz / 10.0), 1);
+										}
+										else
+										{
+											Upos = hl->cfont->underline_pos * (tsz / 10.0);
+											lw = QMAX(hl->cfont->strokeWidth * (tsz / 10.0), 1);
+										}
+										if (hl->ccolor != "None")
+										{
+											PS_setcapjoin(Qt::FlatCap, Qt::MiterJoin);
+											PS_setdash(Qt::SolidLine, 0, dum);
+											SetFarbe(Doc, hl->ccolor, hl->cshade, &h, &s, &v, &k, gcr);
+											PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
+										}
+										PS_setlinewidth(lw);
+										PS_moveto(hl->xp-kern, -hl->yp+Upos);
+										PS_lineto(hl->xp+Ulen, -hl->yp+Upos);
+										PS_stroke();
+									}
+									if (hl->cstyle & 512)
+									{
+										int chs = hl->csize;
+										ite->SetZeichAttr(hl, &chs, &chx);
+										double wide = Cwidth(Doc, hl->cfont, chx, chs);
+										chx = "-";
+										uint chr = chx[0].unicode();
+										if (hl->cfont->CharWidth.contains(chr))
+										{
+											FPointArray gly = hl->cfont->GlyphArray[chr].Outlines.copy();
+											QWMatrix chma;
+											chma.scale(tsz / 100.0, tsz / 100.0);
+											gly.map(chma);
+											chma = QWMatrix();
+											chma.scale(hl->cscale / 100.0, 1);
+											gly.map(chma);
+											if (hl->ccolor != "None")
+											{
+												PS_save();
+												PS_newpath();
+												PS_translate(hl->xp+wide, (hl->yp - (tsz / 10.0)) * -1);
+												SetFarbe(Doc, hl->ccolor, hl->cshade, &h, &s, &v, &k, gcr);
+												PS_setcmykcolor_fill(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
+												SetClipPath(&gly);
+												PS_closepath();
+												PS_fill();
+												PS_restore();
+											}
+										}
+									}
+								}
+*/
 								setTextSt(Doc, ite, gcr, a);
 								if (((ite->lineColor() != "None") || (ite->NamedLStyle != "")) && (!ite->isTableItem))
 								{
@@ -1694,9 +2247,8 @@ void PSLib::ProcessItem(ScribusDoc* Doc,
 					PS_setcmykcolor_stroke(h / 255.0, s / 255.0, v / 255.0, k / 255.0);
 				}
 				/* Subset all TTF Fonts until the bug in the TTF-Embedding Code is fixed */
-				QFileInfo fd = QFileInfo(hl->cfont->Datei);
-				QString fext = fd.extension(false).lower();
-				if ((fext == "ttf") || (hl->cfont->isOTF) || (hl->cfont->Subset))
+				Foi::FontType type = hl->cfont->typeCode;
+				if ((type == Foi::TTF) ||  (hl->cfont->isOTF) || (hl->cfont->Subset))
 				{
 					uint chr = chx[0].unicode();
 					if ((hl->cfont->CharWidth.contains(chr)) && (chr != 32))
@@ -2124,9 +2676,8 @@ void PSLib::setTextCh(ScribusDoc* Doc, P
 	if (hl->cstyle & 2)
 		tsz = hl->csize * Doc->typographicSetttings.scalingSuperScript / 100;
 	/* Subset all TTF Fonts until the bug in the TTF-Embedding Code is fixed */
-	QFileInfo fd = QFileInfo(hl->cfont->Datei);
-	QString fext = fd.extension(false).lower();
-	if ((fext == "ttf") || (hl->cfont->isOTF) || (hl->cfont->Subset))
+	Foi::FontType ftype = hl->cfont->typeCode;
+	if ((ftype == Foi::TTF) || (hl->cfont->isOTF) || (hl->cfont->Subset))
 	{
 		uint chr = chx[0].unicode();
 		if ((hl->cfont->CharWidth.contains(chr)) && (chr != 32))
Index: scribus/plugins/scriptplugin/cmdmisc.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/plugins/scriptplugin/cmdmisc.cpp,v
retrieving revision 1.12.2.19
diff -u -p -r1.12.2.19 cmdmisc.cpp
--- scribus/plugins/scriptplugin/cmdmisc.cpp	8 May 2005 08:58:54 -0000	1.12.2.19
+++ scribus/plugins/scriptplugin/cmdmisc.cpp	26 May 2005 21:51:23 -0000
@@ -4,7 +4,7 @@
 #include "qbuffer.h"
 #include "qpixmap.h"
 
-extern QPixmap FontSample(QString da, int s, QString ts, QColor back, bool force = false);
+extern QPixmap FontSample(Foi * fnt, int s, QString ts, QColor back, bool force = false);
 
 PyObject *scribus_setredraw(PyObject */*self*/, PyObject* args)
 {
@@ -104,8 +104,7 @@ PyObject *scribus_renderfont(PyObject* /
 	if (!format)
 		// User specified no format, so use the historical default of PPM format.
 		format = "PPM";
-	QString da = Carrier->Prefs.AvailFonts[QString::fromUtf8(Name)]->Datei;
-	QPixmap pm = FontSample(da, Size, ts, Qt::white);
+	QPixmap pm = FontSample(Carrier->Prefs.AvailFonts[QString::fromUtf8(Name)], Size, ts, Qt::white);
 	// If the user specified an empty filename, return the image data as
 	// a string. Otherwise, save it to disk.
 	if (QString::fromUtf8(FileName) == "")
Index: scribus/plugins/fontpreview/ui.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/plugins/fontpreview/ui.cpp,v
retrieving revision 1.8.2.12
diff -u -p -r1.8.2.12 ui.cpp
--- scribus/plugins/fontpreview/ui.cpp	20 Apr 2005 19:18:02 -0000	1.8.2.12
+++ scribus/plugins/fontpreview/ui.cpp	28 May 2005 01:14:54 -0000
@@ -13,7 +13,7 @@
 
 #include <prefsfile.h>
 
-extern QPixmap fontSamples(QString da, int s, QString ts, QColor back);
+extern QPixmap fontSamples(Foi * fnt, int s, QString ts, QColor back);
 extern QPixmap loadIcon(QString nam);
 extern PrefsFile *prefsFile;
 
@@ -100,6 +100,52 @@ FontPreview::FontPreview(ScribusApp *car
 	/* go through available fonts and check their properties */
 	reallyUsedFonts.clear();
 	carrier->GetUsedFonts(&reallyUsedFonts);
+/* ui.cpp
+	QPixmap ttfFont = loadIcon("font_truetype16.png");
+	QPixmap otfFont = loadIcon("font_otf16.png");
+	QPixmap psFont = loadIcon("font_type1_16.png");
+	QPixmap okIcon = loadIcon("ok.png");
+
+	for (SCFontsIterator fontIter(carrier->Prefs.AvailFonts); fontIter.current(); ++fontIter)
+	{
+		if (fontIter.current()->UseFont)
+		{
+			QListViewItem *row = new QListViewItem(fontList);
+			Foi::FontType type = fontIter.current()->typeCode;
+			row->setText(0, fontIter.current()->SCName);
+			if (reallyUsedFonts.contains(fontIter.current()->SCName))
+				row->setPixmap(1, okIcon);
+
+			if (type == Foi::OTF)
+			{
+				row->setPixmap(2, otfFont);
+				row->setText(2, "OpenType");
+			}
+			else
+				if (fontIter.current()->Subset)
+					row->setPixmap(3, okIcon);
+
+			if (type == Foi::TYPE1) 
+			{
+				row->setPixmap(2, psFont);
+				row->setText(2, "Type1");
+			}
+
+			if (type == Foi::TTF)
+			{
+				row->setPixmap(2, ttfFont);
+				row->setText(2, "TrueType");
+			}
+
+			if (fontIter.current()->fontPath().contains(QDir::homeDirPath())) 
+				row->setText(4, tr("User", "font preview"));
+			else
+				row->setText(4, tr("System", "font preview"));
+
+			fontList->insertItem(row);
+		}
+	} // for fontIter
+*/
 	ttfFont = loadIcon("font_truetype16.png");
 	otfFont = loadIcon("font_otf16.png");
 	psFont = loadIcon("font_type1_16.png");
@@ -175,8 +221,7 @@ void FontPreview::fontList_changed()
 	QString t = tr("Woven silk pyjamas exchanged for blue quartz", "font preview");
 	t.replace('\n', " "); // remove French <NL> from translation...
 	QListViewItem *item = fontList->currentItem();
-	QString da = carrier->Prefs.AvailFonts[item->text(0)]->Datei;
-	QPixmap pixmap = fontSamples(da, sizeSpin->value(), t, white /*paletteBackgroundColor()*/);
+	QPixmap pixmap = fontSamples(carrier->Prefs.AvailFonts[item->text(0)], sizeSpin->value(), t, white /*paletteBackgroundColor()*/);
 	fontPreview->clear();
 	if (!pixmap.isNull())
 		fontPreview->setPixmap(pixmap);
@@ -193,15 +238,14 @@ void FontPreview::updateFontList(QString
 		if (fontIter.current()->UseFont)
 		{
 			QListViewItem *row = new QListViewItem(fontList);
-			QFileInfo fi = QFileInfo(fontIter.current()->Datei);
-			QString ext = fi.extension(false).lower();
+			Foi::FontType type = fontIter.current()->typeCode;
 
 			row->setText(0, fontIter.current()->SCName);
 			// searching
 			if (reallyUsedFonts.contains(fontIter.current()->SCName))
 				row->setPixmap(1, okIcon);
 
-			if (ext == "otf")
+			if (type == Foi::OTF)
 			{
 				row->setPixmap(2, otfFont);
 				row->setText(2, "OpenType");
@@ -210,18 +254,19 @@ void FontPreview::updateFontList(QString
 				if (fontIter.current()->Subset)
 					row->setPixmap(3, okIcon);
 
-			if ((ext == "pfa") || (ext == "pfb")) // type1
+			if (type == Foi::TYPE1) // type1
 			{
 				row->setPixmap(2, psFont);
 				row->setText(2, "Type1");
 			}
 
-			if (ext == "ttf")
+			if (type == Foi::TTF)
 			{
 				row->setPixmap(2, ttfFont);
 				row->setText(2, "TrueType");
 			}
 
+			QFileInfo fi(fontIter.current()->Datei);
 			fi.absFilePath().contains(QDir::homeDirPath()) ?
 					row->setText(4, tr("User", "font preview")):
 					row->setText(4, tr("System", "font preview"));
Index: scribus/scfonts.cpp
===================================================================
RCS file: /cvs/Scribus/scribus/scfonts.cpp,v
retrieving revision 1.15.2.13
diff -u -p -r1.15.2.13 scfonts.cpp
--- scribus/scfonts.cpp	13 May 2005 21:42:32 -0000	1.15.2.13
+++ scribus/scfonts.cpp	28 May 2005 01:17:58 -0000
@@ -35,16 +35,22 @@
 #include <fontconfig/fontconfig.h>
 #endif
 
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_TRUETYPE_TABLES_H
+
 extern FPointArray traceChar(FT_Face face, uint chr, int chs, double *x, double *y, bool *err);
 extern int setBestEncoding(FT_Face face);
 extern bool loadText(QString nam, QString *Buffer);
-extern bool GlyNames(QMap<uint, QString> *GList, QString Dat);
+extern bool GlyNames(Foi * fnt, QMap<uint, QString> *GList);
 
 Foi::Foi(QString scname, QString path, bool embedps) :
-	SCName(scname), Datei(path), EmbedPS(embedps)
+	SCName(scname), Datei(path), faceIndex(0), EmbedPS(embedps)
 {
 	isOTF = false;
 	Subset = false;
+	typeCode = Foi::UNKNOWN_TYPE;
+	formatCode = Foi::UNKNOWN_FORMAT;
 }
 
 QString Foi::RealName()
@@ -56,7 +62,7 @@ QString Foi::RealName()
 bool Foi::EmbedFont(QString &str)
 {
 	str+="Base";
-  return(false);
+	return(false);
 }
 
 bool Foi::ReadMetrics()
@@ -69,8 +75,46 @@ bool Foi::ReadMetrics()
 
 bool Foi::GlNames(QMap<uint, QString> *GList)
 {
-	return GlyNames(GList, Datei);
+	return GlyNames(this, GList);
 }
+
+void Foi::RawData(QByteArray & bb)
+{
+	FT_Library library;
+	FT_Face    face;
+	bool       error;
+	
+	error = FT_Init_FreeType( &library );
+	if (error)
+	{
+		qDebug(QObject::tr("Freetype lib not available"));
+	}
+	else
+	{
+		error = FT_New_Face( library, Datei, faceIndex, &face );
+	}
+	if (error)
+	{
+		qDebug(QObject::tr("Font %1 is broken, no embedding").arg(Datei));
+	}
+	else {
+		FT_Stream fts = face->stream;
+		bb.resize(fts->size);
+		error = FT_Stream_Seek(fts, 0L);
+		if (!error)
+			error = FT_Stream_Read(fts, reinterpret_cast<FT_Byte *>(bb.data()), fts->size);
+		if (error) {
+			qDebug(QObject::tr("Font %1 is broken (read stream), no embedding").arg(Datei));
+			bb.resize(0);
+		}
+		QFile f(Datei);
+		qDebug(QObject::tr("RawData for Font %1(%2): size=%3 filesize=%4").arg(Datei).arg(faceIndex).arg(bb.size()).arg(f.size()));
+	}
+	FT_Done_Face(face);
+	FT_Done_FreeType(library);
+}
+
+
 /*
 void Foi::FontBez()
 {
@@ -146,6 +190,7 @@ class Foi_postscript : public Foi
 			StdVW = "1";
 			FontBBox = "0 0 0 0";
 			IsFixedPitch = false;
+			typeCode = TYPE1;
 			HasMetrics=true;
 		}
 
@@ -176,14 +221,15 @@ class Foi_postscript : public Foi
 			if (error)
 			{
 				UseFont = false;
-				qDebug(QObject::tr("Font %1 is broken, discarding it").arg(Datei));
+				qDebug(QObject::tr("Font %1 is broken (FreeType), discarding it").arg(Datei));
 				return false;
 			}
-			error = FT_New_Face( library, Datei, 0, &face );
+			error = FT_New_Face( library, Datei, faceIndex, &face );
 			if (error)
 			{
 				UseFont = false;
-				qDebug(QObject::tr("Font %1 is broken, discarding it").arg(Datei));
+				qDebug(QObject::tr("Font %1 is broken (no Face), discarding it").arg(Datei));
+				FT_Done_FreeType( library );
 				return false;
 			}
 			uniEM = static_cast<double>(face->units_per_EM);
@@ -214,15 +260,18 @@ class Foi_postscript : public Foi
 			setBestEncoding(face);
 			gindex = 0;
 			charcode = FT_Get_First_Char( face, &gindex );
+			int goodGlyph = 0;
+			int invalidGlyph = 0;
 			while ( gindex != 0 )
 			{
 				error = FT_Load_Glyph( face, gindex, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP );
 				if (error)
 				{
-					UseFont = false;
-					qDebug(QObject::tr("Font %1 is broken, discarding it").arg(Datei));
+					++invalidGlyph;
+					qDebug(QObject::tr("Font %1 has broken glyph %2 (charcode %3)").arg(Datei).arg(gindex).arg(charcode));
 					break;
 				}
+				++goodGlyph;
 				double ww = face->glyph->metrics.horiAdvance / uniEM;
 				if (face->glyph->format == FT_GLYPH_FORMAT_PLOTTER)
 					isStroked = true;
@@ -244,7 +293,9 @@ class Foi_postscript : public Foi
 				glyName = newName;
 				charcode = FT_Get_Next_Char( face, charcode, &gindex );
 			}
+			FT_Done_Face( face );
 			FT_Done_FreeType( library );
+			UseFont = goodGlyph > invalidGlyph;
 			HasMetrics=UseFont;
 			metricsread=UseFont;
 			return(HasMetrics);
@@ -265,35 +316,34 @@ class Foi_pfb : public Foi_postscript
 		Foi_pfb(QString scname, QString path, bool embedps) :
 		Foi_postscript(scname,path,embedps)
 		{
+			formatCode = PFB;
 		}
 
 		virtual bool EmbedFont(QString &str)
 		{
-			QFile f(Datei);
+			QByteArray bb;
+			RawData(bb);
 			QString tmp2 = "";
-			if (f.open(IO_ReadOnly))
+			if ((bb.size() > 2) &&  (bb[0] == char(0x80)) && (static_cast<int>(bb[1]) == 1))
 			{
-				QByteArray bb(f.size());
-				f.readBlock(bb.data(), f.size());
-				if ((bb[0] == char(0x80)) && (static_cast<int>(bb[1]) == 1))
+				QString tmp3="";
+				QString tmp4 = "";
+				uint posi,cxxc=0;
+				for (posi = 6; posi < bb.size(); ++posi)
 				{
-					QString tmp3="";
-					QString tmp4 = "";
-					uint posi,cxxc=0;
-					for (posi = 6; posi < bb.size(); ++posi)
-					{
-						if ((bb[posi] == char(0x80)) && (static_cast<int>(bb[posi+1]) == 2))
-							break;
-						str += bb[posi];
-					}
-					uint ulen;
+					if ((bb[posi] == char(0x80)) && (posi+1 < bb.size()) && (static_cast<int>(bb[posi+1]) == 2))
+						break;
+					str += bb[posi];
+				}
+				uint ulen;
+				if (posi+6 < bb.size()) {
 					ulen = bb[posi+2] & 0xff;
 					ulen |= (bb[posi+3] << 8) & 0xff00;
 					ulen |= (bb[posi+4] << 16) & 0xff0000;
 					ulen |= (bb[posi+5] << 24) & 0xff000000;
-					if (ulen > bb.size())
-						ulen = bb.size()-7;
 					posi += 6;
+					if (posi + ulen > bb.size())
+						ulen = bb.size() - posi - 1;
 					char linebuf[80];
 					cxxc=0;
 					for (uint j = 0; j < ulen; ++j)
@@ -317,24 +367,25 @@ class Foi_pfb : public Foi_postscript
 					linebuf[cxxc]=0;
 					str += linebuf;
 					str += "\n";
-					posi += 6;
-					for (uint j = posi; j < bb.size(); ++j)
-					{
-						if ((bb[j] == static_cast<char>(0x80)) && (static_cast<int>(bb[j+1]) == 3))
-							break;
-						if(bb[j]=='\r')
-							str+="\n";
-						else
-							str += bb[j];
-					}
-					str += "\n";
-					cxxc = 0;
 				}
-				f.close();
-				return(true);
+				posi += 6;
+				for (uint j = posi; j < bb.size(); ++j)
+				{
+					if ((bb[j] == static_cast<char>(0x80)) && (j+1 < bb.size()) && (static_cast<int>(bb[j+1]) == 3))
+						break;
+					if(bb[j]=='\r')
+						str+="\n";
+					else
+						str += bb[j];
+				}
+				str += "\n";
+				cxxc = 0;
+				return true;
+			}
+			else {
+				qDebug(QObject::tr("Font %1 can't be read, no embedding").arg(Datei));
+				return false;
 			}
-			else
-				return(false);
 		}
 };
 
@@ -350,14 +401,23 @@ class Foi_pfa : public Foi_postscript
 		Foi_pfa(QString scname, QString path, bool embedps) :
 		Foi_postscript(scname,path,embedps)
 		{
+			formatCode = PFA;
 		}
 		virtual bool EmbedFont(QString &str)
 		{
-			return loadText(Datei, &str);
+			QByteArray bb;
+			RawData(bb);
+			if (bb.size() > 2 && bb[0] == '%' && bb[1] == '!') {
+				// this is ok since bb will not contain '\0'
+				str.append(bb);
+				return true; 
+			}
+			return false;
 		}
 };
 
 
+
 /***************************************************************************/
 
 SCFonts::~SCFonts()
@@ -391,6 +451,9 @@ void SCFonts::AddScalableFonts(const QSt
 			QFileInfo fi(path+d[dc]);
 			if (!fi.exists())      // Sanity check for broken Symlinks
 				continue;
+			
+			qApp->processEvents();
+			
 			if (fi.isSymLink())
 			{
 				QFileInfo fi3(fi.readLink());
@@ -402,65 +465,190 @@ void SCFonts::AddScalableFonts(const QSt
 			else
 				pathfile = path+d[dc];
 			QFileInfo fi2(pathfile);
+			if (fi2.isDir()) {
+				if (DocName == "")
+					AddScalableFonts(pathfile);
+				continue;
+			}
 			QString ext = fi.extension(false).lower();
 			QString ext2 = fi2.extension(false).lower();
 			if ((ext != ext2) && (ext == "")) ext = ext2;
-			if ((ext == "pfa") || (ext == "pfb") || (ext == "ttf") || (ext == "otf"))
+			if ((ext == "ttc") || (ext == "dfont") || (ext == "pfa") || (ext == "pfb") || (ext == "ttf") || (ext == "otf"))
 			{
-				error = AddScalableFont(pathfile,library, DocName);
+				error = AddScalableFont(pathfile, library, DocName);
+				if (error)
+					qDebug(QObject::tr("Font %1 is broken, discarding it").arg(pathfile));
+			}
+#ifdef FT_MACINTOSH
+			else if (ext == "" && DocName == "") {
+				error = AddScalableFont(pathfile, library, DocName);
+				if (error) {
+					error = AddScalableFont(pathfile + "/rsrc",library, DocName);
+				}
 				if (error)
 					qDebug(QObject::tr("Font %1 is broken, discarding it").arg(pathfile));
 			}
+#endif				
 		}
 	}
 	FT_Done_FreeType( library );
 }
 
+/**
+ * tests magic words to determine the fontformat and preliminary fonttype
+ */
+void getFontFormat(FT_Face face, Foi::FontFormat & fmt, Foi::FontType & type)
+{
+	static const char* T42_HEAD      = "%!PS-TrueTypeFont";
+	static const char* T1_HEAD      = "%!FontType1";
+	static const char* T1_ADOBE_HEAD = "%!PS-AdobeFont-1";
+	static const char* PSFONT_ADOBE2_HEAD  = "%!PS-Adobe-2.0 Font";
+	static const char* PSFONT_ADOBE21_HEAD  = "%!PS-Adobe-2.1 Font";
+	static const char* PSFONT_ADOBE3_HEAD  = "%!PS-Adobe-3.0 Resource-Font";
+	static const int   NO_ERROR = 0;
+	
+	const FT_Stream fts = face->stream;
+	char buf[128];
+	
+	fmt = Foi::UNKNOWN_FORMAT;
+	type = Foi::UNKNOWN_TYPE;
+	if (FT_Stream_Seek(fts, 0L) == NO_ERROR && FT_Stream_Read(fts, reinterpret_cast<FT_Byte *>(buf), 128) == NO_ERROR) {
+		if(strncmp(buf,T42_HEAD,strlen(T42_HEAD)) == 0) {
+			fmt = Foi::TYPE42;
+			type = Foi::TTF;
+		}			
+		else if(strncmp(buf,T1_HEAD,strlen(T1_HEAD)) == 0 ||
+			    strncmp(buf,T1_ADOBE_HEAD,strlen(T1_ADOBE_HEAD)) == 0) {
+			fmt = Foi::PFA;
+			type = Foi::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) {
+			// Type2(CFF), Type0(Composite/CID), Type 3, Type 14 etc would end here
+			fmt = Foi::PFA;
+			type = Foi::UNKNOWN_TYPE;
+		}			
+		else if(buf[0] == '\200' && buf[1] == '\1')
+		{
+			fmt = Foi::PFB;
+			type = Foi::TYPE1;
+		}
+		else if(buf[0] == '\0' && buf[1] == '\1' 
+				&& buf[2] == '\0' && buf[3] == '\0')
+		{
+			fmt = Foi::SFNT;
+			type = Foi::TTF;
+		}
+		else if(strncmp(buf,"true",4) == 0)
+		{
+			fmt = Foi::SFNT;
+			type = Foi::TTF;
+		}
+		else if(strncmp(buf,"ttcf",4) == 0)
+		{
+			fmt = Foi::TTCF;
+			type = Foi::OTF;
+		}
+		else if(strncmp(buf,"OTTO",4) == 0)
+		{
+			fmt = Foi::SFNT;
+			type = Foi::OTF;
+		}
+		// missing: raw CFF
+	}
+}
+
+/**
+ * Checks face, which must be sfnt based, for the subtype.
+ * Possible values: TTF, CFF, OTF
+ */
+void getSFontType(FT_Face face, Foi::FontType & type) 
+{
+	if (FT_IS_SFNT(face)) {
+		FT_ULong ret = 0;
+		bool hasGlyph = ! FT_Load_Sfnt_Table(face, TTAG_glyf, 0, NULL,  &ret);
+		hasGlyph &= ret > 0;
+		bool hasCFF = ! FT_Load_Sfnt_Table(face, TTAG_CFF, 0, NULL,  &ret);
+		hasCFF &= ret > 0;
+		if (hasGlyph)
+			type = Foi::TTF;
+		else if (hasCFF)
+			type = Foi::OTF;
+		// TODO: CID or no
+	}
+} 
+
 // Load a single font into the library from the passed filename. Returns true on error.
 bool SCFonts::AddScalableFont(QString filename, FT_Library &library, QString DocName)
 {
-	FT_Face face = NULL;
+	Foi::FontFormat format;
+	Foi::FontType   type;
+	FT_Face         face = NULL;
+	
 	bool error = FT_New_Face( library, filename, 0, &face );
-	if (error)
+	if (error) {
+		if (face != NULL)
+			FT_Done_Face( face );
 		return true;
-	QString ts = QString(face->family_name) + " " + QString(face->style_name);
-	if (!find(ts))
+	}
+		
+	getFontFormat(face, format, type);
+	
+	if (format == Foi::UNKNOWN_FORMAT) {
+		qDebug(QObject::tr("Failed to load font %1 - font type unknown").arg(filename));
+		error = true;
+	}
+		
+	int faceindex=0; 
+
+	while (!error)
 	{
-		Foi *t=0;
-		// Yes, I realise we're checking the extension twice, but it's not
-		// a big cost, and nicer than passing it into this function.
-		//QFileInfo fi2(filename);
-		QString ext = QFileInfo(filename).extension(false).lower();
-		if(ext == "pfa")
-		{
-			t = new Foi_pfa(ts, filename, true);
-			t->typeCode = 1;
-		}
-		else if(ext == "pfb")
-		{
-			t = new Foi_pfb(ts, filename, true);
-			t->typeCode = 1;
-		}
-		else if(ext == "ttf")
-		{
-			t = new Foi_ttf(ts, filename, true);
-			t->typeCode = 2;
-		}
-		else if(ext == "otf")
-		{
-			t = new Foi_ttf(ts, filename, true);
-			t->typeCode = 3;
-		}
-		if(t)
-		{
-			t->cached_RealName = QString(FT_Get_Postscript_Name(face));
+		QString ts = QString(face->family_name) + " " + QString(face->style_name);
+		Foi *t = find(ts);
+		if (!t)
+		{
+			switch (format) {
+			case Foi::PFA:
+				t = new Foi_pfa(ts, filename, true);
+				break;
+			case Foi::PFB:				
+				t = new Foi_pfb(ts, filename, true);
+				break;
+			case Foi::SFNT:
+				t = new Foi_ttf(ts, filename, true);
+				getSFontType(face, t->typeCode);
+				if (t->typeCode == Foi::OTF) {
+					t->isOTF = true;
+					t->Subset = true;
+				}
+				break;
+			case Foi::TTCF:
+				t = new Foi_ttf(ts, filename, true);
+				t->formatCode = Foi::TTCF;
+				t->typeCode = Foi::TTF;
+				//getSFontType(face, t->typeCode);
+				if (t->typeCode == Foi::OTF) {
+					t->isOTF = true;
+					t->Subset = true;
+				}
+				break;
+			case Foi::TYPE42:
+				t = new Foi_ttf(ts, filename, true);
+				getSFontType(face, t->typeCode);
+				if (t->typeCode == Foi::OTF) {
+					t->isOTF = true;
+					t->Subset = true;
+				}
+				break;
+			}
+			const char* psName = FT_Get_Postscript_Name(face);
+			if (psName)
+				t->cached_RealName = QString(psName);
+			else
+				t->cached_RealName = ts;
 			t->Font = qApp->font();
 			t->Font.setPointSize(qApp->font().pointSize());
-			if (ext == "otf")
-			{
-				t->isOTF = true;
-				t->Subset = true;
-			}
 			insert(ts,t);
 			t->EmbedPS = true;
 			t->UseFont = true;
@@ -469,9 +657,51 @@ bool SCFonts::AddScalableFont(QString fi
 			t->CharWidth[9] = 1;
 			t->Family = QString(face->family_name);
 			t->Effect = QString(face->style_name);
+			t->faceIndex = faceindex;
 			t->PrivateFont = DocName;
+			setBestEncoding(face); //AV
+			switch (face->charmap? face->charmap->encoding : -1)
+			{
+				case	 FT_ENCODING_ADOBE_STANDARD: 
+					t->FontEnc = QString("StandardEncoding");
+					break;
+				case	 FT_ENCODING_APPLE_ROMAN: 
+					t->FontEnc = QString("MacRomanEncoding");
+					break;
+				case	 FT_ENCODING_ADOBE_EXPERT: 
+					t->FontEnc = QString("MacExpertEncoding");
+					break;
+				case	 FT_ENCODING_ADOBE_LATIN_1: 
+					t->FontEnc = QString("WinAnsiEncoding");
+					break;
+				case	 FT_ENCODING_UNICODE: 
+					t->FontEnc = QString("Unicode");
+					break;
+				default:
+					t->FontEnc = QString();
+			}
+			qDebug(QObject::tr("Font %1 loaded from %2(%3)").arg(t->cached_RealName).arg(filename).arg(faceindex+1));
+
+/*/debug
+			QByteArray bb;
+			t->RawData(bb);
+			QFile dump(QString("/tmp/fonts/%1-%2").arg(ts).arg(psName));
+			dump.open(IO_WriteOnly);
+			QDataStream os(&dump);
+			os.writeRawBytes(bb.data(), bb.size());
+			dump.close();
+/*/
+			FT_Done_Face(face);
+			++faceindex;
+			error = FT_New_Face( library, filename, faceindex, &face );
+		}
+		else {
+			qDebug(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
+			error = true;
 		}
-	}
+	} //while
+	
 	if (face != 0)
 		FT_Done_Face( face );
 	return false;
@@ -513,6 +743,7 @@ void SCFonts::AddFontconfigFonts()
         FcChar8 *file = NULL;
         if (FcPatternGetString (fs->fonts[i], FC_FILE, 0, &file) == FcResultMatch)
         {
+			qDebug(QObject::tr("loading Font %1 (found using fontconfig)").arg(QString((char*)file)));
             error = AddScalableFont(QString((char*)file), library, "");
             if (error)
                 qDebug(QObject::tr("Font %1 (found using fontconfig) is broken, discarding it").arg(QString((char*)file)));
@@ -524,6 +755,7 @@ void SCFonts::AddFontconfigFonts()
 }
 
 #else
+#ifndef QT_MAC
 
 void SCFonts::AddXFontPath()
 {
@@ -589,6 +821,7 @@ void SCFonts::AddXFontServerPath()
 	}
 }
 #endif
+#endif
 
 /* Add an extra path to the X-Server's Fontpath
  * allowing a user to have extra Fonts installed
@@ -617,14 +850,27 @@ void SCFonts::GetFonts(QString pf)
 {
 	FontPath.clear();
 	AddUserPath(pf);
-#ifdef HAVE_FONTCONFIG
+// if fontconfig is there, it does all the work
+#if HAVE_FONTCONFIG
 	for(QStrListIterator fpi(FontPath) ; fpi.current() ; ++fpi)
 		AddScalableFonts(fpi.current());
 	AddFontconfigFonts();
 #else
+// if FreeType thinks we are on Mac, let it search the default paths
+#if FT_MACINTOSH
+	AddScalableFonts(QDir::homeDirPath() + "/Library/Fonts/");
+	AddScalableFonts("/Library/Fonts/");
+	AddScalableFonts("/Network/Library/Fonts/");
+	AddScalableFonts("/System/Library/Fonts/");
+#endif
+// on X11 look there:
+#ifdef Q_WS_X11
 	AddXFontPath();
 	AddXFontServerPath();
-	for(QStrListIterator fpi(FontPath) ; fpi.current() ; ++fpi)
+#endif
+// add user and X11 fonts:
+	for(QStrListIterator fpi(FontPath) ; fpi.current() ; ++fpi) {
 		AddScalableFonts(fpi.current());
+	}
 #endif
 }
morefonts5.diff (68,950 bytes)   

plinnell

2005-05-29 09:04

viewer   ~0004830

This crash is triggered adding fonts to $HOME/.fonts

Font Univers-ExtraBlackObl loaded from /home/peter/.fonts/UniEBO49.pfa(1)
Font /home/peter/.fonts/UniEBO49.pfb(1) is duplicate of /home/peter/.fonts/UniEBO49.pfa(1)

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1089528960 (LWP 6823)]
0x409a5202 in parse_encoding () from /usr/lib/libfreetype.so.6
(gdb) bt
#0 0x409a5202 in parse_encoding () from /usr/lib/libfreetype.so.6
0000001 0x409a574f in parse_dict () from /usr/lib/libfreetype.so.6
0000002 0x409a5a66 in T1_Face_Init () from /usr/lib/libfreetype.so.6
0000003 0x4096c71f in open_face () from /usr/lib/libfreetype.so.6
0000004 0x4096cef6 in FT_Open_Face () from /usr/lib/libfreetype.so.6
0000005 0x4096dc38 in FT_New_Face () from /usr/lib/libfreetype.so.6
0000006 0xbfffd790 in ?? ()
0000007 0x00000000 in ?? ()
0000008 0xbfffd874 in ?? ()
0000009 0x00000004 in ?? ()
0000010 0xbfffdbb0 in ?? ()
0000011 0xbfffd7b8 in ?? ()
0000012 0x087ba210 in ?? ()
0000013 0xbfffd8b0 in ?? ()
0000014 0xbfffd7c0 in ?? ()
0000015 0x00000018 in ?? ()
0000016 0x40919f40 in __JCR_LIST__ () from /usr/lib/qt3/lib/libqt-mt.so.3
0000017 0x08b0c2c8 in ?? ()
0000018 0xbfffd8f0 in ?? ()
0000019 0xbfffd898 in ?? ()
0000020 0x0830d964 in SCFonts::AddScalableFont (this=0x0, filename=Cannot access memory at address 0x2
)
    at scfonts.cpp:589
Previous frame inner to this frame (corrupt stack?

plinnell

2005-05-29 09:08

viewer   ~0004831

with same fonts in ./fonts. instant death on startup. Note this is a Suse 9.1 system with ft 2.1.7


Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1089528960 (LWP 8193)]
0x409a5202 in parse_encoding () from /usr/lib/libfreetype.so.6
(gdb)

plinnell

2005-05-29 10:40

viewer   ~0004833

OK, I think I have figured out the crashes. It seems FT error checking is being disabled by the patch or not working with Ft 2.1.7.

Testing the same fonts (which are definitely borken) on my home system without the patch works fine e.g. Scribus quietly drops them on loading.

Contining to test.

plinnell

2005-05-31 18:44

viewer   ~0004851

needed to be added is a check for FT 2.1.9+

Issue History

Date Modified Username Field Change
2005-03-25 21:59 avox New Issue
2005-03-25 21:59 avox File Added: morefonts.diff
2005-04-06 14:36 avox File Added: morefonts2.diff
2005-04-06 14:44 avox Note Added: 0004097
2005-04-06 14:45 avox File Added: glyphnames.txt.q
2005-04-06 18:40 cbradney Note Added: 0004099
2005-04-06 19:05 avox Note Added: 0004100
2005-04-06 19:06 avox Note Edited: 0004100
2005-04-06 19:21 avox Note Edited: 0004100
2005-04-06 20:01 cbradney Note Added: 0004102
2005-04-06 23:53 avox File Added: morefonts3.diff
2005-04-06 23:58 avox Note Added: 0004105
2005-05-26 20:14 avox File Added: morefonts4.diff
2005-05-26 20:15 avox Note Added: 0004793
2005-05-26 20:25 avox File Deleted: morefonts.diff
2005-05-26 20:25 avox File Deleted: morefonts2.diff
2005-05-26 20:25 avox File Deleted: glyphnames.txt.q
2005-05-26 20:25 avox File Deleted: morefonts3.diff
2005-05-26 20:25 avox Status new => assigned
2005-05-26 20:25 avox Assigned To => fschmid
2005-05-27 05:53 mhanski Relationship added related to 0002015
2005-05-27 20:55 cbradney File Deleted: morefonts4.diff
2005-05-27 20:55 cbradney File Added: morefonts4.diff
2005-05-27 20:56 cbradney Note Added: 0004813
2005-05-27 23:20 avox File Added: morefonts5.diff
2005-05-28 16:51 cbradney Assigned To fschmid => cbradney
2005-05-29 09:04 plinnell Note Added: 0004830
2005-05-29 09:08 plinnell Note Added: 0004831
2005-05-29 10:40 plinnell Note Added: 0004833
2005-05-29 18:19 cbradney Status assigned => resolved
2005-05-29 18:19 cbradney Fixed in Version => 1.3.0cvs
2005-05-29 18:19 cbradney Resolution open => fixed
2005-05-31 18:44 plinnell Note Added: 0004851
2005-06-01 17:42 cbradney File Deleted: morefonts4.diff
2005-06-01 17:42 cbradney Status resolved => closed