Back to index

scribus-ng  1.3.4.dfsg+svn20071115
scface_ttf.cpp
Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 
00008 #include <qfile.h>
00009 #include <qstring.h>
00010 #include <qobject.h>
00011 
00012 #include <sys/types.h>
00013 
00014 #include "fonts/scface_ttf.h"
00015 #include "fonts/scfontmetrics.h"
00016 #include "util.h"
00017 #include "scconfig.h"
00018 
00019 
00020 
00021 namespace {
00022 uint word(QByteArray const & bb, uint pos) 
00023 {
00024        unsigned char * pp = reinterpret_cast<unsigned char*>(bb.data()) + pos;
00025        return pp[0] << 24 | pp[1] << 16 | pp[2] << 8 | pp[3];
00026 }
00027 uint word16(QByteArray const & bb, uint pos) 
00028 {
00029        unsigned char * pp = reinterpret_cast<unsigned char*>(bb.data()) + pos;
00030        return pp[0] << 8 | pp[1];
00031 }
00032 QString tag(QByteArray const & bb, uint pos)
00033 {
00034        char buf[5] = "1234";
00035        buf[0] = bb.data()[pos];
00036        buf[1] = bb.data()[pos+1];
00037        buf[2] = bb.data()[pos+2];
00038        buf[3] = bb.data()[pos+3];
00039        return buf;
00040 }
00041 bool copy(QByteArray & dst, uint to, QByteArray & src, uint from, uint len) 
00042 {
00043        if (!dst.data())
00044               return false;
00045        if (!src.data())
00046               return false;
00047        if (to + len > dst.size())
00048               return false;
00049        if (from + len > src.size())
00050               return false;
00051        
00052        memcpy(dst.data() + to, src.data() + from, len);
00053        return true;
00054 }
00055 } //namespace
00056 
00057 
00058 void ScFace_ttf::RawData(QByteArray & bb) const {
00059        if (formatCode == ScFace::TTCF) {
00060               QByteArray coll;
00061               FtFace::RawData(coll);
00062               // access table for faceIndex
00063               if (faceIndex >= static_cast<int>(word(coll, 8)))
00064               {
00065                      bb.resize(0);
00066                      return;
00067               }
00068               static const uint OFFSET_TABLE_LEN = 12;
00069               static const uint   TDIR_ENTRY_LEN = 16;
00070               uint faceOffset = word(coll, 12 + 4 * faceIndex);
00071               uint nTables    = word16(coll, faceOffset + 4);
00072               sDebug(QObject::tr("extracting face %1 from font %2 (offset=%3, nTables=%4)").arg(faceIndex).arg(fontFile).arg(faceOffset).arg(nTables));
00073               uint headerLength = OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * nTables;
00074               uint tableLengths = 0;
00075               // sum table lengths incl padding
00076               for (uint i=0; i < nTables; ++i)
00077               {
00078                      tableLengths += word(coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12);
00079                      tableLengths = (tableLengths+3) & ~3;
00080               }
00081               bb.resize(headerLength + tableLengths);
00082               if (! bb.data())
00083                      return;
00084               // write header
00085               sDebug(QObject::tr("memcpy header: %1 %2 %3").arg(0).arg(faceOffset).arg(headerLength));
00086               if (!copy(bb, 0, coll, faceOffset, headerLength))
00087                      return;
00088 
00089               uint pos = headerLength;
00090               for (uint i=0; i < nTables; ++i)
00091               {
00092                      uint tableSize  = word(coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12);
00093                      uint tableStart = word(coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 8);
00094                      sDebug(QObject::tr("table '%1'").arg(tag(coll, tableStart)));
00095                      sDebug(QObject::tr("memcpy table: %1 %2 %3").arg(pos).arg(tableStart).arg(tableSize));
00096                      if (!copy(bb, pos, coll, tableStart, tableSize)) break;
00097                      // write new offset to table entry
00098                      sDebug(QObject::tr("memcpy offset: %1 %2 %3").arg(OFFSET_TABLE_LEN + TDIR_ENTRY_LEN*i + 8).arg(pos).arg(4));
00099                      memcpy(bb.data() + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 8, &pos, 4);
00100                      pos += tableSize;
00101                      // pad
00102                      while ((pos & 3) != 0)
00103                             bb.data()[pos++] = '\0';
00104               }
00105        }      
00106        else if (formatCode == ScFace::TYPE42) {
00107               FtFace::RawData(bb);
00108        }
00109        else {
00110               FtFace::RawData(bb);
00111        }
00112 }
00113 
00114 bool ScFace_ttf::EmbedFont(QString &str) const
00115 {
00116        if (formatCode == ScFace::TYPE42) {
00117               //easy:
00118               QByteArray bb;
00119               FtFace::RawData(bb);
00120               str += bb;
00121               return true;
00122        }
00123        QString tmp4;
00124        QString tmp2 = "";
00125        QString tmp3 = "";
00126        int counter = 0;
00127        char *buf[50];
00128        FT_ULong  charcode;
00129        FT_UInt   gindex;
00130        FT_Face face = ftFace();
00131        if (!face) {
00132               return false;
00133        }
00134        const FT_Stream fts = face->stream;
00135        if (ftIOFunc(fts, 0L, NULL, 0)) {
00136               return(false);
00137        }
00138        str+="%!PS-TrueTypeFont\n";
00139        str+="11 dict begin\n";
00140        str+="/FontName /" + psName + " def\n";
00141        str+="/Encoding /ISOLatin1Encoding where {pop ISOLatin1Encoding} {StandardEncoding} ifelse def\n";
00142        str+="/PaintType 0 def\n/FontMatrix [1 0 0 1 0 0] def\n";
00143        str+="/FontBBox ["+FontBBox+"] def\n";
00144        str+="/FontType 42 def\n";
00145        str+="/FontInfo 8 dict dup begin\n";
00146        str+="/FamilyName (" + psName + ") def\n";
00147        str+="end readonly def\n";
00148        unsigned char *tmp = new unsigned char[65535];
00149        int length;
00150        char linebuf[80];
00151        str += "/sfnts [";
00152        int poso=0;
00153        do {
00154               int posi=0;
00155               length= fts->size - fts->pos;
00156               if (length > 65534) {
00157                      length = 65534;
00158               }
00159               if (!ftIOFunc(fts, 0L, tmp, length))
00160               {
00161                      str+="\n<\n";
00162                      for (int j = 0; j < length; j++)
00163                      {
00164                             unsigned char u=tmp[posi];
00165                             linebuf[poso]=((u >> 4) & 15) + '0';
00166                             if(u>0x9f) linebuf[poso]+='a'-':';
00167                             ++poso;
00168                             u&=15; linebuf[poso]=u + '0';
00169                             if(u>0x9) linebuf[poso]+='a'-':';
00170                             ++posi;
00171                             ++poso;
00172                             if (poso > 70)
00173                             {
00174                                    linebuf[poso++]='\n';
00175                                    linebuf[poso++]=0;
00176                                    str += linebuf;
00177                                    poso = 0;
00178                             }
00179                      }
00180                      linebuf[poso++]=0;
00181                      str += linebuf;
00182                      poso = 0;
00183                      str += "00\n>";
00184               }
00185               else {
00186                      sDebug(QObject::tr("Font %1 is broken (read stream), no embedding").arg(fontFile));
00187                      str += "\n] def\n";
00188                      status = QMAX(status,ScFace::BROKENGLYPHS);
00189                      return false;
00190               }
00191        } while (length==65534);
00192        
00193        str += "\n] def\n";
00194        delete[] tmp;
00195        gindex = 0;
00196        charcode = FT_Get_First_Char(face, &gindex );
00197        while (gindex != 0)
00198        {
00199               FT_Get_Glyph_Name(face, gindex, buf, 50);
00200               tmp2 += "/"+QString(reinterpret_cast<char*>(buf))+" "+tmp3.setNum(gindex)+" def\n";
00201                charcode = FT_Get_Next_Char(face, charcode, &gindex );
00202               counter++;
00203        }
00204        tmp4.setNum(counter);
00205        str += "/CharStrings " + tmp4 + " dict dup begin\n"+tmp2;
00206        str += "end readonly def\n";
00207        str += "FontName currentdict end definefont pop\n";
00208        return(true);
00209 }
00210