Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/pdf/fofi/FoFiTrueType.cc
diff options
context:
space:
mode:
Diffstat (limited to 'pdf/fofi/FoFiTrueType.cc')
-rw-r--r--pdf/fofi/FoFiTrueType.cc1438
1 files changed, 0 insertions, 1438 deletions
diff --git a/pdf/fofi/FoFiTrueType.cc b/pdf/fofi/FoFiTrueType.cc
deleted file mode 100644
index a4cf43c..0000000
--- a/pdf/fofi/FoFiTrueType.cc
+++ /dev/null
@@ -1,1438 +0,0 @@
-//========================================================================
-//
-// FoFiTrueType.cc
-//
-// Copyright 1999-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include "gtypes.h"
-#include "gmem.h"
-#include "GString.h"
-#include "GHash.h"
-#include "FoFiTrueType.h"
-
-//
-// Terminology
-// -----------
-//
-// character code = number used as an element of a text string
-//
-// character name = glyph name = name for a particular glyph within a
-// font
-//
-// glyph index = GID = position (within some internal table in the font)
-// where the instructions to draw a particular glyph are
-// stored
-//
-// Type 1 fonts
-// ------------
-//
-// Type 1 fonts contain:
-//
-// Encoding: array of glyph names, maps char codes to glyph names
-//
-// Encoding[charCode] = charName
-//
-// CharStrings: dictionary of instructions, keyed by character names,
-// maps character name to glyph data
-//
-// CharStrings[charName] = glyphData
-//
-// TrueType fonts
-// --------------
-//
-// TrueType fonts contain:
-//
-// 'cmap' table: mapping from character code to glyph index; there may
-// be multiple cmaps in a TrueType font
-//
-// cmap[charCode] = gid
-//
-// 'post' table: mapping from glyph index to glyph name
-//
-// post[gid] = glyphName
-//
-// Type 42 fonts
-// -------------
-//
-// Type 42 fonts contain:
-//
-// Encoding: array of glyph names, maps char codes to glyph names
-//
-// Encoding[charCode] = charName
-//
-// CharStrings: dictionary of glyph indexes, keyed by character names,
-// maps character name to glyph index
-//
-// CharStrings[charName] = gid
-//
-
-//------------------------------------------------------------------------
-
-struct TrueTypeTable {
- Guint tag;
- Guint checksum;
- int offset;
- int origOffset;
- int len;
-};
-
-struct TrueTypeCmap {
- int platform;
- int encoding;
- int offset;
- int len;
- int fmt;
-};
-
-struct TrueTypeLoca {
- int idx;
- int origOffset;
- int newOffset;
- int len;
-};
-
-#define cmapTag 0x636d6170
-#define glyfTag 0x676c7966
-#define locaTag 0x6c6f6361
-#define nameTag 0x6e616d65
-#define postTag 0x706f7374
-
-static int cmpTrueTypeLocaOffset(const void *p1, const void *p2) {
- TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
- TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
-
- if (loca1->origOffset == loca2->origOffset) {
- return loca1->idx - loca2->idx;
- }
- return loca1->origOffset - loca2->origOffset;
-}
-
-static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) {
- TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
- TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
-
- return loca1->idx - loca2->idx;
-}
-
-static int cmpTrueTypeTableTag(const void *p1, const void *p2) {
- TrueTypeTable *tab1 = (TrueTypeTable *)p1;
- TrueTypeTable *tab2 = (TrueTypeTable *)p2;
-
- return (int)tab1->tag - (int)tab2->tag;
-}
-
-//------------------------------------------------------------------------
-
-struct T42Table {
- char *tag; // 4-byte tag
- GBool required; // required by the TrueType spec?
-};
-
-// TrueType tables to be embedded in Type 42 fonts.
-// NB: the table names must be in alphabetical order here.
-#define nT42Tables 11
-static T42Table t42Tables[nT42Tables] = {
- { "cvt ", gTrue },
- { "fpgm", gTrue },
- { "glyf", gTrue },
- { "head", gTrue },
- { "hhea", gTrue },
- { "hmtx", gTrue },
- { "loca", gTrue },
- { "maxp", gTrue },
- { "prep", gTrue },
- { "vhea", gFalse },
- { "vmtx", gFalse }
-};
-#define t42HeadTable 3
-#define t42LocaTable 6
-#define t42GlyfTable 2
-
-//------------------------------------------------------------------------
-
-// Glyph names in some arbitrary standard order that Apple uses for
-// their TrueType fonts.
-static char *macGlyphNames[258] = {
- ".notdef", "null", "CR", "space",
- "exclam", "quotedbl", "numbersign", "dollar",
- "percent", "ampersand", "quotesingle", "parenleft",
- "parenright", "asterisk", "plus", "comma",
- "hyphen", "period", "slash", "zero",
- "one", "two", "three", "four",
- "five", "six", "seven", "eight",
- "nine", "colon", "semicolon", "less",
- "equal", "greater", "question", "at",
- "A", "B", "C", "D",
- "E", "F", "G", "H",
- "I", "J", "K", "L",
- "M", "N", "O", "P",
- "Q", "R", "S", "T",
- "U", "V", "W", "X",
- "Y", "Z", "bracketleft", "backslash",
- "bracketright", "asciicircum", "underscore", "grave",
- "a", "b", "c", "d",
- "e", "f", "g", "h",
- "i", "j", "k", "l",
- "m", "n", "o", "p",
- "q", "r", "s", "t",
- "u", "v", "w", "x",
- "y", "z", "braceleft", "bar",
- "braceright", "asciitilde", "Adieresis", "Aring",
- "Ccedilla", "Eacute", "Ntilde", "Odieresis",
- "Udieresis", "aacute", "agrave", "acircumflex",
- "adieresis", "atilde", "aring", "ccedilla",
- "eacute", "egrave", "ecircumflex", "edieresis",
- "iacute", "igrave", "icircumflex", "idieresis",
- "ntilde", "oacute", "ograve", "ocircumflex",
- "odieresis", "otilde", "uacute", "ugrave",
- "ucircumflex", "udieresis", "dagger", "degree",
- "cent", "sterling", "section", "bullet",
- "paragraph", "germandbls", "registered", "copyright",
- "trademark", "acute", "dieresis", "notequal",
- "AE", "Oslash", "infinity", "plusminus",
- "lessequal", "greaterequal", "yen", "mu1",
- "partialdiff", "summation", "product", "pi",
- "integral", "ordfeminine", "ordmasculine", "Ohm",
- "ae", "oslash", "questiondown", "exclamdown",
- "logicalnot", "radical", "florin", "approxequal",
- "increment", "guillemotleft", "guillemotright", "ellipsis",
- "nbspace", "Agrave", "Atilde", "Otilde",
- "OE", "oe", "endash", "emdash",
- "quotedblleft", "quotedblright", "quoteleft", "quoteright",
- "divide", "lozenge", "ydieresis", "Ydieresis",
- "fraction", "currency", "guilsinglleft", "guilsinglright",
- "fi", "fl", "daggerdbl", "periodcentered",
- "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
- "Ecircumflex", "Aacute", "Edieresis", "Egrave",
- "Iacute", "Icircumflex", "Idieresis", "Igrave",
- "Oacute", "Ocircumflex", "applelogo", "Ograve",
- "Uacute", "Ucircumflex", "Ugrave", "dotlessi",
- "circumflex", "tilde", "overscore", "breve",
- "dotaccent", "ring", "cedilla", "hungarumlaut",
- "ogonek", "caron", "Lslash", "lslash",
- "Scaron", "scaron", "Zcaron", "zcaron",
- "brokenbar", "Eth", "eth", "Yacute",
- "yacute", "Thorn", "thorn", "minus",
- "multiply", "onesuperior", "twosuperior", "threesuperior",
- "onehalf", "onequarter", "threequarters", "franc",
- "Gbreve", "gbreve", "Idot", "Scedilla",
- "scedilla", "Cacute", "cacute", "Ccaron",
- "ccaron", "dmacron"
-};
-
-//------------------------------------------------------------------------
-// FoFiTrueType
-//------------------------------------------------------------------------
-
-FoFiTrueType *FoFiTrueType::make(char *fileA, int lenA) {
- FoFiTrueType *ff;
-
- ff = new FoFiTrueType(fileA, lenA, gFalse);
- if (!ff->parsedOk) {
- delete ff;
- return NULL;
- }
- return ff;
-}
-
-FoFiTrueType *FoFiTrueType::load(char *fileName) {
- 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;
-}
-
-FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA):
- FoFiBase(fileA, lenA, freeFileDataA)
-{
- tables = NULL;
- nTables = 0;
- cmaps = NULL;
- nCmaps = 0;
- nameToGID = NULL;
- parsedOk = gFalse;
-
- parse();
-}
-
-FoFiTrueType::~FoFiTrueType() {
- gfree(tables);
- gfree(cmaps);
- delete nameToGID;
-}
-
-int FoFiTrueType::getNumCmaps() {
- return nCmaps;
-}
-
-int FoFiTrueType::getCmapPlatform(int i) {
- return cmaps[i].platform;
-}
-
-int FoFiTrueType::getCmapEncoding(int i) {
- return cmaps[i].encoding;
-}
-
-int FoFiTrueType::findCmap(int platform, int encoding) {
- int i;
-
- for (i = 0; i < nCmaps; ++i) {
- if (cmaps[i].platform == platform && cmaps[i].encoding == encoding) {
- return i;
- }
- }
- return -1;
-}
-
-Gushort FoFiTrueType::mapCodeToGID(int i, int c) {
- 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;
-}
-
-int FoFiTrueType::mapNameToGID(char *name) {
- if (!nameToGID) {
- return 0;
- }
- return nameToGID->lookupInt(name);
-}
-
-int FoFiTrueType::getEmbeddingRights() {
- 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;
-}
-
-void FoFiTrueType::convertToType42(char *psName, char **encoding,
- Gushort *codeToGID,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- 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);
-}
-
-void FoFiTrueType::convertToCIDType2(char *psName,
- Gushort *cidMap, int nCIDs,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- 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);
-}
-
-void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- 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);
-}
-
-void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
- void *outputStream) {
- 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);
-}
-
-void FoFiTrueType::cvtEncoding(char **encoding,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- 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);
-}
-
-void FoFiTrueType::cvtCharStrings(char **encoding,
- Gushort *codeToGID,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- 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);
-}
-
-void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
- void *outputStream, GString *name) {
- 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);
-}
-
-void FoFiTrueType::dumpString(Guchar *s, int length,
- FoFiOutputFunc outputFunc,
- void *outputStream) {
- 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);
-}
-
-Guint FoFiTrueType::computeTableChecksum(Guchar *data, int length) {
- 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;
-}
-
-void FoFiTrueType::parse() {
- 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;
- }
-}
-
-void FoFiTrueType::readPostTable() {
- 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);
- }
- }
- }
-}
-
-int FoFiTrueType::seekTable(char *tag) {
- 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;
-}