parseCFFTable function

dynamic parseCFFTable(
  1. dynamic data,
  2. dynamic start,
  3. Font font,
  4. 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));
    }
  }
}