OpenTypeFont.createFromGlyphs constructor

OpenTypeFont.createFromGlyphs({
  1. required List<GenericGlyph> glyphList,
  2. String? fontName,
  3. String? description,
  4. Revision? revision,
  5. String? achVendID,
  6. bool? useOpenType,
  7. bool? usePostV2,
  8. bool? normalize,
})

Generates new OpenType font.

Mutates every glyph's metadata, so that it contains newly generated charcode.

  • glyphList is a list of generic glyphs. Required.
  • fontName is a font name. If null, glyph names are omitted (PostScriptV3 table is generated).
  • description is a font description for naming table.
  • revision is a font revision. Defaults to 1.0.
  • achVendID is a vendor ID in OS/2 table. Defaults to 4 spaces.
  • If useOpenType is set to true, OpenType outlines in CFF table format are generated. Otherwise, a font with TrueType outlines (TTF) is generated. Defaults to true.
  • If usePostV2 is set to true, post table of version 2 is generated (containing a name for each glyph). Otherwise, version 3 table (without glyph names) is generated. Defaults to false.
  • If normalize is set to true, glyphs are resized and centered to fit in coordinates grid (unitsPerEm). Defaults to true.

Implementation

factory OpenTypeFont.createFromGlyphs({
  required List<GenericGlyph> glyphList,
  String? fontName,
  String? description,
  Revision? revision,
  String? achVendID,
  bool? useOpenType,
  bool? usePostV2,
  bool? normalize,
}) {
  if (fontName?.isEmpty ?? false) {
    fontName = null;
  }

  revision ??= kDefaultFontRevision;
  achVendID ??= kDefaultAchVendID;
  fontName ??= kDefaultFontFamily;
  useOpenType ??= true;
  normalize ??= true;
  usePostV2 ??= false;

  glyphList = _generateCharCodes(glyphList);

  // A power of two is recommended only for TrueType outlines
  final unitsPerEm =
      useOpenType ? kDefaultOpenTypeUnitsPerEm : kDefaultTrueTypeUnitsPerEm;

  final baselineExtension = normalize ? kDefaultBaselineExtension : 0;
  final ascender = unitsPerEm - baselineExtension;
  final descender = -baselineExtension;

  final resizedGlyphList = _resizeAndCenter(
    glyphList,
    ascender: normalize ? ascender : null,
    descender: normalize ? descender : null,
    fontHeight: normalize ? null : unitsPerEm,
  );

  final defaultGlyphList = generateDefaultGlyphList(ascender);
  final fullGlyphList = [
    ...defaultGlyphList,
    ...resizedGlyphList,
  ];

  final defaultGlyphMetricsList =
      defaultGlyphList.map((g) => g.metrics).toList();

  // If normalization is off every custom glyph's size equals unitsPerEm
  final customGlyphMetricsList = normalize
      ? resizedGlyphList.map((g) => g.metrics).toList()
      : List.filled(
          resizedGlyphList.length, GenericGlyphMetrics.square(unitsPerEm));

  final glyphMetricsList = [
    ...defaultGlyphMetricsList,
    ...customGlyphMetricsList,
  ];

  final glyf = useOpenType ? null : GlyphDataTable.fromGlyphs(fullGlyphList);
  final head =
      HeaderTable.create(glyphMetricsList, glyf, revision, unitsPerEm);
  final loca = useOpenType
      ? null
      : IndexToLocationTable.create(head.indexToLocFormat, glyf!);
  final hmtx = HorizontalMetricsTable.create(glyphMetricsList, unitsPerEm);
  final hhea = HorizontalHeaderTable.create(
      glyphMetricsList, hmtx, ascender, descender);
  final post = PostScriptTable.create(resizedGlyphList, usePostV2);
  final name = NamingTable.create(fontName, description, revision);

  if (name == null) {
    throw TableDataFormatException('Unknown "name" table format');
  }

  final maxp = MaximumProfileTable.create(fullGlyphList.length, glyf);
  final cmap = CharacterToGlyphTable.create(fullGlyphList);
  final gsub = GlyphSubstitutionTable.create();
  final os2 = OS2Table.create(hmtx, head, hhea, cmap, gsub, achVendID);

  final cff =
      useOpenType ? CFF1Table.create(fullGlyphList, head, hmtx, name) : null;

  final tables = <String, FontTable>{
    if (!useOpenType) ...{
      kGlyfTag: glyf!,
      kLocaTag: loca!,
    },
    if (useOpenType) ...{
      kCFFTag: cff!,
    },
    kCmapTag: cmap,
    kMaxpTag: maxp,
    kHeadTag: head,
    kHmtxTag: hmtx,
    kHheaTag: hhea,
    kPostTag: post,
    kNameTag: name,
    kGSUBTag: gsub,
    kOS2Tag: os2,
  };

  final offsetTable = OffsetTable.create(tables.length, useOpenType);

  return OpenTypeFont(offsetTable, tables);
}