parseCFFTable function
dynamic
parseCFFTable(
- dynamic data,
- dynamic start,
- Font font,
- dynamic opt,
)
Implementation
parseCFFTable(data, start, Font font, opt) {
font.tables["cff"] = {};
Map<String, dynamic> header = parseCFFHeader(data, start);
Map<String, dynamic> nameIndex =
parseCFFIndex(data, header["endOffset"], bytesToString);
Map<String, dynamic> topDictIndex =
parseCFFIndex(data, nameIndex["endOffset"], null);
Map<String, dynamic> stringIndex =
parseCFFIndex(data, topDictIndex["endOffset"], bytesToString);
Map<String, dynamic> globalSubrIndex =
parseCFFIndex(data, stringIndex["endOffset"], null);
font.gsubrs = globalSubrIndex["objects"];
font.gsubrsBias = calcCFFSubroutineBias(font.gsubrs);
var topDictArray = gatherCFFTopDicts(
data, start, topDictIndex["objects"], stringIndex["objects"]);
if (topDictArray.length != 1) {
throw ('CFF table has too many fonts in \'FontSet\' - count of fonts NameIndex.length = ' +
topDictArray.length);
}
Map<String, dynamic> topDict = topDictArray[0];
font.tables["cff"]["topDict"] = topDict;
if (topDict["_privateDict"] != null) {
font.defaultWidthX = topDict["_privateDict"].defaultWidthX;
font.nominalWidthX = topDict["_privateDict"].nominalWidthX;
}
if (topDict["ros"][0] != null && topDict["ros"][1] != null) {
font.isCIDFont = true;
}
if (font.isCIDFont) {
var fdArrayOffset = topDict["fdArray"];
var fdSelectOffset = topDict["fdSelect"];
if (fdArrayOffset == 0 || fdSelectOffset == 0) {
throw ('Font is marked as a CID font, but FDArray and/or FDSelect information is missing');
}
fdArrayOffset += start;
Map<String, dynamic> fdArrayIndex = parseCFFIndex(data, fdArrayOffset, null);
var fdArray = gatherCFFTopDicts(
data, start, fdArrayIndex["objects"], stringIndex["objects"]);
topDict["_fdArray"] = fdArray;
fdSelectOffset += start;
topDict["_fdSelect"] =
parseCFFFDSelect(data, fdSelectOffset, font.numGlyphs, fdArray.length);
}
var privateDictOffset = start + topDict["private"][1];
Map<String, dynamic> privateDict = parseCFFPrivateDict(
data, privateDictOffset, topDict["private"][0], stringIndex["objects"]);
font.defaultWidthX = privateDict["defaultWidthX"];
font.nominalWidthX = privateDict["nominalWidthX"];
if (privateDict["subrs"] != 0) {
var subrOffset = privateDictOffset + privateDict["subrs"];
var subrIndex = parseCFFIndex(data, subrOffset, null);
font.subrs = subrIndex.objects;
font.subrsBias = calcCFFSubroutineBias(font.subrs);
} else {
font.subrs = [];
font.subrsBias = 0;
}
// Offsets in the top dict are relative to the beginning of the CFF data, so add the CFF start offset.
var charStringsIndex;
if (opt["lowMemory"] == true) {
charStringsIndex =
parseCFFIndexLowMemory(data, start + topDict["charStrings"]);
font.nGlyphs = charStringsIndex.offsets.length;
} else {
charStringsIndex =
parseCFFIndex(data, start + topDict["charStrings"], null);
font.nGlyphs = charStringsIndex["objects"].length;
}
var charset = parseCFFCharset(
data, start + topDict["charset"], font.nGlyphs, stringIndex["objects"]);
if (topDict["encoding"] == 0) {
// Standard encoding
font.cffEncoding = new CffEncoding(cffStandardEncoding, charset);
} else if (topDict["encoding"] == 1) {
// Expert encoding
font.cffEncoding = new CffEncoding(cffExpertEncoding, charset);
} else {
font.cffEncoding =
parseCFFEncoding(data, start + topDict["encoding"], charset);
}
// Prefer the CMAP encoding to the CFF encoding.
font.encoding = font.encoding ?? font.cffEncoding;
font.glyphs = new GlyphSet(font, null);
if (opt["lowMemory"] == true) {
font.push = (i) {
var charString = getCffIndexObject(i, charStringsIndex.offsets, data,
start + topDict["charStrings"], null);
font.glyphs
.push(i, cffGlyphLoader(font, i, parseCFFCharstring, charString));
};
} else {
for (var i = 0; i < font.nGlyphs; i += 1) {
var charString = charStringsIndex["objects"][i];
font.glyphs
.push(i, cffGlyphLoader(font, i, parseCFFCharstring, charString));
}
}
}