View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0001816 | Scribus | Fonts | public | 2005-03-25 21:59 | 2005-06-01 17:42 |
Reporter | avox | Assigned To | cbradney | ||
Priority | normal | Severity | feature | Reproducibility | always |
Status | closed | Resolution | fixed | ||
Product Version | 1.3 | ||||
Fixed in Version | 1.3.0cvs | ||||
Summary | 0001816: Fonts are only recognized in 'pfa', 'pfb', 'ttf' and 'otf' files. | ||||
Description | Freetype 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. | ||||
Tags | No tags attached. | ||||
Patch | |||||
|
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 |
|
Why does it need this text file? |
|
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 |
|
We need confirmation on licensing of the glyph list in its current format, otherwise we need something from unicode.org I assume. |
|
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 |
|
Updated the patch with a version against current CVS |
|
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 } |
|
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? |
|
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) |
|
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. |
|
needed to be added is a check for FT 2.1.9+ |
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 |
|
Note Added: 0004830 | |
2005-05-29 09:08 |
|
Note Added: 0004831 | |
2005-05-29 10:40 |
|
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 |
|
Note Added: 0004851 | |
2005-06-01 17:42 | cbradney | File Deleted: morefonts4.diff | |
2005-06-01 17:42 | cbradney | Status | resolved => closed |