📄 fofitruetype.cc
字号:
} 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); } else if (needVerticalMetrics && i == t42VheaTable) { dumpString(vheaTab, length, outputFunc, outputStream); } else if (needVerticalMetrics && i == t42VmtxTable) { dumpString(vmtxTab, length, outputFunc, outputStream); gfree(vmtxTab); } } } } // end the sfnts array (*outputFunc)(outputStream, "] def\n", 6); gfree(locaData); gfree(locaTable);}void FoFiTrueType::dumpString(Guchar *s, int length, FoFiOutputFunc outputFunc, void *outputStream) { GString *buf; int pad, i, j; (*outputFunc)(outputStream, "<", 1); for (i = 0; i < length; i += 32) { for (j = 0; j < 32 && i+j < length; ++j) { buf = GString::format("{0:02x}", s[i+j] & 0xff); (*outputFunc)(outputStream, buf->getCString(), buf->getLength()); delete 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() { Guint topTag; int pos, ver, 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; } // check the sfnt version ver = getU32BE(pos, &parsedOk); if (!parsedOk) { return; } openTypeCFF = ver == 0x4f54544f; // 'OTTO' // read the table directory nTables = getU16BE(pos + 4, &parsedOk); if (!parsedOk) { return; } 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); 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("maxp") < 0 || seekTable("hmtx") < 0 || (!openTypeCFF && seekTable("loca") < 0) || (!openTypeCFF && seekTable("glyf") < 0) || (openTypeCFF && seekTable("CFF ") < 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 *)gmallocn(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; } // make sure the loca table is sane (correct length and entries are // in bounds) if (!openTypeCFF) { i = seekTable("loca"); if (tables[i].len < 0) { parsedOk = gFalse; return; } if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) { nGlyphs = tables[i].len / (locaFmt ? 4 : 2) - 1; } 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, &ok); if (!ok) { goto err; } 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, &ok); if (!ok) { goto err; } if (n > nGlyphs) { n = nGlyphs; } stringIdx = 0; stringPos = tablePos + 34 + 2*n; for (i = 0; i < n; ++i) { j = getU16BE(tablePos + 34 + 2*i, &ok); 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, &ok)) ; if (!ok) { goto err; } } m = getU8(stringPos, &ok); if (!ok || !checkRegion(stringPos + 1, m)) { goto err; } 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, &ok); if (!ok) { goto err; } if (j < 258) { nameToGID->removeInt(macGlyphNames[j]); nameToGID->add(new GString(macGlyphNames[j]), i); } } } return; err: if (nameToGID) { delete nameToGID; nameToGID = NULL; }}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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -