X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=pdf2swf%2Fxpdf%2FFoFiTrueType.cc;fp=pdf2swf%2Fxpdf%2FFoFiTrueType.cc;h=46b61ec39796ea68268d2529376a06eee1869d14;hb=85c46a8011c7fd5e4bda282266006c972ea7606b;hp=a4cf43cb57e8aa640423b65f85e9161923315326;hpb=b0d012f83219d898e9cd92281d9996bc9ff13b5f;p=swftools.git diff --git a/pdf2swf/xpdf/FoFiTrueType.cc b/pdf2swf/xpdf/FoFiTrueType.cc index a4cf43c..46b61ec 100644 --- a/pdf2swf/xpdf/FoFiTrueType.cc +++ b/pdf2swf/xpdf/FoFiTrueType.cc @@ -13,6 +13,7 @@ #endif #include +#include #include "gtypes.h" #include "gmem.h" #include "GString.h" @@ -77,6 +78,10 @@ //------------------------------------------------------------------------ +#define ttcfTag 0x74746366 + +//------------------------------------------------------------------------ + struct TrueTypeTable { Guint tag; Guint checksum; @@ -102,6 +107,7 @@ struct TrueTypeLoca { #define cmapTag 0x636d6170 #define glyfTag 0x676c7966 +#define headTag 0x68656164 #define locaTag 0x6c6f6361 #define nameTag 0x6e616d65 #define postTag 0x706f7374 @@ -153,9 +159,11 @@ static T42Table t42Tables[nT42Tables] = { { "vhea", gFalse }, { "vmtx", gFalse } }; -#define t42HeadTable 3 -#define t42LocaTable 6 -#define t42GlyfTable 2 +#define t42HeadTable 3 +#define t42LocaTable 6 +#define t42GlyfTable 2 +#define t42VheaTable 9 +#define t42VmtxTable 10 //------------------------------------------------------------------------ @@ -276,7 +284,9 @@ FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA): FoFiTrueType::~FoFiTrueType() { gfree(tables); gfree(cmaps); - delete nameToGID; + if (nameToGID) { + delete nameToGID; + } } int FoFiTrueType::getNumCmaps() { @@ -432,7 +442,7 @@ void FoFiTrueType::convertToType42(char *psName, char **encoding, // write the guts of the dictionary cvtEncoding(encoding, outputFunc, outputStream); cvtCharStrings(encoding, codeToGID, outputFunc, outputStream); - cvtSfnts(outputFunc, outputStream, NULL); + cvtSfnts(outputFunc, outputStream, NULL, gFalse); // end the dictionary and define the font (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40); @@ -440,6 +450,7 @@ void FoFiTrueType::convertToType42(char *psName, char **encoding, void FoFiTrueType::convertToCIDType2(char *psName, Gushort *cidMap, int nCIDs, + GBool needVerticalMetrics, FoFiOutputFunc outputFunc, void *outputStream) { char buf[512]; @@ -540,7 +551,7 @@ void FoFiTrueType::convertToCIDType2(char *psName, (*outputFunc)(outputStream, " end readonly def\n", 19); // write the guts of the dictionary - cvtSfnts(outputFunc, outputStream, NULL); + cvtSfnts(outputFunc, outputStream, NULL, needVerticalMetrics); // end the dictionary and define the font (*outputFunc)(outputStream, @@ -549,6 +560,7 @@ void FoFiTrueType::convertToCIDType2(char *psName, } void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs, + GBool needVerticalMetrics, FoFiOutputFunc outputFunc, void *outputStream) { char buf[512]; @@ -557,7 +569,7 @@ void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs, // write the Type 42 sfnts array sfntsName = (new GString(psName))->append("_sfnts"); - cvtSfnts(outputFunc, outputStream, sfntsName); + cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics); delete sfntsName; // write the descendant Type 42 fonts @@ -620,18 +632,28 @@ void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs, } void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, - void *outputStream) { - static char cmapTab[20] = { + void *outputStream, char *name, + Gushort *codeToGID) { + // this substitute cmap table maps char codes 0000-ffff directly to + // glyphs 0000-ffff + static char cmapTab[36] = { 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 + 0, 4, // subtable format + 0, 24, // subtable length + 0, 0, // subtable version + 0, 2, // segment count * 2 + 0, 2, // 2 * 2 ^ floor(log2(segCount)) + 0, 0, // floor(log2(segCount)) + 0, 0, // 2*segCount - 2*2^floor(log2(segCount)) + (char)0xff, (char)0xff, // endCount[0] + 0, 0, // reserved + 0, 0, // startCount[0] + 0, 0, // idDelta[0] + 0, 0 // pad to a mulitple of four bytes }; static char nameTab[8] = { 0, 0, // format @@ -654,9 +676,11 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, int nZeroLengthTables; TrueTypeLoca *locaTable; TrueTypeTable *newTables; - int nNewTables, cmapIdx, cmapLen, glyfLen; + char *newNameTab, *newCmapTab; + int nNewTables, cmapIdx, cmapLen, glyfLen, newNameLen, newCmapLen, next; + Guint locaChecksum, glyfChecksum, fileChecksum; char *tableDir; - char locaBuf[4]; + char locaBuf[4], checksumBuf[4]; GBool ok; Guint t; int pos, i, j, k, n; @@ -667,7 +691,7 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, missingPost = seekTable("post") < 0; // read the loca table, check to see if it's sorted - locaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) * sizeof(TrueTypeLoca)); + locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca)); unsortedLoca = gFalse; i = seekTable("loca"); pos = tables[i].offset; @@ -710,7 +734,7 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, // if nothing is broken, just write the TTF file as is if (!missingCmap && !missingName && !missingPost && !unsortedLoca && - !badCmapLen && nZeroLengthTables == 0) { + !badCmapLen && nZeroLengthTables == 0 && !name && !codeToGID) { (*outputFunc)(outputStream, (char *)file, len); goto done1; } @@ -742,46 +766,206 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, glyfLen = pos; } + // compute checksums for the loca and glyf tables + locaChecksum = glyfChecksum = 0; + if (unsortedLoca) { + if (locaFmt) { + for (j = 0; j <= nGlyphs; ++j) { + locaChecksum += locaTable[j].newOffset; + } + } else { + for (j = 0; j <= nGlyphs; j += 2) { + locaChecksum += locaTable[j].newOffset << 16; + if (j + 1 <= nGlyphs) { + locaChecksum += locaTable[j+1].newOffset; + } + } + } + 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)) { + glyfChecksum += computeTableChecksum(file + pos + k, n); + } + } + } + } + + // construct the new name table + if (name) { + n = strlen(name); + newNameLen = (6 + 4*12 + 2 * (3*n + 7) + 3) & ~3; + newNameTab = (char *)gmalloc(newNameLen); + memset(newNameTab, 0, newNameLen); + newNameTab[0] = 0; // format selector + newNameTab[1] = 0; + newNameTab[2] = 0; // number of name records + newNameTab[3] = 4; + newNameTab[4] = 0; // offset to start of string storage + newNameTab[5] = 6 + 4*12; + next = 0; + for (i = 0; i < 4; ++i) { + newNameTab[6 + i*12 + 0] = 0; // platform ID = Microsoft + newNameTab[6 + i*12 + 1] = 3; + newNameTab[6 + i*12 + 2] = 0; // encoding ID = Unicode + newNameTab[6 + i*12 + 3] = 1; + newNameTab[6 + i*12 + 4] = 0x04; // language ID = American English + newNameTab[6 + i*12 + 5] = 0x09; + newNameTab[6 + i*12 + 6] = 0; // name ID + newNameTab[6 + i*12 + 7] = i + 1; + newNameTab[6 + i*12 + 8] = i+1 == 2 ? 0 : ((2*n) >> 8); // string length + newNameTab[6 + i*12 + 9] = i+1 == 2 ? 14 : ((2*n) & 0xff); + newNameTab[6 + i*12 + 10] = next >> 8; // string offset + newNameTab[6 + i*12 + 11] = next & 0xff; + if (i+1 == 2) { + memcpy(newNameTab + 6 + 4*12 + next, "\0R\0e\0g\0u\0l\0a\0r", 14); + next += 14; + } else { + for (j = 0; j < n; ++j) { + newNameTab[6 + 4*12 + next + 2*j] = 0; + newNameTab[6 + 4*12 + next + 2*j + 1] = name[j]; + } + next += 2*n; + } + } + } else { + newNameLen = 0; + newNameTab = NULL; + } + + // construct the new cmap table + if (codeToGID) { + newCmapLen = 44 + 256 * 2; + newCmapTab = (char *)gmalloc(newCmapLen); + newCmapTab[0] = 0; // table version number = 0 + newCmapTab[1] = 0; + newCmapTab[2] = 0; // number of encoding tables = 1 + newCmapTab[3] = 1; + newCmapTab[4] = 0; // platform ID = Microsoft + newCmapTab[5] = 3; + newCmapTab[6] = 0; // encoding ID = Unicode + newCmapTab[7] = 1; + newCmapTab[8] = 0; // offset of subtable + newCmapTab[9] = 0; + newCmapTab[10] = 0; + newCmapTab[11] = 12; + newCmapTab[12] = 0; // subtable format = 4 + newCmapTab[13] = 4; + newCmapTab[14] = 0x02; // subtable length + newCmapTab[15] = 0x20; + newCmapTab[16] = 0; // subtable version = 0 + newCmapTab[17] = 0; + newCmapTab[18] = 0; // segment count * 2 + newCmapTab[19] = 4; + newCmapTab[20] = 0; // 2 * 2 ^ floor(log2(segCount)) + newCmapTab[21] = 4; + newCmapTab[22] = 0; // floor(log2(segCount)) + newCmapTab[23] = 1; + newCmapTab[24] = 0; // 2*segCount - 2*2^floor(log2(segCount)) + newCmapTab[25] = 0; + newCmapTab[26] = 0x00; // endCount[0] + newCmapTab[27] = (char)0xff; + newCmapTab[28] = (char)0xff; // endCount[1] + newCmapTab[29] = (char)0xff; + newCmapTab[30] = 0; // reserved + newCmapTab[31] = 0; + newCmapTab[32] = 0x00; // startCount[0] + newCmapTab[33] = 0x00; + newCmapTab[34] = (char)0xff; // startCount[1] + newCmapTab[35] = (char)0xff; + newCmapTab[36] = 0; // idDelta[0] + newCmapTab[37] = 0; + newCmapTab[38] = 0; // idDelta[1] + newCmapTab[39] = 1; + newCmapTab[40] = 0; // idRangeOffset[0] + newCmapTab[41] = 4; + newCmapTab[42] = 0; // idRangeOffset[1] + newCmapTab[43] = 0; + for (i = 0; i < 256; ++i) { + newCmapTab[44 + 2*i] = codeToGID[i] >> 8; + newCmapTab[44 + 2*i + 1] = codeToGID[i] & 0xff; + } + } else { + newCmapLen = 0; + newCmapTab = NULL; + } + // 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 + // - (re)compute table checksums nNewTables = nTables - nZeroLengthTables + (missingCmap ? 1 : 0) + (missingName ? 1 : 0) + (missingPost ? 1 : 0); - newTables = (TrueTypeTable *)gmalloc(nNewTables * sizeof(TrueTypeTable)); + newTables = (TrueTypeTable *)gmallocn(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) { + if (checkRegion(tables[i].offset, newTables[i].len)) { + newTables[j].checksum = + computeTableChecksum(file + tables[i].offset, tables[i].len); + if (tables[i].tag == headTag) { + // don't include the file checksum + newTables[j].checksum -= getU32BE(tables[i].offset + 8, &ok); + } + } + if (newTables[j].tag == cmapTag && codeToGID) { + newTables[j].len = newCmapLen; + newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab, + newCmapLen); + } else 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); + newTables[j].checksum = locaChecksum; } else if (newTables[j].tag == glyfTag && unsortedLoca) { newTables[j].len = glyfLen; + newTables[j].checksum = glyfChecksum; + } else if (newTables[j].tag == nameTag && name) { + newTables[j].len = newNameLen; + newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab, + newNameLen); } ++j; } } if (missingCmap) { newTables[j].tag = cmapTag; - newTables[j].checksum = 0; //~ should compute the checksum - newTables[j].len = sizeof(cmapTab); + if (codeToGID) { + newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab, + newCmapLen); + newTables[j].len = newCmapLen; + } else { + newTables[j].checksum = computeTableChecksum((Guchar *)cmapTab, + sizeof(cmapTab)); + 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); + if (name) { + newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab, + newNameLen); + newTables[j].len = newNameLen; + } else { + newTables[j].checksum = computeTableChecksum((Guchar *)nameTab, + sizeof(nameTab)); + newTables[j].len = sizeof(nameTab); + } ++j; } if (missingPost) { newTables[j].tag = postTag; - newTables[j].checksum = 0; //~ should compute the checksum + newTables[j].checksum = computeTableChecksum((Guchar *)postTab, + sizeof(postTab)); newTables[j].len = sizeof(postTab); ++j; } @@ -835,10 +1019,38 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, } (*outputFunc)(outputStream, tableDir, 12 + nNewTables * 16); + // compute the file checksum + fileChecksum = computeTableChecksum((Guchar *)tableDir, + 12 + nNewTables * 16); + for (i = 0; i < nNewTables; ++i) { + fileChecksum += newTables[i].checksum; + } + fileChecksum = 0xb1b0afba - fileChecksum; + // write the tables for (i = 0; i < nNewTables; ++i) { - if (newTables[i].tag == cmapTag && missingCmap) { + if (newTables[i].tag == headTag) { + if (checkRegion(newTables[i].origOffset, newTables[i].len)) { + (*outputFunc)(outputStream, (char *)file + newTables[i].origOffset, 8); + checksumBuf[0] = fileChecksum >> 24; + checksumBuf[1] = fileChecksum >> 16; + checksumBuf[2] = fileChecksum >> 8; + checksumBuf[3] = fileChecksum; + (*outputFunc)(outputStream, checksumBuf, 4); + (*outputFunc)(outputStream, + (char *)file + newTables[i].origOffset + 12, + newTables[i].len - 12); + } else { + for (j = 0; j < newTables[i].len; ++j) { + (*outputFunc)(outputStream, "\0", 1); + } + } + } else if (newTables[i].tag == cmapTag && codeToGID) { + (*outputFunc)(outputStream, newCmapTab, newTables[i].len); + } else if (newTables[i].tag == cmapTag && missingCmap) { (*outputFunc)(outputStream, cmapTab, newTables[i].len); + } else if (newTables[i].tag == nameTag && name) { + (*outputFunc)(outputStream, newNameTab, newTables[i].len); } else if (newTables[i].tag == nameTag && missingName) { (*outputFunc)(outputStream, nameTab, newTables[i].len); } else if (newTables[i].tag == postTag && missingPost) { @@ -890,6 +1102,8 @@ void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, } } + gfree(newCmapTab); + gfree(newNameTab); gfree(tableDir); gfree(newTables); done1: @@ -974,7 +1188,8 @@ void FoFiTrueType::cvtCharStrings(char **encoding, } void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, - void *outputStream, GString *name) { + void *outputStream, GString *name, + GBool needVerticalMetrics) { Guchar headData[54]; TrueTypeLoca *locaTable; Guchar *locaData; @@ -984,6 +1199,28 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, Guint checksum; int nNewTables; int length, pos, glyfPos, i, j, k; + Guchar vheaTab[36] = { + 0, 1, 0, 0, // table version number + 0, 0, // ascent + 0, 0, // descent + 0, 0, // reserved + 0, 0, // max advance height + 0, 0, // min top side bearing + 0, 0, // min bottom side bearing + 0, 0, // y max extent + 0, 0, // caret slope rise + 0, 1, // caret slope run + 0, 0, // caret offset + 0, 0, // reserved + 0, 0, // reserved + 0, 0, // reserved + 0, 0, // reserved + 0, 0, // metric data format + 0, 1 // number of advance heights in vmtx table + }; + Guchar *vmtxTab; + GBool needVhea, needVmtx; + int advance; // construct the 'head' table, zero out the font checksum i = seekTable("head"); @@ -1001,7 +1238,7 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, // 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)); + locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca)); i = seekTable("loca"); pos = tables[i].offset; ok = gTrue; @@ -1031,7 +1268,7 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, } // construct the new 'loca' table - locaData = (Guchar *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2)); + locaData = (Guchar *)gmallocn(nGlyphs + 1, (locaFmt ? 4 : 2)); for (i = 0; i <= nGlyphs; ++i) { pos = locaTable[i].newOffset; if (locaFmt) { @@ -1053,6 +1290,22 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, ++nNewTables; } } + vmtxTab = NULL; // make gcc happy + advance = 0; // make gcc happy + if (needVerticalMetrics) { + needVhea = seekTable("vhea") < 0; + needVmtx = seekTable("vmtx") < 0; + if (needVhea || needVmtx) { + i = seekTable("head"); + advance = getU16BE(tables[i].offset + 18, &ok); // units per em + if (needVhea) { + ++nNewTables; + } + if (needVmtx) { + ++nNewTables; + } + } + } // construct the new table headers, including table checksums // (pad each table out to a multiple of 4 bytes) @@ -1088,6 +1341,21 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, if (checkRegion(tables[j].offset, length)) { checksum = computeTableChecksum(file + tables[j].offset, length); } + } else if (needVerticalMetrics && i == t42VheaTable) { + vheaTab[10] = advance / 256; // max advance height + vheaTab[11] = advance % 256; + length = sizeof(vheaTab); + checksum = computeTableChecksum(vheaTab, length); + } else if (needVerticalMetrics && i == t42VmtxTable) { + length = 4 + (nGlyphs - 1) * 4; + vmtxTab = (Guchar *)gmalloc(length); + vmtxTab[0] = advance / 256; + vmtxTab[1] = advance % 256; + for (j = 2; j < length; j += 2) { + vmtxTab[j] = 0; + vmtxTab[j+1] = 0; + } + checksum = computeTableChecksum(vmtxTab, length); } else if (t42Tables[i].required) { //~ error(-1, "Embedded TrueType font is missing a required table ('%s')", //~ t42Tables[i].tag); @@ -1193,6 +1461,11 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, checkRegion(tables[j].offset, tables[j].len)) { dumpString(file + tables[j].offset, tables[j].len, outputFunc, outputStream); + } else if (needVerticalMetrics && i == t42VheaTable) { + dumpString(vheaTab, length, outputFunc, outputStream); + } else if (needVerticalMetrics && i == t42VmtxTable) { + dumpString(vmtxTab, length, outputFunc, outputStream); + gfree(vmtxTab); } } } @@ -1263,17 +1536,32 @@ Guint FoFiTrueType::computeTableChecksum(Guchar *data, int length) { } void FoFiTrueType::parse() { + Guint topTag; int pos, i, j; parsedOk = gTrue; + // look for a collection (TTC) + topTag = getU32BE(0, &parsedOk); + if (!parsedOk) { + return; + } + if (topTag == ttcfTag) { + pos = getU32BE(12, &parsedOk); + if (!parsedOk) { + return; + } + } else { + pos = 0; + } + // read the table directory - nTables = getU16BE(4, &parsedOk); + nTables = getU16BE(pos + 4, &parsedOk); if (!parsedOk) { return; } - tables = (TrueTypeTable *)gmalloc(nTables * sizeof(TrueTypeTable)); - pos = 12; + tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable)); + pos += 12; for (i = 0; i < nTables; ++i) { tables[i].tag = getU32BE(pos, &parsedOk); tables[i].checksum = getU32BE(pos + 4, &parsedOk); @@ -1309,7 +1597,7 @@ void FoFiTrueType::parse() { if (!parsedOk) { return; } - cmaps = (TrueTypeCmap *)gmalloc(nCmaps * sizeof(TrueTypeCmap)); + cmaps = (TrueTypeCmap *)gmallocn(nCmaps, sizeof(TrueTypeCmap)); for (j = 0; j < nCmaps; ++j) { cmaps[j].platform = getU16BE(pos, &parsedOk); cmaps[j].encoding = getU16BE(pos + 2, &parsedOk); @@ -1343,25 +1631,45 @@ void FoFiTrueType::parse() { return; } - // read the post table - readPostTable(); + // make sure the loca table is sane (correct length and entries are + // in bounds) + i = seekTable("loca"); + if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) { + parsedOk = gFalse; + return; + } + for (j = 0; j <= nGlyphs; ++j) { + if (locaFmt) { + pos = (int)getU32BE(tables[i].offset + j*4, &parsedOk); + } else { + pos = getU16BE(tables[i].offset + j*2, &parsedOk); + } + if (pos < 0 || pos > len) { + parsedOk = gFalse; + } + } if (!parsedOk) { return; } + + // read the post table + readPostTable(); } void FoFiTrueType::readPostTable() { GString *name; int tablePos, postFmt, stringIdx, stringPos; + GBool ok; int i, j, n, m; + ok = gTrue; if ((i = seekTable("post")) < 0) { return; } tablePos = tables[i].offset; - postFmt = getU32BE(tablePos, &parsedOk); - if (!parsedOk) { - return; + postFmt = getU32BE(tablePos, &ok); + if (!ok) { + goto err; } if (postFmt == 0x00010000) { nameToGID = new GHash(gTrue); @@ -1370,9 +1678,9 @@ void FoFiTrueType::readPostTable() { } } else if (postFmt == 0x00020000) { nameToGID = new GHash(gTrue); - n = getU16BE(tablePos + 32, &parsedOk); - if (!parsedOk) { - return; + n = getU16BE(tablePos + 32, &ok); + if (!ok) { + goto err; } if (n > nGlyphs) { n = nGlyphs; @@ -1380,7 +1688,7 @@ void FoFiTrueType::readPostTable() { stringIdx = 0; stringPos = tablePos + 34 + 2*n; for (i = 0; i < n; ++i) { - j = getU16BE(tablePos + 34 + 2*i, &parsedOk); + j = getU16BE(tablePos + 34 + 2*i, &ok); if (j < 258) { nameToGID->removeInt(macGlyphNames[j]); nameToGID->add(new GString(macGlyphNames[j]), i); @@ -1389,15 +1697,14 @@ void FoFiTrueType::readPostTable() { if (j != stringIdx) { for (stringIdx = 0, stringPos = tablePos + 34 + 2*n; stringIdx < j; - ++stringIdx, stringPos += 1 + getU8(stringPos, &parsedOk)) ; - if (!parsedOk) { - return; + ++stringIdx, stringPos += 1 + getU8(stringPos, &ok)) ; + if (!ok) { + goto err; } } - m = getU8(stringPos, &parsedOk); - if (!parsedOk || !checkRegion(stringPos + 1, m)) { - parsedOk = gFalse; - return; + m = getU8(stringPos, &ok); + if (!ok || !checkRegion(stringPos + 1, m)) { + goto err; } name = new GString((char *)&file[stringPos + 1], m); nameToGID->removeInt(name); @@ -1409,9 +1716,9 @@ void FoFiTrueType::readPostTable() { } else if (postFmt == 0x00028000) { nameToGID = new GHash(gTrue); for (i = 0; i < nGlyphs; ++i) { - j = getU8(tablePos + 32 + i, &parsedOk); - if (!parsedOk) { - return; + j = getU8(tablePos + 32 + i, &ok); + if (!ok) { + goto err; } if (j < 258) { nameToGID->removeInt(macGlyphNames[j]); @@ -1419,6 +1726,14 @@ void FoFiTrueType::readPostTable() { } } } + + return; + + err: + if (nameToGID) { + delete nameToGID; + nameToGID = NULL; + } } int FoFiTrueType::seekTable(char *tag) {