Back to index

tetex-bin  3.0
Public Member Functions | Static Public Member Functions | Protected Member Functions | Static Protected Member Functions | Protected Attributes | Private Member Functions | Private Attributes
FoFiTrueType Class Reference

#include <FoFiTrueType.h>

Inheritance diagram for FoFiTrueType:
Inheritance graph
[legend]
Collaboration diagram for FoFiTrueType:
Collaboration graph
[legend]

List of all members.

Public Member Functions

virtual ~FoFiTrueType ()
int getNumCmaps ()
int getCmapPlatform (int i)
int getCmapEncoding (int i)
int findCmap (int platform, int encoding)
Gushort mapCodeToGID (int i, int c)
int mapNameToGID (char *name)
int getEmbeddingRights ()
void convertToType42 (char *psName, char **encoding, Gushort *codeToGID, FoFiOutputFunc outputFunc, void *outputStream)
void convertToCIDType2 (char *psName, Gushort *cidMap, int nCIDs, FoFiOutputFunc outputFunc, void *outputStream)
void convertToType0 (char *psName, Gushort *cidMap, int nCIDs, FoFiOutputFunc outputFunc, void *outputStream)
void writeTTF (FoFiOutputFunc outputFunc, void *outputStream)

Static Public Member Functions

static FoFiTrueTypemake (char *fileA, int lenA)
static FoFiTrueTypeload (char *fileName)

Protected Member Functions

int getS8 (int pos, GBool *ok)
int getU8 (int pos, GBool *ok)
int getS16BE (int pos, GBool *ok)
int getU16BE (int pos, GBool *ok)
int getS32BE (int pos, GBool *ok)
Guint getU32BE (int pos, GBool *ok)
Guint getUVarBE (int pos, int size, GBool *ok)
GBool checkRegion (int pos, int size)

Static Protected Member Functions

static char * readFile (char *fileName, int *fileLen)

Protected Attributes

GucharfileData
Gucharfile
int len
GBool freeFileData

Private Member Functions

 FoFiTrueType (char *fileA, int lenA, GBool freeFileDataA)
void cvtEncoding (char **encoding, FoFiOutputFunc outputFunc, void *outputStream)
void cvtCharStrings (char **encoding, Gushort *codeToGID, FoFiOutputFunc outputFunc, void *outputStream)
void cvtSfnts (FoFiOutputFunc outputFunc, void *outputStream, GString *name)
void dumpString (Guchar *s, int length, FoFiOutputFunc outputFunc, void *outputStream)
Guint computeTableChecksum (Guchar *data, int length)
void parse ()
void readPostTable ()
int seekTable (char *tag)

Private Attributes

TrueTypeTabletables
int nTables
TrueTypeCmapcmaps
int nCmaps
int nGlyphs
int locaFmt
int bbox [4]
GHashnameToGID
GBool parsedOk

Detailed Description

Definition at line 29 of file FoFiTrueType.h.


Constructor & Destructor Documentation

Definition at line 276 of file FoFiTrueType.cc.

                            {
  gfree(tables);
  gfree(cmaps);
  delete nameToGID;
}

Here is the call graph for this function:

FoFiTrueType::FoFiTrueType ( char *  fileA,
int  lenA,
GBool  freeFileDataA 
) [private]

Definition at line 263 of file FoFiTrueType.cc.

                                                                    :
  FoFiBase(fileA, lenA, freeFileDataA)
{
  tables = NULL;
  nTables = 0;
  cmaps = NULL;
  nCmaps = 0;
  nameToGID = NULL;
  parsedOk = gFalse;

  parse();
}

Here is the call graph for this function:

Here is the caller graph for this function:


Member Function Documentation

GBool FoFiBase::checkRegion ( int  pos,
int  size 
) [protected, inherited]

Definition at line 152 of file FoFiBase.cc.

                                             {
  return pos >= 0 &&
         pos + size >= pos &&
         pos + size <= len;
}

Here is the caller graph for this function:

Guint FoFiTrueType::computeTableChecksum ( Guchar data,
int  length 
) [private]

Definition at line 1236 of file FoFiTrueType.cc.

                                                                 {
  Guint checksum, word;
  int i;

  checksum = 0;
  for (i = 0; i+3 < length; i += 4) {
    word = ((data[i  ] & 0xff) << 24) +
           ((data[i+1] & 0xff) << 16) +
           ((data[i+2] & 0xff) <<  8) +
            (data[i+3] & 0xff);
    checksum += word;
  }
  if (length & 3) {
    word = 0;
    i = length & ~3;
    switch (length & 3) {
    case 3:
      word |= (data[i+2] & 0xff) <<  8;
    case 2:
      word |= (data[i+1] & 0xff) << 16;
    case 1:
      word |= (data[i  ] & 0xff) << 24;
      break;
    }
    checksum += word;
  }
  return checksum;
}

Here is the caller graph for this function:

void FoFiTrueType::convertToCIDType2 ( char *  psName,
Gushort cidMap,
int  nCIDs,
FoFiOutputFunc  outputFunc,
void outputStream 
)

Definition at line 441 of file FoFiTrueType.cc.

                                                     {
  char buf[512];
  Gushort cid;
  GBool ok;
  int i, j, k;

  // write the header
  ok = gTrue;
  sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0);
  (*outputFunc)(outputStream, buf, strlen(buf));

  // begin the font dictionary
  (*outputFunc)(outputStream, "20 dict begin\n", 14);
  (*outputFunc)(outputStream, "/CIDFontName /", 14);
  (*outputFunc)(outputStream, psName, strlen(psName));
  (*outputFunc)(outputStream, " def\n", 5);
  (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
  (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
  (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
  (*outputFunc)(outputStream, "  /Registry (Adobe) def\n", 24);
  (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
  (*outputFunc)(outputStream, "  /Supplement 0 def\n", 20);
  (*outputFunc)(outputStream, "  end def\n", 10);
  (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
  if (cidMap) {
    sprintf(buf, "/CIDCount %d def\n", nCIDs);
    (*outputFunc)(outputStream, buf, strlen(buf));
    if (nCIDs > 32767) {
      (*outputFunc)(outputStream, "/CIDMap [", 9);
      for (i = 0; i < nCIDs; i += 32768 - 16) {
       (*outputFunc)(outputStream, "<\n", 2);
       for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
         (*outputFunc)(outputStream, "  ", 2);
         for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
           cid = cidMap[i+j+k];
           sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
           (*outputFunc)(outputStream, buf, strlen(buf));
         }
         (*outputFunc)(outputStream, "\n", 1);
       }
       (*outputFunc)(outputStream, "  >", 3);
      }
      (*outputFunc)(outputStream, "\n", 1);
      (*outputFunc)(outputStream, "] def\n", 6);
    } else {
      (*outputFunc)(outputStream, "/CIDMap <\n", 10);
      for (i = 0; i < nCIDs; i += 16) {
       (*outputFunc)(outputStream, "  ", 2);
       for (j = 0; j < 16 && i+j < nCIDs; ++j) {
         cid = cidMap[i+j];
         sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
         (*outputFunc)(outputStream, buf, strlen(buf));
       }
       (*outputFunc)(outputStream, "\n", 1);
      }
      (*outputFunc)(outputStream, "> def\n", 6);
    }
  } else {
    // direct mapping - just fill the string(s) with s[i]=i
    sprintf(buf, "/CIDCount %d def\n", nGlyphs);
    (*outputFunc)(outputStream, buf, strlen(buf));
    if (nGlyphs > 32767) {
      (*outputFunc)(outputStream, "/CIDMap [\n", 10);
      for (i = 0; i < nGlyphs; i += 32767) {
       j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
       sprintf(buf, "  %d string 0 1 %d {\n", 2 * j, j - 1);
       (*outputFunc)(outputStream, buf, strlen(buf));
       sprintf(buf, "    2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
       (*outputFunc)(outputStream, buf, strlen(buf));
       sprintf(buf, "    1 index exch dup 2 mul 1 add exch %d add"
              " 255 and put\n", i);
       (*outputFunc)(outputStream, buf, strlen(buf));
       (*outputFunc)(outputStream, "  } for\n", 8);
      }
      (*outputFunc)(outputStream, "] def\n", 6);
    } else {
      sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
      (*outputFunc)(outputStream, buf, strlen(buf));
      sprintf(buf, "  0 1 %d {\n", nGlyphs - 1);
      (*outputFunc)(outputStream, buf, strlen(buf));
      (*outputFunc)(outputStream,
                  "    2 copy dup 2 mul exch -8 bitshift put\n", 42);
      (*outputFunc)(outputStream,
                  "    1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
      (*outputFunc)(outputStream, "  } for\n", 8);
      (*outputFunc)(outputStream, "def\n", 4);
    }
  }
  (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
  sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
         bbox[0], bbox[1], bbox[2], bbox[3]);
  (*outputFunc)(outputStream, buf, strlen(buf));
  (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
  (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
  (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
  (*outputFunc)(outputStream, "  /.notdef 0 def\n", 17);
  (*outputFunc)(outputStream, "  end readonly def\n", 19);

  // write the guts of the dictionary
  cvtSfnts(outputFunc, outputStream, NULL);

  // end the dictionary and define the font
  (*outputFunc)(outputStream,
              "CIDFontName currentdict end /CIDFont defineresource pop\n",
              56);
}

Here is the call graph for this function:

void FoFiTrueType::convertToType0 ( char *  psName,
Gushort cidMap,
int  nCIDs,
FoFiOutputFunc  outputFunc,
void outputStream 
)

Definition at line 551 of file FoFiTrueType.cc.

                                                  {
  char buf[512];
  GString *sfntsName;
  int n, i, j;

  // write the Type 42 sfnts array
  sfntsName = (new GString(psName))->append("_sfnts");
  cvtSfnts(outputFunc, outputStream, sfntsName);
  delete sfntsName;

  // write the descendant Type 42 fonts
  n = cidMap ? nCIDs : nGlyphs;
  for (i = 0; i < n; i += 256) {
    (*outputFunc)(outputStream, "10 dict begin\n", 14);
    (*outputFunc)(outputStream, "/FontName /", 11);
    (*outputFunc)(outputStream, psName, strlen(psName));
    sprintf(buf, "_%02x def\n", i >> 8);
    (*outputFunc)(outputStream, buf, strlen(buf));
    (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
    sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
           bbox[0], bbox[1], bbox[2], bbox[3]);
    (*outputFunc)(outputStream, buf, strlen(buf));
    (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
    (*outputFunc)(outputStream, "/sfnts ", 7);
    (*outputFunc)(outputStream, psName, strlen(psName));
    (*outputFunc)(outputStream, "_sfnts def\n", 11);
    (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
    for (j = 0; j < 256 && i+j < n; ++j) {
      sprintf(buf, "dup %d /c%02x put\n", j, j);
      (*outputFunc)(outputStream, buf, strlen(buf));
    }
    (*outputFunc)(outputStream, "readonly def\n", 13);
    (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
    (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
    for (j = 0; j < 256 && i+j < n; ++j) {
      sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
      (*outputFunc)(outputStream, buf, strlen(buf));
    }
    (*outputFunc)(outputStream, "end readonly def\n", 17);
    (*outputFunc)(outputStream,
                "FontName currentdict end definefont pop\n", 40);
  }

  // write the Type 0 parent font
  (*outputFunc)(outputStream, "16 dict begin\n", 14);
  (*outputFunc)(outputStream, "/FontName /", 11);
  (*outputFunc)(outputStream, psName, strlen(psName));
  (*outputFunc)(outputStream, " def\n", 5);
  (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
  (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
  (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
  (*outputFunc)(outputStream, "/Encoding [\n", 12);
  for (i = 0; i < n; i += 256) {
    sprintf(buf, "%d\n", i >> 8);
    (*outputFunc)(outputStream, buf, strlen(buf));
  }
  (*outputFunc)(outputStream, "] def\n", 6);
  (*outputFunc)(outputStream, "/FDepVector [\n", 14);
  for (i = 0; i < n; i += 256) {
    (*outputFunc)(outputStream, "/", 1);
    (*outputFunc)(outputStream, psName, strlen(psName));
    sprintf(buf, "_%02x findfont\n", i >> 8);
    (*outputFunc)(outputStream, buf, strlen(buf));
  }
  (*outputFunc)(outputStream, "] def\n", 6);
  (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
}

Here is the call graph for this function:

void FoFiTrueType::convertToType42 ( char *  psName,
char **  encoding,
Gushort codeToGID,
FoFiOutputFunc  outputFunc,
void outputStream 
)

Definition at line 408 of file FoFiTrueType.cc.

                                                   {
  char buf[512];
  GBool ok;

  // write the header
  ok = gTrue;
  sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0);
  (*outputFunc)(outputStream, buf, strlen(buf));

  // begin the font dictionary
  (*outputFunc)(outputStream, "10 dict begin\n", 14);
  (*outputFunc)(outputStream, "/FontName /", 11);
  (*outputFunc)(outputStream, psName, strlen(psName));
  (*outputFunc)(outputStream, " def\n", 5);
  (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
  (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
  sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
         bbox[0], bbox[1], bbox[2], bbox[3]);
  (*outputFunc)(outputStream, buf, strlen(buf));
  (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);

  // write the guts of the dictionary
  cvtEncoding(encoding, outputFunc, outputStream);
  cvtCharStrings(encoding, codeToGID, outputFunc, outputStream);
  cvtSfnts(outputFunc, outputStream, NULL);

  // end the dictionary and define the font
  (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
}

Here is the call graph for this function:

void FoFiTrueType::cvtCharStrings ( char **  encoding,
Gushort codeToGID,
FoFiOutputFunc  outputFunc,
void outputStream 
) [private]

Definition at line 926 of file FoFiTrueType.cc.

                                                  {
  char *name;
  char buf[64], buf2[16];
  int i, k;

  // always define '.notdef'
  (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
  (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);

  // if there's no 'cmap' table, punt
  if (nCmaps == 0) {
    goto err;
  }

  // map char name to glyph index:
  // 1. use encoding to map name to char code
  // 2. use codeToGID to map char code to glyph index
  // N.B. We do this in reverse order because font subsets can have
  //      weird encodings that use the same character name twice, and
  //      the first definition is probably the one we want.
  k = 0; // make gcc happy
  for (i = 255; i >= 0; --i) {
    if (encoding) {
      name = encoding[i];
    } else {
      sprintf(buf2, "c%02x", i);
      name = buf2;
    }
    if (name && strcmp(name, ".notdef")) {
      k = codeToGID[i];
      // note: Distiller (maybe Adobe's PS interpreter in general)
      // doesn't like TrueType fonts that have CharStrings entries
      // which point to nonexistent glyphs, hence the (k < nGlyphs)
      // test
      if (k > 0 && k < nGlyphs) {
       (*outputFunc)(outputStream, "/", 1);
       (*outputFunc)(outputStream, name, strlen(name));
       sprintf(buf, " %d def\n", k);
       (*outputFunc)(outputStream, buf, strlen(buf));
      }
    }
  }

 err:
  (*outputFunc)(outputStream, "end readonly def\n", 17);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void FoFiTrueType::cvtEncoding ( char **  encoding,
FoFiOutputFunc  outputFunc,
void outputStream 
) [private]

Definition at line 899 of file FoFiTrueType.cc.

                                                {
  char *name;
  char buf[64];
  int i;

  (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
  if (encoding) {
    for (i = 0; i < 256; ++i) {
      if (!(name = encoding[i])) {
       name = ".notdef";
      }
      sprintf(buf, "dup %d /", i);
      (*outputFunc)(outputStream, buf, strlen(buf));
      (*outputFunc)(outputStream, name, strlen(name));
      (*outputFunc)(outputStream, " put\n", 5);
    }
  } else {
    for (i = 0; i < 256; ++i) {
      sprintf(buf, "dup %d /c%02x put\n", i, i);
      (*outputFunc)(outputStream, buf, strlen(buf));
    }
  }
  (*outputFunc)(outputStream, "readonly def\n", 13);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void FoFiTrueType::cvtSfnts ( FoFiOutputFunc  outputFunc,
void outputStream,
GString name 
) [private]

Definition at line 976 of file FoFiTrueType.cc.

                                                            {
  Guchar headData[54];
  TrueTypeLoca *locaTable;
  Guchar *locaData;
  TrueTypeTable newTables[nT42Tables];
  Guchar tableDir[12 + nT42Tables*16];
  GBool ok;
  Guint checksum;
  int nNewTables;
  int length, pos, glyfPos, i, j, k;

  // construct the 'head' table, zero out the font checksum
  i = seekTable("head");
  pos = tables[i].offset;
  if (!checkRegion(pos, 54)) {
    return;
  }
  memcpy(headData, file + pos, 54);
  headData[8] = headData[9] = headData[10] = headData[11] = (Guchar)0;

  // read the original 'loca' table, pad entries out to 4 bytes, and
  // sort it into proper order -- some (non-compliant) fonts have
  // out-of-order loca tables; in order to correctly handle the case
  // where (compliant) fonts have empty entries in the middle of the
  // table, cmpTrueTypeLocaPos uses offset as its primary sort key,
  // and idx as its secondary key (ensuring that adjacent entries with
  // the same pos value remain in the same order)
  locaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) * sizeof(TrueTypeLoca));
  i = seekTable("loca");
  pos = tables[i].offset;
  ok = gTrue;
  for (i = 0; i <= nGlyphs; ++i) {
    locaTable[i].idx = i;
    if (locaFmt) {
      locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
    } else {
      locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
    }
  }
  qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
       &cmpTrueTypeLocaOffset);
  for (i = 0; i < nGlyphs; ++i) {
    locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
  }
  locaTable[nGlyphs].len = 0;
  qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
       &cmpTrueTypeLocaIdx);
  pos = 0;
  for (i = 0; i <= nGlyphs; ++i) {
    locaTable[i].newOffset = pos;
    pos += locaTable[i].len;
    if (pos & 3) {
      pos += 4 - (pos & 3);
    }
  }

  // construct the new 'loca' table
  locaData = (Guchar *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
  for (i = 0; i <= nGlyphs; ++i) {
    pos = locaTable[i].newOffset;
    if (locaFmt) {
      locaData[4*i  ] = (Guchar)(pos >> 24);
      locaData[4*i+1] = (Guchar)(pos >> 16);
      locaData[4*i+2] = (Guchar)(pos >>  8);
      locaData[4*i+3] = (Guchar) pos;
    } else {
      locaData[2*i  ] = (Guchar)(pos >> 9);
      locaData[2*i+1] = (Guchar)(pos >> 1);
    }
  }

  // count the number of tables
  nNewTables = 0;
  for (i = 0; i < nT42Tables; ++i) {
    if (t42Tables[i].required ||
       seekTable(t42Tables[i].tag) >= 0) {
      ++nNewTables;
    }
  }

  // construct the new table headers, including table checksums
  // (pad each table out to a multiple of 4 bytes)
  pos = 12 + nNewTables*16;
  k = 0;
  for (i = 0; i < nT42Tables; ++i) {
    length = -1;
    checksum = 0; // make gcc happy
    if (i == t42HeadTable) {
      length = 54;
      checksum = computeTableChecksum(headData, 54);
    } else if (i == t42LocaTable) {
      length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
      checksum = computeTableChecksum(locaData, length);
    } else if (i == t42GlyfTable) {
      length = 0;
      checksum = 0;
      glyfPos = tables[seekTable("glyf")].offset;
      for (j = 0; j < nGlyphs; ++j) {
       length += locaTable[j].len;
       if (length & 3) {
         length += 4 - (length & 3);
       }
       if (checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
         checksum +=
             computeTableChecksum(file + glyfPos + locaTable[j].origOffset,
                               locaTable[j].len);
       }
      }
    } else {
      if ((j = seekTable(t42Tables[i].tag)) >= 0) {
       length = tables[j].len;
       if (checkRegion(tables[j].offset, length)) {
         checksum = computeTableChecksum(file + tables[j].offset, length);
       }
      } else if (t42Tables[i].required) {
       //~ error(-1, "Embedded TrueType font is missing a required table ('%s')",
       //~       t42Tables[i].tag);
       length = 0;
       checksum = 0;
      }
    }
    if (length >= 0) {
      newTables[k].tag = ((t42Tables[i].tag[0] & 0xff) << 24) |
                        ((t42Tables[i].tag[1] & 0xff) << 16) |
                        ((t42Tables[i].tag[2] & 0xff) <<  8) |
                         (t42Tables[i].tag[3] & 0xff);
      newTables[k].checksum = checksum;
      newTables[k].offset = pos;
      newTables[k].len = length;
      pos += length;
      if (pos & 3) {
       pos += 4 - (length & 3);
      }
      ++k;
    }
  }

  // construct the table directory
  tableDir[0] = 0x00;              // sfnt version
  tableDir[1] = 0x01;
  tableDir[2] = 0x00;
  tableDir[3] = 0x00;
  tableDir[4] = 0;          // numTables
  tableDir[5] = nNewTables;
  tableDir[6] = 0;          // searchRange
  tableDir[7] = (Guchar)128;
  tableDir[8] = 0;          // entrySelector
  tableDir[9] = 3;
  tableDir[10] = 0;         // rangeShift
  tableDir[11] = (Guchar)(16 * nNewTables - 128);
  pos = 12;
  for (i = 0; i < nNewTables; ++i) {
    tableDir[pos   ] = (Guchar)(newTables[i].tag >> 24);
    tableDir[pos+ 1] = (Guchar)(newTables[i].tag >> 16);
    tableDir[pos+ 2] = (Guchar)(newTables[i].tag >>  8);
    tableDir[pos+ 3] = (Guchar) newTables[i].tag;
    tableDir[pos+ 4] = (Guchar)(newTables[i].checksum >> 24);
    tableDir[pos+ 5] = (Guchar)(newTables[i].checksum >> 16);
    tableDir[pos+ 6] = (Guchar)(newTables[i].checksum >>  8);
    tableDir[pos+ 7] = (Guchar) newTables[i].checksum;
    tableDir[pos+ 8] = (Guchar)(newTables[i].offset >> 24);
    tableDir[pos+ 9] = (Guchar)(newTables[i].offset >> 16);
    tableDir[pos+10] = (Guchar)(newTables[i].offset >>  8);
    tableDir[pos+11] = (Guchar) newTables[i].offset;
    tableDir[pos+12] = (Guchar)(newTables[i].len >> 24);
    tableDir[pos+13] = (Guchar)(newTables[i].len >> 16);
    tableDir[pos+14] = (Guchar)(newTables[i].len >>  8);
    tableDir[pos+15] = (Guchar) newTables[i].len;
    pos += 16;
  }

  // compute the font checksum and store it in the head table
  checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
  for (i = 0; i < nNewTables; ++i) {
    checksum += newTables[i].checksum;
  }
  checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
  headData[ 8] = (Guchar)(checksum >> 24);
  headData[ 9] = (Guchar)(checksum >> 16);
  headData[10] = (Guchar)(checksum >>  8);
  headData[11] = (Guchar) checksum;

  // start the sfnts array
  if (name) {
    (*outputFunc)(outputStream, "/", 1);
    (*outputFunc)(outputStream, name->getCString(), name->getLength());
    (*outputFunc)(outputStream, " [\n", 3);
  } else {
    (*outputFunc)(outputStream, "/sfnts [\n", 9);
  }

  // write the table directory
  dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);

  // write the tables
  for (i = 0; i < nNewTables; ++i) {
    if (i == t42HeadTable) {
      dumpString(headData, 54, outputFunc, outputStream);
    } else if (i == t42LocaTable) {
      length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
      dumpString(locaData, length, outputFunc, outputStream);
    } else if (i == t42GlyfTable) {
      glyfPos = tables[seekTable("glyf")].offset;
      for (j = 0; j < nGlyphs; ++j) {
       if (locaTable[j].len > 0 &&
           checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
         dumpString(file + glyfPos + locaTable[j].origOffset,
                   locaTable[j].len, outputFunc, outputStream);
       }
      }
    } else {
      // length == 0 means the table is missing and the error was
      // already reported during the construction of the table
      // headers
      if ((length = newTables[i].len) > 0) {
       if ((j = seekTable(t42Tables[i].tag)) >= 0 &&
           checkRegion(tables[j].offset, tables[j].len)) {
         dumpString(file + tables[j].offset, tables[j].len,
                   outputFunc, outputStream);
       }
      }
    }
  }

  // end the sfnts array
  (*outputFunc)(outputStream, "] def\n", 6);

  gfree(locaData);
  gfree(locaTable);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void FoFiTrueType::dumpString ( Guchar s,
int  length,
FoFiOutputFunc  outputFunc,
void outputStream 
) [private]

Definition at line 1208 of file FoFiTrueType.cc.

                                               {
  char buf[64];
  int pad, i, j;

  (*outputFunc)(outputStream, "<", 1);
  for (i = 0; i < length; i += 32) {
    for (j = 0; j < 32 && i+j < length; ++j) {
      sprintf(buf, "%02X", s[i+j] & 0xff);
      (*outputFunc)(outputStream, buf, strlen(buf));
    }
    if (i % (65536 - 32) == 65536 - 64) {
      (*outputFunc)(outputStream, ">\n<", 3);
    } else if (i+32 < length) {
      (*outputFunc)(outputStream, "\n", 1);
    }
  }
  if (length & 3) {
    pad = 4 - (length & 3);
    for (i = 0; i < pad; ++i) {
      (*outputFunc)(outputStream, "00", 2);
    }
  }
  // add an extra zero byte because the Adobe Type 42 spec says so
  (*outputFunc)(outputStream, "00>\n", 4);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int FoFiTrueType::findCmap ( int  platform,
int  encoding 
)

Definition at line 294 of file FoFiTrueType.cc.

                                                     {
  int i;

  for (i = 0; i < nCmaps; ++i) {
    if (cmaps[i].platform == platform && cmaps[i].encoding == encoding) {
      return i;
    }
  }
  return -1;
}

Definition at line 290 of file FoFiTrueType.cc.

                                       {
  return cmaps[i].encoding;
}

Here is the caller graph for this function:

Definition at line 286 of file FoFiTrueType.cc.

                                       {
  return cmaps[i].platform;
}

Here is the caller graph for this function:

Definition at line 384 of file FoFiTrueType.cc.

                                     {
  int i, fsType;
  GBool ok;

  if ((i = seekTable("OS/2")) < 0) {
    return 4;
  }
  ok = gTrue;
  fsType = getU16BE(tables[i].offset + 8, &ok);
  if (!ok) {
    return 4;
  }
  if (fsType & 0x0008) {
    return 2;
  }
  if (fsType & 0x0004) {
    return 1;
  }
  if (fsType & 0x0002) {
    return 0;
  }
  return 3;
}

Here is the call graph for this function:

Definition at line 282 of file FoFiTrueType.cc.

                              {
  return nCmaps;
}

Here is the caller graph for this function:

int FoFiBase::getS16BE ( int  pos,
GBool ok 
) [protected, inherited]

Definition at line 79 of file FoFiBase.cc.

                                         {
  int x;

  if (pos < 0 || pos+1 >= len) {
    *ok = gFalse;
    return 0;
  }
  x = file[pos];
  x = (x << 8) + file[pos+1];
  if (x & 0x8000) {
    x |= ~0xffff;
  }
  return x;
}

Here is the caller graph for this function:

int FoFiBase::getS32BE ( int  pos,
GBool ok 
) [protected, inherited]

Definition at line 106 of file FoFiBase.cc.

                                         {
  int x;

  if (pos < 0 || pos+3 >= len) {
    *ok = gFalse;
    return 0;
  }
  x = file[pos];
  x = (x << 8) + file[pos+1];
  x = (x << 8) + file[pos+2];
  x = (x << 8) + file[pos+3];
  if (x & 0x80000000) {
    x |= ~0xffffffff;
  }
  return x;
}

Here is the caller graph for this function:

int FoFiBase::getS8 ( int  pos,
GBool ok 
) [protected, inherited]

Definition at line 57 of file FoFiBase.cc.

                                      {
  int x;

  if (pos < 0 || pos >= len) {
    *ok = gFalse;
    return 0;
  }
  x = file[pos];
  if (x & 0x80) {
    x |= ~0xff;
  }
  return x;
}
int FoFiBase::getU16BE ( int  pos,
GBool ok 
) [protected, inherited]

Definition at line 94 of file FoFiBase.cc.

                                         {
  int x;

  if (pos < 0 || pos+1 >= len) {
    *ok = gFalse;
    return 0;
  }
  x = file[pos];
  x = (x << 8) + file[pos+1];
  return x;
}

Here is the caller graph for this function:

Guint FoFiBase::getU32BE ( int  pos,
GBool ok 
) [protected, inherited]

Definition at line 123 of file FoFiBase.cc.

                                           {
  Guint x;

  if (pos < 0 || pos+3 >= len) {
    *ok = gFalse;
    return 0;
  }
  x = file[pos];
  x = (x << 8) + file[pos+1];
  x = (x << 8) + file[pos+2];
  x = (x << 8) + file[pos+3];
  return x;
}

Here is the caller graph for this function:

int FoFiBase::getU8 ( int  pos,
GBool ok 
) [protected, inherited]

Definition at line 71 of file FoFiBase.cc.

                                      {
  if (pos < 0 || pos >= len) {
    *ok = gFalse;
    return 0;
  }
  return file[pos];
}

Here is the caller graph for this function:

Guint FoFiBase::getUVarBE ( int  pos,
int  size,
GBool ok 
) [protected, inherited]

Definition at line 137 of file FoFiBase.cc.

                                                      {
  Guint x;
  int i;

  if (pos < 0 || pos + size > len) {
    *ok = gFalse;
    return 0;
  }
  x = 0;
  for (i = 0; i < size; ++i) {
    x = (x << 8) + file[pos + i];
  }
  return x;
}

Here is the caller graph for this function:

FoFiTrueType * FoFiTrueType::load ( char *  fileName) [static]

Definition at line 247 of file FoFiTrueType.cc.

                                               {
  FoFiTrueType *ff;
  char *fileA;
  int lenA;

  if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
    return NULL;
  }
  ff = new FoFiTrueType(fileA, lenA, gTrue);
  if (!ff->parsedOk) {
    delete ff;
    return NULL;
  }
  return ff;
}

Here is the call graph for this function:

FoFiTrueType * FoFiTrueType::make ( char *  fileA,
int  lenA 
) [static]

Definition at line 236 of file FoFiTrueType.cc.

                                                      {
  FoFiTrueType *ff;

  ff = new FoFiTrueType(fileA, lenA, gFalse);
  if (!ff->parsedOk) {
    delete ff;
    return NULL;
  }
  return ff;
}

Here is the call graph for this function:

Definition at line 305 of file FoFiTrueType.cc.

                                               {
  Gushort gid;
  int segCnt, segEnd, segStart, segDelta, segOffset;
  int cmapFirst, cmapLen;
  int pos, a, b, m;
  GBool ok;

  if (i < 0 || i >= nCmaps) {
    return 0;
  }
  ok = gTrue;
  pos = cmaps[i].offset;
  switch (cmaps[i].fmt) {
  case 0:
    if (c < 0 || c >= cmaps[i].len - 6) {
      return 0;
    }
    gid = getU8(cmaps[i].offset + 6 + c, &ok);
    break;
  case 4:
    segCnt = getU16BE(pos + 6, &ok) / 2;
    a = -1;
    b = segCnt - 1;
    segEnd = getU16BE(pos + 14 + 2*b, &ok);
    if (c > segEnd) {
      // malformed font -- the TrueType spec requires the last segEnd
      // to be 0xffff
      return 0;
    }
    // invariant: seg[a].end < code <= seg[b].end
    while (b - a > 1 && ok) {
      m = (a + b) / 2;
      segEnd = getU16BE(pos + 14 + 2*m, &ok);
      if (segEnd < c) {
       a = m;
      } else {
       b = m;
      }
    }
    segStart = getU16BE(pos + 16 + 2*segCnt + 2*b, &ok);
    segDelta = getU16BE(pos + 16 + 4*segCnt + 2*b, &ok);
    segOffset = getU16BE(pos + 16 + 6*segCnt + 2*b, &ok);
    if (c < segStart) {
      return 0;
    }
    if (segOffset == 0) {
      gid = (c + segDelta) & 0xffff;
    } else {
      gid = getU16BE(pos + 16 + 6*segCnt + 2*b +
                     segOffset + 2 * (c - segStart), &ok);
      if (gid != 0) {
       gid = (gid + segDelta) & 0xffff;
      }
    }
    break;
  case 6:
    cmapFirst = getU16BE(pos + 6, &ok);
    cmapLen = getU16BE(pos + 8, &ok);
    if (c < cmapFirst || c >= cmapFirst + cmapLen) {
      return 0;
    }
    gid = getU16BE(pos + 10 + 2 * (c - cmapFirst), &ok);
    break;
  default:
    return 0;
  }
  if (!ok) {
    return 0;
  }
  return gid;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int FoFiTrueType::mapNameToGID ( char *  name)

Definition at line 377 of file FoFiTrueType.cc.

                                         {
  if (!nameToGID) {
    return 0;
  }
  return nameToGID->lookupInt(name);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void FoFiTrueType::parse ( ) [private]

Definition at line 1265 of file FoFiTrueType.cc.

                         {
  int pos, i, j;

  parsedOk = gTrue;

  // read the table directory
  nTables = getU16BE(4, &parsedOk);
  if (!parsedOk) {
    return;
  }
  tables = (TrueTypeTable *)gmalloc(nTables * sizeof(TrueTypeTable));
  pos = 12;
  for (i = 0; i < nTables; ++i) {
    tables[i].tag = getU32BE(pos, &parsedOk);
    tables[i].checksum = getU32BE(pos + 4, &parsedOk);
    tables[i].offset = (int)getU32BE(pos + 8, &parsedOk);
    tables[i].len = (int)getU32BE(pos + 12, &parsedOk);
    if (tables[i].offset + tables[i].len < tables[i].offset ||
       tables[i].offset + tables[i].len > len) {
      parsedOk = gFalse;
    }
    pos += 16;
  }
  if (!parsedOk) {
    return;
  }

  // check for tables that are required by both the TrueType spec and
  // the Type 42 spec
  if (seekTable("head") < 0 ||
      seekTable("hhea") < 0 ||
      seekTable("loca") < 0 ||
      seekTable("maxp") < 0 ||
      seekTable("glyf") < 0 ||
      seekTable("hmtx") < 0) {
    parsedOk = gFalse;
    return;
  }

  // read the cmaps
  if ((i = seekTable("cmap")) >= 0) {
    pos = tables[i].offset + 2;
    nCmaps = getU16BE(pos, &parsedOk);
    pos += 2;
    if (!parsedOk) {
      return;
    }
    cmaps = (TrueTypeCmap *)gmalloc(nCmaps * sizeof(TrueTypeCmap));
    for (j = 0; j < nCmaps; ++j) {
      cmaps[j].platform = getU16BE(pos, &parsedOk);
      cmaps[j].encoding = getU16BE(pos + 2, &parsedOk);
      cmaps[j].offset = tables[i].offset + getU32BE(pos + 4, &parsedOk);
      pos += 8;
      cmaps[j].fmt = getU16BE(cmaps[j].offset, &parsedOk);
      cmaps[j].len = getU16BE(cmaps[j].offset + 2, &parsedOk);
    }
    if (!parsedOk) {
      return;
    }
  } else {
    nCmaps = 0;
  }

  // get the number of glyphs from the maxp table
  i = seekTable("maxp");
  nGlyphs = getU16BE(tables[i].offset + 4, &parsedOk);
  if (!parsedOk) {
    return;
  }

  // get the bbox and loca table format from the head table
  i = seekTable("head");
  bbox[0] = getS16BE(tables[i].offset + 36, &parsedOk);
  bbox[1] = getS16BE(tables[i].offset + 38, &parsedOk);
  bbox[2] = getS16BE(tables[i].offset + 40, &parsedOk);
  bbox[3] = getS16BE(tables[i].offset + 42, &parsedOk);
  locaFmt = getS16BE(tables[i].offset + 50, &parsedOk);
  if (!parsedOk) {
    return;
  }

  // read the post table
  readPostTable();
  if (!parsedOk) {
    return;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

char * FoFiBase::readFile ( char *  fileName,
int fileLen 
) [static, protected, inherited]

Definition at line 35 of file FoFiBase.cc.

                                                     {
  FILE *f;
  char *buf;
  int n;

  if (!(f = fopen(fileName, "rb"))) {
    return NULL;
  }
  fseek(f, 0, SEEK_END);
  n = (int)ftell(f);
  fseek(f, 0, SEEK_SET);
  buf = (char *)gmalloc(n);
  if ((int)fread(buf, 1, n, f) != n) {
    gfree(buf);
    fclose(f);
    return NULL;
  }
  fclose(f);
  *fileLen = n;
  return buf;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1353 of file FoFiTrueType.cc.

                                 {
  GString *name;
  int tablePos, postFmt, stringIdx, stringPos;
  int i, j, n, m;

  if ((i = seekTable("post")) < 0) {
    return;
  }
  tablePos = tables[i].offset;
  postFmt = getU32BE(tablePos, &parsedOk);
  if (!parsedOk) {
    return;
  }
  if (postFmt == 0x00010000) {
    nameToGID = new GHash(gTrue);
    for (i = 0; i < 258; ++i) {
      nameToGID->add(new GString(macGlyphNames[i]), i);
    }
  } else if (postFmt == 0x00020000) {
    nameToGID = new GHash(gTrue);
    n = getU16BE(tablePos + 32, &parsedOk);
    if (!parsedOk) {
      return;
    }
    if (n > nGlyphs) {
      n = nGlyphs;
    }
    stringIdx = 0;
    stringPos = tablePos + 34 + 2*n;
    for (i = 0; i < n; ++i) {
      j = getU16BE(tablePos + 34 + 2*i, &parsedOk);
      if (j < 258) {
       nameToGID->removeInt(macGlyphNames[j]);
       nameToGID->add(new GString(macGlyphNames[j]), i);
      } else {
       j -= 258;
       if (j != stringIdx) {
         for (stringIdx = 0, stringPos = tablePos + 34 + 2*n;
              stringIdx < j;
              ++stringIdx, stringPos += 1 + getU8(stringPos, &parsedOk)) ;
         if (!parsedOk) {
           return;
         }
       }
       m = getU8(stringPos, &parsedOk);
       if (!parsedOk || !checkRegion(stringPos + 1, m)) {
         parsedOk = gFalse;
         return;
       }
       name = new GString((char *)&file[stringPos + 1], m);
       nameToGID->removeInt(name);
       nameToGID->add(name, i);
       ++stringIdx;
       stringPos += 1 + m;
      }
    }
  } else if (postFmt == 0x00028000) {
    nameToGID = new GHash(gTrue);
    for (i = 0; i < nGlyphs; ++i) {
      j = getU8(tablePos + 32 + i, &parsedOk);
      if (!parsedOk) {
       return;
      }
      if (j < 258) {
       nameToGID->removeInt(macGlyphNames[j]);
       nameToGID->add(new GString(macGlyphNames[j]), i);
      }
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int FoFiTrueType::seekTable ( char *  tag) [private]

Definition at line 1424 of file FoFiTrueType.cc.

                                     {
  Guint tagI;
  int i;

  tagI = ((tag[0] & 0xff) << 24) |
         ((tag[1] & 0xff) << 16) |
         ((tag[2] & 0xff) << 8) |
          (tag[3] & 0xff);
  for (i = 0; i < nTables; ++i) {
    if (tables[i].tag == tagI) {
      return i;
    }
  }
  return -1;
}

Here is the caller graph for this function:

void FoFiTrueType::writeTTF ( FoFiOutputFunc  outputFunc,
void outputStream 
)

Definition at line 622 of file FoFiTrueType.cc.

                                             {
  static char cmapTab[20] = {
    0, 0,                   // table version number
    0, 1,                   // number of encoding tables
    0, 1,                   // platform ID
    0, 0,                   // encoding ID
    0, 0, 0, 12,            // offset of subtable
    0, 0,                   // subtable format
    0, 1,                   // subtable length
    0, 1,                   // subtable version
    0,                      // map char 0 -> glyph 0
    0                       // pad to multiple of four bytes
  };
  static char nameTab[8] = {
    0, 0,                   // format
    0, 0,                   // number of name records
    0, 6,                   // offset to start of string storage
    0, 0                    // pad to multiple of four bytes
  };
  static char postTab[32] = {
    0, 1, 0, 0,                    // format
    0, 0, 0, 0,                    // italic angle
    0, 0,                   // underline position
    0, 0,                   // underline thickness
    0, 0, 0, 0,                    // fixed pitch
    0, 0, 0, 0,                    // min Type 42 memory
    0, 0, 0, 0,                    // max Type 42 memory
    0, 0, 0, 0,                    // min Type 1 memory
    0, 0, 0, 0                     // max Type 1 memory
  };
  GBool missingCmap, missingName, missingPost, unsortedLoca, badCmapLen;
  int nZeroLengthTables;
  TrueTypeLoca *locaTable;
  TrueTypeTable *newTables;
  int nNewTables, cmapIdx, cmapLen, glyfLen;
  char *tableDir;
  char locaBuf[4];
  GBool ok;
  Guint t;
  int pos, i, j, k, n;

  // check for missing tables
  missingCmap = (cmapIdx = seekTable("cmap")) < 0;
  missingName = seekTable("name") < 0;
  missingPost = seekTable("post") < 0;

  // read the loca table, check to see if it's sorted
  locaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) * sizeof(TrueTypeLoca));
  unsortedLoca = gFalse;
  i = seekTable("loca");
  pos = tables[i].offset;
  ok = gTrue;
  for (i = 0; i <= nGlyphs; ++i) {
    if (locaFmt) {
      locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
    } else {
      locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
    }
    if (i > 0 && locaTable[i].origOffset < locaTable[i-1].origOffset) {
      unsortedLoca = gTrue;
    }
    locaTable[i].idx = i;
  }

  // check for zero-length tables
  nZeroLengthTables = 0;
  for (i = 0; i < nTables; ++i) {
    if (tables[i].len == 0) {
      ++nZeroLengthTables;
    }
  }

  // check for an incorrect cmap table length
  badCmapLen = gFalse;
  cmapLen = 0; // make gcc happy
  if (!missingCmap) {
    cmapLen = cmaps[0].offset + cmaps[0].len;
    for (i = 1; i < nCmaps; ++i) {
      if (cmaps[i].offset + cmaps[i].len > cmapLen) {
       cmapLen = cmaps[i].offset + cmaps[i].len;
      }
    }
    cmapLen -= tables[cmapIdx].offset;
    if (cmapLen > tables[cmapIdx].len) {
      badCmapLen = gTrue;
    }
  }

  // if nothing is broken, just write the TTF file as is
  if (!missingCmap && !missingName && !missingPost && !unsortedLoca &&
      !badCmapLen && nZeroLengthTables == 0) {
    (*outputFunc)(outputStream, (char *)file, len);
    goto done1;
  }

  // sort the 'loca' table: some (non-compliant) fonts have
  // out-of-order loca tables; in order to correctly handle the case
  // where (compliant) fonts have empty entries in the middle of the
  // table, cmpTrueTypeLocaOffset uses offset as its primary sort key,
  // and idx as its secondary key (ensuring that adjacent entries with
  // the same pos value remain in the same order)
  glyfLen = 0; // make gcc happy
  if (unsortedLoca) {
    qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
         &cmpTrueTypeLocaOffset);
    for (i = 0; i < nGlyphs; ++i) {
      locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
    }
    locaTable[nGlyphs].len = 0;
    qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
         &cmpTrueTypeLocaIdx);
    pos = 0;
    for (i = 0; i <= nGlyphs; ++i) {
      locaTable[i].newOffset = pos;
      pos += locaTable[i].len;
      if (pos & 3) {
       pos += 4 - (pos & 3);
      }
    }
    glyfLen = pos;
  }

  // construct the new table directory:
  // - keep all original tables with non-zero length
  // - fix the cmap table's length, if necessary
  // - add missing tables
  // - sort the table by tag
  // - compute new table positions, including 4-byte alignment
  nNewTables = nTables - nZeroLengthTables +
               (missingCmap ? 1 : 0) + (missingName ? 1 : 0) +
               (missingPost ? 1 : 0);
  newTables = (TrueTypeTable *)gmalloc(nNewTables * sizeof(TrueTypeTable));
  j = 0;
  for (i = 0; i < nTables; ++i) {
    if (tables[i].len > 0) {
      newTables[j] = tables[i];
      newTables[j].origOffset = tables[i].offset;
      if (newTables[j].tag == cmapTag && badCmapLen) {
       newTables[j].len = cmapLen;
      } else if (newTables[j].tag == locaTag && unsortedLoca) {
       newTables[j].len = (nGlyphs + 1) * (locaFmt ? 4 : 2);
      } else if (newTables[j].tag == glyfTag && unsortedLoca) {
       newTables[j].len = glyfLen;
      }
      ++j;
    }
  }
  if (missingCmap) {
    newTables[j].tag = cmapTag;
    newTables[j].checksum = 0; //~ should compute the checksum
    newTables[j].len = sizeof(cmapTab);
    ++j;
  }
  if (missingName) {
    newTables[j].tag = nameTag;
    newTables[j].checksum = 0; //~ should compute the checksum
    newTables[j].len = sizeof(nameTab);
    ++j;
  }
  if (missingPost) {
    newTables[j].tag = postTag;
    newTables[j].checksum = 0; //~ should compute the checksum
    newTables[j].len = sizeof(postTab);
    ++j;
  }
  qsort(newTables, nNewTables, sizeof(TrueTypeTable),
       &cmpTrueTypeTableTag);
  pos = 12 + nNewTables * 16;
  for (i = 0; i < nNewTables; ++i) {
    newTables[i].offset = pos;
    pos += newTables[i].len;
    if (pos & 3) {
      pos += 4 - (pos & 3);
    }
  }

  // write the table directory
  tableDir = (char *)gmalloc(12 + nNewTables * 16);
  tableDir[0] = 0x00;                                   // sfnt version
  tableDir[1] = 0x01;
  tableDir[2] = 0x00;
  tableDir[3] = 0x00;
  tableDir[4] = (char)((nNewTables >> 8) & 0xff);       // numTables
  tableDir[5] = (char)(nNewTables & 0xff);
  for (i = -1, t = (Guint)nNewTables; t; ++i, t >>= 1) ;
  t = 1 << (4 + i);
  tableDir[6] = (char)((t >> 8) & 0xff);         // searchRange
  tableDir[7] = (char)(t & 0xff);
  tableDir[8] = (char)((i >> 8) & 0xff);         // entrySelector
  tableDir[9] = (char)(i & 0xff);
  t = nNewTables * 16 - t;
  tableDir[10] = (char)((t >> 8) & 0xff);        // rangeShift
  tableDir[11] = (char)(t & 0xff);
  pos = 12;
  for (i = 0; i < nNewTables; ++i) {
    tableDir[pos   ] = (char)(newTables[i].tag >> 24);
    tableDir[pos+ 1] = (char)(newTables[i].tag >> 16);
    tableDir[pos+ 2] = (char)(newTables[i].tag >>  8);
    tableDir[pos+ 3] = (char) newTables[i].tag;
    tableDir[pos+ 4] = (char)(newTables[i].checksum >> 24);
    tableDir[pos+ 5] = (char)(newTables[i].checksum >> 16);
    tableDir[pos+ 6] = (char)(newTables[i].checksum >>  8);
    tableDir[pos+ 7] = (char) newTables[i].checksum;
    tableDir[pos+ 8] = (char)(newTables[i].offset >> 24);
    tableDir[pos+ 9] = (char)(newTables[i].offset >> 16);
    tableDir[pos+10] = (char)(newTables[i].offset >>  8);
    tableDir[pos+11] = (char) newTables[i].offset;
    tableDir[pos+12] = (char)(newTables[i].len >> 24);
    tableDir[pos+13] = (char)(newTables[i].len >> 16);
    tableDir[pos+14] = (char)(newTables[i].len >>  8);
    tableDir[pos+15] = (char) newTables[i].len;
    pos += 16;
  }
  (*outputFunc)(outputStream, tableDir, 12 + nNewTables * 16);

  // write the tables
  for (i = 0; i < nNewTables; ++i) {
    if (newTables[i].tag == cmapTag && missingCmap) {
      (*outputFunc)(outputStream, cmapTab, newTables[i].len);
    } else if (newTables[i].tag == nameTag && missingName) {
      (*outputFunc)(outputStream, nameTab, newTables[i].len);
    } else if (newTables[i].tag == postTag && missingPost) {
      (*outputFunc)(outputStream, postTab, newTables[i].len);
    } else if (newTables[i].tag == locaTag && unsortedLoca) {
      for (j = 0; j <= nGlyphs; ++j) {
       if (locaFmt) {
         locaBuf[0] = (char)(locaTable[j].newOffset >> 24);
         locaBuf[1] = (char)(locaTable[j].newOffset >> 16);
         locaBuf[2] = (char)(locaTable[j].newOffset >>  8);
         locaBuf[3] = (char) locaTable[j].newOffset;
         (*outputFunc)(outputStream, locaBuf, 4);
       } else {
         locaBuf[0] = (char)(locaTable[j].newOffset >> 9);
         locaBuf[1] = (char)(locaTable[j].newOffset >> 1);
         (*outputFunc)(outputStream, locaBuf, 2);
       }
      }
    } else if (newTables[i].tag == glyfTag && unsortedLoca) {
      pos = tables[seekTable("glyf")].offset;
      for (j = 0; j < nGlyphs; ++j) {
       n = locaTable[j].len;
       if (n > 0) {
         k = locaTable[j].origOffset;
         if (checkRegion(pos + k, n)) {
           (*outputFunc)(outputStream, (char *)file + pos + k, n);
         } else {
           for (k = 0; k < n; ++k) {
             (*outputFunc)(outputStream, "\0", 1);
           }
         }
         if ((k = locaTable[j].len & 3)) {
           (*outputFunc)(outputStream, "\0\0\0\0", 4 - k);
         }
       }
      }
    } else {
      if (checkRegion(newTables[i].origOffset, newTables[i].len)) {
       (*outputFunc)(outputStream, (char *)file + newTables[i].origOffset,
                    newTables[i].len);
      } else {
       for (j = 0; j < newTables[i].len; ++j) {
         (*outputFunc)(outputStream, "\0", 1);
       }
      }
    }
    if (newTables[i].len & 3) {
      (*outputFunc)(outputStream, "\0\0\0", 4 - (newTables[i].len & 3));
    }
  }

  gfree(tableDir);
  gfree(newTables);
 done1:
  gfree(locaTable);
}

Here is the call graph for this function:


Member Data Documentation

int FoFiTrueType::bbox[4] [private]

Definition at line 127 of file FoFiTrueType.h.

Definition at line 123 of file FoFiTrueType.h.

Guchar* FoFiBase::file [protected, inherited]

Definition at line 52 of file FoFiBase.h.

Guchar* FoFiBase::fileData [protected, inherited]

Definition at line 51 of file FoFiBase.h.

GBool FoFiBase::freeFileData [protected, inherited]

Definition at line 54 of file FoFiBase.h.

int FoFiBase::len [protected, inherited]

Definition at line 53 of file FoFiBase.h.

Definition at line 126 of file FoFiTrueType.h.

Definition at line 128 of file FoFiTrueType.h.

Definition at line 124 of file FoFiTrueType.h.

Definition at line 125 of file FoFiTrueType.h.

Definition at line 122 of file FoFiTrueType.h.

Definition at line 130 of file FoFiTrueType.h.

Definition at line 121 of file FoFiTrueType.h.


The documentation for this class was generated from the following files: