diff options
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/fofi')
-rw-r--r-- | Build/source/libs/xpdf/xpdf-src/fofi/FoFiBase.cc | 3 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-src/fofi/FoFiTrueType.cc | 34 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-src/fofi/FoFiTrueType.h | 15 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1.cc | 41 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.cc | 403 | ||||
-rw-r--r-- | Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.h | 13 |
6 files changed, 482 insertions, 27 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/fofi/FoFiBase.cc b/Build/source/libs/xpdf/xpdf-src/fofi/FoFiBase.cc index 07cc3fcd52f..e1951b08b9f 100644 --- a/Build/source/libs/xpdf/xpdf-src/fofi/FoFiBase.cc +++ b/Build/source/libs/xpdf/xpdf-src/fofi/FoFiBase.cc @@ -171,6 +171,7 @@ Guint FoFiBase::getUVarBE(int pos, int size, GBool *ok) { GBool FoFiBase::checkRegion(int pos, int size) { return pos >= 0 && - pos + size >= pos && + size >= 0 && + size <= INT_MAX - pos && pos + size <= len; } diff --git a/Build/source/libs/xpdf/xpdf-src/fofi/FoFiTrueType.cc b/Build/source/libs/xpdf/xpdf-src/fofi/FoFiTrueType.cc index 3709a1f2809..0f5b5bc7230 100644 --- a/Build/source/libs/xpdf/xpdf-src/fofi/FoFiTrueType.cc +++ b/Build/source/libs/xpdf/xpdf-src/fofi/FoFiTrueType.cc @@ -320,6 +320,7 @@ FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA, nCmaps = 0; nameToGID = NULL; isDfont = isDfontA; + isTTC = gFalse; parsedOk = gFalse; parse(fontNum, allowHeadlessCFF); @@ -985,7 +986,8 @@ void FoFiTrueType::convertToType0(char *psName, int *cidMap, int nCIDs, GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, void *outputStream, char *name, - int *codeToGID) { + int *codeToGID, Guchar *replacementCmapTable, + int replacementCmapTableLen) { // this substitute cmap table maps char code ffff to glyph 0, // with tables for MacRoman and MS Unicode static char cmapTab[44] = { @@ -1188,7 +1190,7 @@ GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, if (!missingCmap && !missingName && !missingPost && !missingOS2 && !unsortedLoca && !emptyCmap && !badCmapLen && !abbrevHMTX && nZeroLengthTables == 0 && nBogusTables == 0 && - !name && !codeToGID && !isDfont) { + !name && !codeToGID && !replacementCmapTable && !isDfont && !isTTC) { (*outputFunc)(outputStream, (char *)file, len); gfree(locaTable); return gFalse; @@ -1306,7 +1308,7 @@ GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, } // construct the new cmap table - if (codeToGID) { + if (codeToGID && !replacementCmapTable) { newCmapLen = 44 + 256 * 2; newCmapTab = (char *)gmalloc(newCmapLen); newCmapTab[0] = 0; // table version number = 0 @@ -1435,8 +1437,15 @@ GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, // don't include the file checksum newTables[j].checksum -= getU32BE(tables[i].offset + 8, &ok); } + } else { + // we'll write four zero bytes for this table + newTables[j].len = 4; } - if (newTables[j].tag == cmapTag && codeToGID) { + if (newTables[j].tag == cmapTag && replacementCmapTable) { + newTables[j].len = replacementCmapTableLen; + newTables[j].checksum = computeTableChecksum(replacementCmapTable, + replacementCmapTableLen); + } else if (newTables[j].tag == cmapTag && codeToGID) { newTables[j].len = newCmapLen; newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab, newCmapLen); @@ -1470,7 +1479,11 @@ GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, } if (missingCmap) { newTables[j].tag = cmapTag; - if (codeToGID) { + if (replacementCmapTable) { + newTables[j].checksum = computeTableChecksum(replacementCmapTable, + replacementCmapTableLen); + newTables[j].len = replacementCmapTableLen; + } else if (codeToGID) { newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab, newCmapLen); newTables[j].len = newCmapLen; @@ -1588,6 +1601,9 @@ GBool FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, (*outputFunc)(outputStream, "\0", 1); } } + } else if (newTables[i].tag == cmapTag && replacementCmapTable) { + (*outputFunc)(outputStream, (char *)replacementCmapTable, + newTables[i].len); } else if (newTables[i].tag == cmapTag && codeToGID) { (*outputFunc)(outputStream, newCmapTab, newTables[i].len); } else if (newTables[i].tag == cmapTag && missingCmap) { @@ -1816,7 +1832,8 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, } else { locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok); } - if (locaTable[i].origOffset > glyfTableLen) { + if (locaTable[i].origOffset < 0 || + locaTable[i].origOffset > glyfTableLen) { locaTable[i].origOffset = glyfTableLen; } } @@ -2172,7 +2189,9 @@ void FoFiTrueType::parse(int fontNum, GBool allowHeadlessCFF) { tables[j].checksum = getU32BE(offset + pos + 4, &parsedOk); tables[j].offset = offset + (int)getU32BE(offset + pos + 8, &parsedOk); tables[j].len = (int)getU32BE(offset + pos + 12, &parsedOk); - if (tables[j].offset + tables[j].len >= tables[j].offset && + if (tables[j].offset >= 0 && + tables[j].len >= 0 && + tables[j].offset + tables[j].len >= tables[j].offset && tables[j].offset + tables[j].len <= len) { // ignore any bogus entries in the table directory ++j; @@ -2274,6 +2293,7 @@ void FoFiTrueType::parse(int fontNum, GBool allowHeadlessCFF) { void FoFiTrueType::parseTTC(int fontNum, int *pos) { int nFonts; + isTTC = gTrue; nFonts = getU32BE(8, &parsedOk); if (!parsedOk) { return; diff --git a/Build/source/libs/xpdf/xpdf-src/fofi/FoFiTrueType.h b/Build/source/libs/xpdf/xpdf-src/fofi/FoFiTrueType.h index a0f759b2a6f..619e1bd6676 100644 --- a/Build/source/libs/xpdf/xpdf-src/fofi/FoFiTrueType.h +++ b/Build/source/libs/xpdf/xpdf-src/fofi/FoFiTrueType.h @@ -95,6 +95,9 @@ public: // for OpenType CFF fonts.) void getFontMatrix(double *mat); + // Return the number of glyphs in the font. + int getNumGlyphs() { return nGlyphs; } + // Returns true if this looks like a CJK font that uses bytecode // instructions to assemble glyphs. GBool checkForTrickyCJK(); @@ -154,10 +157,15 @@ public: // various other errors. If <name> is non-NULL, the font is renamed // to <name>. If <codeToGID> is non-NULL, the font is re-encoded, // using a Windows Unicode cmap. If <name> is NULL and the font is - // complete and correct, it will be written unmodified. (Not useful - // for OpenType CFF fonts.) Returns true if the font was modified. + // complete and correct, it will be written unmodified. If + // <replacementCmapTable> is non-NULL it will be used as the cmap + // table in the written font (overriding any existing cmap table + // and/or the codeToGID arg). (Not useful for OpenType CFF fonts.) + // Returns true if the font was modified. GBool writeTTF(FoFiOutputFunc outputFunc, void *outputStream, - char *name = NULL, int *codeToGID = NULL); + char *name = NULL, int *codeToGID = NULL, + Guchar *replacementCmapTable = NULL, + int replacementCmapTableLen = 0); // Returns a pointer to the CFF font embedded in this OpenType font. // If successful, sets *<start> and *<length>, and returns true. @@ -200,6 +208,7 @@ private: GBool openTypeCFF; GBool headlessCFF; GBool isDfont; + GBool isTTC; GBool parsedOk; }; diff --git a/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1.cc b/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1.cc index 4f5972a7bbb..0d067b5c5a9 100644 --- a/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1.cc +++ b/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1.cc @@ -99,7 +99,7 @@ void FoFiType1::writeEncoded(const char **newEncoding, // copy everything up to the encoding for (line = (char *)file; - line && strncmp(line, "/Encoding", 9); + line && line + 9 <= (char *)file + len && strncmp(line, "/Encoding", 9); line = getNextLine(line)) ; if (!line) { // no encoding - just copy the whole font file @@ -122,7 +122,8 @@ void FoFiType1::writeEncoded(const char **newEncoding, // find the end of the encoding data //~ this ought to parse PostScript tokens - if (!strncmp(line, "/Encoding StandardEncoding def", 30)) { + if (line + 30 <= (char *)file + len && + !strncmp(line, "/Encoding StandardEncoding def", 30)) { line = getNextLine(line); } else { // skip "/Encoding" + one whitespace char, @@ -144,16 +145,18 @@ void FoFiType1::writeEncoded(const char **newEncoding, // check for a second one here if (line) { for (line2 = line, i = 0; - i < 20 && line2 && strncmp(line2, "/Encoding", 9); + i < 20 && line2 && line2 + 9 <= (char *)file + len && + strncmp(line2, "/Encoding", 9); line2 = getNextLine(line2), ++i) ; if (i < 20 && line2) { (*outputFunc)(outputStream, line, (int)(line2 - line)); - if (!strncmp(line2, "/Encoding StandardEncoding def", 30)) { + if (line2 + 30 <= (char *)file + len && + !strncmp(line2, "/Encoding StandardEncoding def", 30)) { line = getNextLine(line2); } else { - // skip "/Encoding" + one whitespace char, + // skip "/Encoding", // then look for 'def' preceded by PostScript whitespace - p = line2 + 10; + p = line2 + 9; line = NULL; for (; p < (char *)file + len; ++p) { if ((*p == ' ' || *p == '\t' || *p == '\x0a' || @@ -203,9 +206,14 @@ void FoFiType1::parse() { ++i) { // get font name - if (!name && !strncmp(line, "/FontName", 9)) { - strncpy(buf, line, 255); - buf[255] = '\0'; + if (!name && line + 9 <= (char *)file + len && + !strncmp(line, "/FontName", 9)) { + n = 255; + if (line + n > (char *)file + len) { + n = (int)(((char *)file + len) - line); + } + strncpy(buf, line, n); + buf[n] = '\0'; if ((p = strchr(buf+9, '/')) && (p = strtok(p+1, " \t\n\r"))) { name = copyString(p); @@ -213,10 +221,10 @@ void FoFiType1::parse() { line = getNextLine(line); // get encoding - } else if (!encoding && + } else if (!encoding && line + 30 <= (char *)file + len && !strncmp(line, "/Encoding StandardEncoding def", 30)) { encoding = (char **)fofiType1StandardEncoding; - } else if (!encoding && + } else if (!encoding && line + 19 <= (char *)file + len && !strncmp(line, "/Encoding 256 array", 19)) { encoding = (char **)gmallocn(256, sizeof(char *)); for (j = 0; j < 256; ++j) { @@ -284,9 +292,14 @@ void FoFiType1::parse() { } //~ check for getinterval/putinterval junk - } else if (!gotMatrix && !strncmp(line, "/FontMatrix", 11)) { - strncpy(buf, line + 11, 255); - buf[255] = '\0'; + } else if (!gotMatrix && line + 11 <= (char *)file + len && + !strncmp(line, "/FontMatrix", 11)) { + n = 255; + if (line + 11 + n > (char *)file + len) { + n = (int)(((char *)file + len) - (line + 11)); + } + strncpy(buf, line + 11, n); + buf[n] = '\0'; if ((p = strchr(buf, '['))) { ++p; if ((p2 = strchr(p, ']'))) { diff --git a/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.cc b/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.cc index cdb767ae8bf..13c045f8b97 100644 --- a/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.cc +++ b/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.cc @@ -18,6 +18,7 @@ #include "gmem.h" #include "gmempp.h" #include "GString.h" +#include "GHash.h" #include "FoFiEncodings.h" #include "FoFiType1C.h" @@ -152,6 +153,23 @@ GString *FoFiType1C::getGlyphName(int gid) { return new GString(buf); } +GHash *FoFiType1C::getNameToGIDMap() { + GHash *map; + char name[256]; + GBool ok; + int gid; + + map = new GHash(gTrue); + for (gid = 0; gid < nGlyphs; ++gid) { + ok = gTrue; + getString(charset[gid], name, &ok); + if (ok) { + map->add(new GString(name), gid); + } + } + return map; +} + int *FoFiType1C::getCIDToGIDMap(int *nCIDs) { int *map; int n, i; @@ -2183,6 +2201,371 @@ void FoFiType1C::writePSString(char *s, FoFiOutputFunc outputFunc, (*outputFunc)(outputStream, buf, i); } +void FoFiType1C::convertToOpenType(FoFiOutputFunc outputFunc, + void *outputStream, + int nWidths, Gushort *widths, + Guchar *cmapTable, int cmapTableLen) { + // dummy OS/2 table (taken from FoFiTrueType::writeTTF) + static Guchar os2Tab[86] = { + 0, 1, // version + 0, 1, // xAvgCharWidth + 0x01, 0x90, // usWeightClass + 0, 5, // usWidthClass + 0, 0, // fsType + 0, 0, // ySubscriptXSize + 0, 0, // ySubscriptYSize + 0, 0, // ySubscriptXOffset + 0, 0, // ySubscriptYOffset + 0, 0, // ySuperscriptXSize + 0, 0, // ySuperscriptYSize + 0, 0, // ySuperscriptXOffset + 0, 0, // ySuperscriptYOffset + 0, 0, // yStrikeoutSize + 0, 0, // yStrikeoutPosition + 0, 0, // sFamilyClass + 0, 0, 0, 0, 0, // panose + 0, 0, 0, 0, 0, + 0, 0, 0, 0, // ulUnicodeRange1 + 0, 0, 0, 0, // ulUnicodeRange2 + 0, 0, 0, 0, // ulUnicodeRange3 + 0, 0, 0, 0, // ulUnicodeRange4 + 0, 0, 0, 0, // achVendID + 0, 0, // fsSelection + 0, 0, // usFirstCharIndex + 0, 0, // usLastCharIndex + 0, 0, // sTypoAscender + 0, 0, // sTypoDescender + 0, 0, // sTypoLineGap + 0x20, 0x00, // usWinAscent + 0x20, 0x00, // usWinDescent + 0, 0, 0, 1, // ulCodePageRange1 + 0, 0, 0, 0 // ulCodePageRange2 + }; + Guchar headTable[54], hheaTable[36], maxpTable[6]; + Guchar nameTable[26], postTable[32]; + Guchar *hmtxTable; + static const char *tableTag[9] = { + "CFF ", + "OS/2", + "cmap", + "head", + "hhea", + "hmtx", + "maxp", + "name", + "post" + }; + Guchar *tableData[9]; + int tableLength[9]; + Guchar header[12 + 9*16]; + double mat[6]; + Gushort maxWidth; + Guint checksum, fileChecksum; + int unitsPerEm, xMin, yMin, xMax, yMax, offset, i; + + //--- CFF_ table + tableData[0] = file; + tableLength[0] = len; + + //--- OS/2 table + tableData[1] = os2Tab; + tableLength[1] = 86; + + //--- cmap table + tableData[2] = cmapTable; + tableLength[2] = cmapTableLen; + + //--- head table + getFontMatrix(mat); + if (mat[0] == 0) { + unitsPerEm = 1000; + } else { + unitsPerEm = (int)(1 / mat[0] + 0.5); + } + xMin = (int)(topDict.fontBBox[0] + 0.5); + yMin = (int)(topDict.fontBBox[1] + 0.5); + xMax = (int)(topDict.fontBBox[2] + 0.5); + yMax = (int)(topDict.fontBBox[3] + 0.5); + headTable[ 0] = 0x00; // version + headTable[ 1] = 0x01; + headTable[ 2] = 0x00; + headTable[ 3] = 0x00; + headTable[ 4] = 0x00; // revision + headTable[ 5] = 0x00; + headTable[ 6] = 0x00; + headTable[ 7] = 0x00; + headTable[ 8] = 0x00; // checksumAdjustment + headTable[ 9] = 0x00; // (set later) + headTable[10] = 0x00; + headTable[11] = 0x00; + headTable[12] = 0x5f; // magicNumber + headTable[13] = 0x0f; + headTable[14] = 0x3c; + headTable[15] = 0xf5; + headTable[16] = 0x00; // flags + headTable[17] = 0x03; + headTable[18] = (Guchar)(unitsPerEm >> 8); // unitsPerEm + headTable[19] = (Guchar)unitsPerEm; + headTable[20] = 0x00; // created + headTable[21] = 0x00; + headTable[22] = 0x00; + headTable[23] = 0x00; + headTable[24] = 0x00; + headTable[25] = 0x00; + headTable[26] = 0x00; + headTable[27] = 0x00; + headTable[28] = 0x00; // modified + headTable[29] = 0x00; + headTable[30] = 0x00; + headTable[31] = 0x00; + headTable[32] = 0x00; + headTable[33] = 0x00; + headTable[34] = 0x00; + headTable[35] = 0x00; + headTable[36] = (Guchar)(xMin >> 8); // xMin + headTable[37] = (Guchar)xMin; + headTable[38] = (Guchar)(yMin >> 8); // yMin + headTable[39] = (Guchar)yMin; + headTable[40] = (Guchar)(xMax >> 8); // xMax + headTable[41] = (Guchar)xMax; + headTable[42] = (Guchar)(yMax >> 8); // yMax + headTable[43] = (Guchar)yMax; + headTable[44] = 0; // macStyle + headTable[45] = 0; + headTable[46] = 0; // lowestRecPPEM + headTable[47] = 3; + headTable[48] = 0; // fontDirectionHint + headTable[49] = 2; // (deprecated) + headTable[50] = 0; // indexToLocFormat + headTable[51] = 0; // (n/a to CFF fonts) + headTable[52] = 0; // glyphDataFormat + headTable[53] = 0; // (n/a to CFF fonts) + tableData[3] = headTable; + tableLength[3] = 54; + + //--- hhea table + maxWidth = widths[0]; + for (i = 1; i < nWidths; ++i) { + if (widths[i] > maxWidth) { + maxWidth = widths[i]; + } + } + hheaTable[ 0] = 0x00; // version + hheaTable[ 1] = 0x01; + hheaTable[ 2] = 0x00; + hheaTable[ 3] = 0x00; + hheaTable[ 4] = (Guchar)(yMax >> 8); // ascender + hheaTable[ 5] = (Guchar)yMax; + hheaTable[ 6] = (Guchar)(yMin >> 8); // descender + hheaTable[ 7] = (Guchar)yMin; + hheaTable[ 8] = 0; // lineGap + hheaTable[ 9] = 0; + hheaTable[10] = (Guchar)(maxWidth >> 8); // advanceWidthMax + hheaTable[11] = (Guchar)maxWidth; + hheaTable[12] = 0; // minLeftSideBearing + hheaTable[13] = 0; + hheaTable[14] = 0; // minRightSideBearing + hheaTable[15] = 0; + hheaTable[16] = (Guchar)(maxWidth >> 8); // xMaxExtent + hheaTable[17] = (Guchar)maxWidth; + hheaTable[18] = 0; // caretSlopeRise + hheaTable[19] = 1; + hheaTable[20] = 0; // caretSlopeRun + hheaTable[21] = 0; + hheaTable[22] = 0; // caretOffset + hheaTable[23] = 0; + hheaTable[24] = 0; // reserved + hheaTable[25] = 0; + hheaTable[26] = 0; // reserved + hheaTable[27] = 0; + hheaTable[28] = 0; // reserved + hheaTable[29] = 0; + hheaTable[30] = 0; // reserved + hheaTable[31] = 0; + hheaTable[32] = 0; // metricDataFormat + hheaTable[33] = 0; + hheaTable[34] = (Guchar)(nWidths >> 8); // numberOfHMetrics + hheaTable[35] = (Guchar)nWidths; + tableData[4] = hheaTable; + tableLength[4] = 36; + + //--- hmtx table + //~ this currently sets LSB to 0 for all glyphs + hmtxTable = (Guchar *)gmallocn(nWidths, 4); + for (i = 0; i < nWidths; ++i) { + hmtxTable[4*i ] = (Guchar)(widths[i] >> 8); + hmtxTable[4*i+1] = (Guchar)widths[i]; + hmtxTable[4*i+2] = 0; + hmtxTable[4*i+3] = 0; + } + tableData[5] = hmtxTable; + tableLength[5] = 4 * nWidths; + + //--- maxp table + maxpTable[0] = 0x00; // version = 0.5 + maxpTable[1] = 0x00; + maxpTable[2] = 0x50; + maxpTable[3] = 0x00; + maxpTable[4] = (Guchar)(nGlyphs >> 8); // numGlyphs + maxpTable[5] = (Guchar)nGlyphs; + tableData[6] = maxpTable; + tableLength[6] = 6; + + //--- name table + nameTable[ 0] = 0x00; // format + nameTable[ 1] = 0x00; + nameTable[ 2] = 0x00; // count + nameTable[ 3] = 0x01; + nameTable[ 4] = 0x00; // stringOffset + nameTable[ 5] = 0x12; + nameTable[ 6] = 0x00; // platformID + nameTable[ 7] = 0x00; + nameTable[ 8] = 0x00; // encodingID + nameTable[ 9] = 0x03; + nameTable[10] = 0x00; // languageID + nameTable[11] = 0x00; + nameTable[12] = 0x00; // nameID + nameTable[13] = 0x00; + nameTable[14] = 0x00; // length + nameTable[15] = 0x08; + nameTable[16] = 0x00; // offset + nameTable[17] = 0x00; + nameTable[18] = 0x00; // string data + nameTable[19] = (Guchar)'n'; + nameTable[20] = 0x00; + nameTable[21] = (Guchar)'o'; + nameTable[22] = 0x00; + nameTable[23] = (Guchar)'n'; + nameTable[24] = 0x00; + nameTable[25] = (Guchar)'e'; + tableData[7] = nameTable; + tableLength[7] = 26; + + //--- post table + postTable[ 0] = 0x00; // version = 3.0 + postTable[ 1] = 0x03; + postTable[ 2] = 0x00; + postTable[ 3] = 0x00; + postTable[ 4] = 0x00; // italicAngle + postTable[ 5] = 0x00; + postTable[ 6] = 0x00; + postTable[ 7] = 0x00; + postTable[ 8] = 0x00; // underlinePosition + postTable[ 9] = 0x00; + postTable[10] = 0x00; // underlineThickness + postTable[11] = 0x00; + postTable[12] = 0x00; // isFixedPitch + postTable[13] = 0x00; + postTable[14] = 0x00; + postTable[15] = 0x00; + postTable[16] = 0x00; // minMemType42 + postTable[17] = 0x00; + postTable[18] = 0x00; + postTable[19] = 0x00; + postTable[20] = 0x00; // maxMemType42 + postTable[21] = 0x00; + postTable[22] = 0x00; + postTable[23] = 0x00; + postTable[24] = 0x00; // minMemType1 + postTable[25] = 0x00; + postTable[26] = 0x00; + postTable[27] = 0x00; + postTable[28] = 0x00; // maxMemType1 + postTable[29] = 0x00; + postTable[30] = 0x00; + postTable[31] = 0x00; + tableData[8] = postTable; + tableLength[8] = 32; + + //--- header and table directory + header[ 0] = 'O'; // sfnt version + header[ 1] = 'T'; + header[ 2] = 'T'; + header[ 3] = 'O'; + header[ 4] = 0x00; // numTables + header[ 5] = 0x09; + header[ 6] = 0x00; // searchRange + header[ 7] = 0x80; + header[ 8] = 0x00; // entrySelector + header[ 9] = 0x03; + header[10] = 0x00; // rangeShift + header[11] = 0x10; + offset = 12 + 9*16; + fileChecksum = 0; + for (i = 0; i < 9; ++i) { + header[12 + i*16 + 0] = tableTag[i][0]; + header[12 + i*16 + 1] = tableTag[i][1]; + header[12 + i*16 + 2] = tableTag[i][2]; + header[12 + i*16 + 3] = tableTag[i][3]; + checksum = computeOpenTypeTableChecksum(tableData[i], tableLength[i]); + fileChecksum += checksum; + header[12 + i*16 + 4] = (Guchar)(checksum >> 24); + header[12 + i*16 + 5] = (Guchar)(checksum >> 16); + header[12 + i*16 + 6] = (Guchar)(checksum >> 8); + header[12 + i*16 + 7] = (Guchar)checksum; + header[12 + i*16 + 8] = (Guchar)(offset >> 24); + header[12 + i*16 + 9] = (Guchar)(offset >> 16); + header[12 + i*16 + 10] = (Guchar)(offset >> 8); + header[12 + i*16 + 11] = (Guchar)offset; + header[12 + i*16 + 12] = (Guchar)(tableLength[i] >> 24); + header[12 + i*16 + 13] = (Guchar)(tableLength[i] >> 16); + header[12 + i*16 + 14] = (Guchar)(tableLength[i] >> 8); + header[12 + i*16 + 15] = (Guchar)tableLength[i]; + offset += tableLength[i]; + if (tableLength[i] & 3) { + offset += 4 - (tableLength[i] & 3); + } + } + + //--- file checksum + fileChecksum += computeOpenTypeTableChecksum(header, 12 + 9*16); + fileChecksum = 0xb1b0afba - fileChecksum; + headTable[ 8] = (Guchar)(fileChecksum >> 24); + headTable[ 9] = (Guchar)(fileChecksum >> 16); + headTable[10] = (Guchar)(fileChecksum >> 8); + headTable[11] = (Guchar)fileChecksum; + + //--- write the OpenType font + (*outputFunc)(outputStream, (char *)header, 12 + 9*16); + for (i = 0; i < 9; ++i) { + (*outputFunc)(outputStream, (char *)tableData[i], tableLength[i]); + if (tableLength[i] & 3) { + (*outputFunc)(outputStream, "\0\0\0", 4 - (tableLength[i] & 3)); + } + } + + gfree(hmtxTable); +} + +Guint FoFiType1C::computeOpenTypeTableChecksum(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; +} + GBool FoFiType1C::parse() { Type1CIndex fdIdx; Type1CIndexVal val; @@ -2577,7 +2960,14 @@ void FoFiType1C::readFDSelect() { parsedOk = gFalse; return; } - memcpy(fdSelect, file + pos, nGlyphs); + for (gid0 = 0; gid0 < nGlyphs; ++gid0) { + if (file[pos + gid0] >= nFDs) { + //~ error(-1, "Bad FDSelect table in CID font"); + parsedOk = gFalse; + return; + } + fdSelect[gid0] = file[pos + gid0]; + } } else if (fdSelectFmt == 3) { nRanges = getU16BE(pos, &parsedOk); pos += 2; @@ -2590,7 +2980,7 @@ void FoFiType1C::readFDSelect() { return; } pos += 2; - if (gid0 > gid1 || gid1 > nGlyphs) { + if (gid0 > gid1 || gid1 > nGlyphs || fd >= nFDs) { //~ error(-1, "Bad FDSelect table in CID font"); parsedOk = gFalse; return; @@ -2703,10 +3093,19 @@ GBool FoFiType1C::readCharset() { if (topDict.charsetOffset == 0) { charset = fofiType1CISOAdobeCharset; + if (nGlyphs > 229) { + nGlyphs = 229; + } } else if (topDict.charsetOffset == 1) { charset = fofiType1CExpertCharset; + if (nGlyphs > 166) { + nGlyphs = 166; + } } else if (topDict.charsetOffset == 2) { charset = fofiType1CExpertSubsetCharset; + if (nGlyphs > 87) { + nGlyphs = 87; + } } else { charset = (Gushort *)gmallocn(nGlyphs, sizeof(Gushort)); for (i = 0; i < nGlyphs; ++i) { diff --git a/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.h b/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.h index ae869687898..eb75dce330d 100644 --- a/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.h +++ b/Build/source/libs/xpdf/xpdf-src/fofi/FoFiType1C.h @@ -18,6 +18,7 @@ #include "gtypes.h" #include "FoFiBase.h" +class GHash; class GString; //------------------------------------------------------------------------ @@ -169,6 +170,10 @@ public: int getNumGlyphs() { return nGlyphs; } GString *getGlyphName(int gid); + // Returns a hash mapping glyph names to GIDs. This is only useful + // with 8-bit fonts. + GHash *getNameToGIDMap(); + // Return the mapping from CIDs to GIDs, and return the number of // CIDs in *<nCIDs>. This is only useful for CID fonts. int *getCIDToGIDMap(int *nCIDs); @@ -208,6 +213,13 @@ public: void convertToType0(char *psName, int *codeMap, int nCodes, FoFiOutputFunc outputFunc, void *outputStream); + // Write an OpenType file, encapsulating the CFF font. <widths> + // provides the glyph widths (in design units) for <nWidths> glyphs. + // The cmap table must be supplied by the caller. + void convertToOpenType(FoFiOutputFunc outputFunc, void *outputStream, + int nWidths, Gushort *widths, + Guchar *cmapTable, int cmapTableLen); + private: FoFiType1C(char *fileA, int lenA, GBool freeFileDataA); @@ -224,6 +236,7 @@ private: void eexecWrite(Type1CEexecBuf *eb, const char *s); void eexecWriteCharstring(Type1CEexecBuf *eb, Guchar *s, int n); void writePSString(char *s, FoFiOutputFunc outputFunc, void *outputStream); + Guint computeOpenTypeTableChecksum(Guchar *data, int length); GBool parse(); void readTopDict(); void readFD(int offset, int length, Type1CPrivateDict *pDict); |