📄 fofitruetype.cc
字号:
} 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); // 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 == 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) { (*outputFunc)(outputStream, postTab, newTables[i].len); } else if (newTables[i].tag == os2Tag && missingOS2) { (*outputFunc)(outputStream, os2Tab, newTables[i].len); } else if (newTables[i].tag == hheaTag && abbrevHMTX) { (*outputFunc)(outputStream, newHHEATab, newTables[i].len); } else if (newTables[i].tag == hmtxTag && abbrevHMTX) { (*outputFunc)(outputStream, newHMTXTab, 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(newHMTXTab); gfree(newHHEATab); gfree(newCmapTab); gfree(newNameTab); gfree(tableDir); gfree(newTables); done1: gfree(locaTable);}void FoFiTrueType::cvtEncoding(char **encoding, FoFiOutputFunc outputFunc, void *outputStream) { char *name; GString *buf; int i; (*outputFunc)(outputStream, "/Encoding 256 array\n", 20); if (encoding) { for (i = 0; i < 256; ++i) { if (!(name = encoding[i])) { name = ".notdef"; } buf = GString::format("dup {0:d} /", i); (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); delete buf; (*outputFunc)(outputStream, name, strlen(name)); (*outputFunc)(outputStream, " put\n", 5); } } else { for (i = 0; i < 256; ++i) { buf = GString::format("dup {0:d} /c{1:02x} put\n", i, i); (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); delete buf; } } (*outputFunc)(outputStream, "readonly def\n", 13);}void FoFiTrueType::cvtCharStrings(char **encoding, Gushort *codeToGID, FoFiOutputFunc outputFunc, void *outputStream) { char *name; GString *buf; char 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)); buf = GString::format(" {0:d} def\n", k); (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); delete buf; } } } err: (*outputFunc)(outputStream, "end readonly def\n", 17);}void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, GString *name, GBool needVerticalMetrics) { 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; 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"); 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 *)gmallocn(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 *)gmallocn(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; } } 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) 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 (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); length = 0; checksum = 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -