subsetFont method

Future<FontAsset?> subsetFont({
  1. required FontAsset font,
  2. required String outputPath,
})

Calls font-subset, which transforms the font to a subsetted version at outputPath.

If the relative path is not recognized as an icon font used in the Flutter application, this returns false. If the font-subset subprocess fails, it will throw. Otherwise, it will return true.

Implementation

Future<FontAsset?> subsetFont({
  required FontAsset font,
  required String outputPath,
}) async {
  final input = File.fromUri(font.file);
  if (input.lengthSync() < 12) {
    return null;
  }
  final mimeType = mime.lookupMimeType(
    input.path,
    headerBytes: await input.openRead(0, 12).first,
  );
  if (!kTtfMimeTypes.contains(mimeType)) {
    return null;
  }
  await (_iconDataProcessing ??= _getIconData());
  assert(_iconData != null);

  final iconTreeShakerData = _iconData![font.file.path];
  if (iconTreeShakerData == null) {
    return null;
  }

  if (!fontSubset.existsSync()) {
    throw IconTreeShakerException._(
      'The font-subset utility is missing. Run "flutter doctor".',
    );
  }

  final args = <String>[outputPath, input.path];
  final requiredCodePointStrings = iconTreeShakerData.codePoints.map(
    (int codePoint) => codePoint.toString(),
  );
  final optionalCodePointStrings = iconTreeShakerData.optionalCodePoints.map(
    (int codePoint) => 'optional:$codePoint',
  );
  final codePointsString = requiredCodePointStrings
      .followedBy(optionalCodePointStrings)
      .join(' ');
  print(
    'Running font-subset: ${fontSubset.path} ${args.join(' ')}, '
    'using codepoints $codePointsString',
  );
  final fontSubsetProcess = await Process.start(fontSubset.path, args);
  try {
    fontSubsetProcess.stdin.write(codePointsString);
    await fontSubsetProcess.stdin.flush();
    await fontSubsetProcess.stdin.close();
  } on Exception {
    // handled by checking the exit code.
  }

  final code = await fontSubsetProcess.exitCode;
  if (code != 0) {
    print(await utf8.decodeStream(fontSubsetProcess.stdout));
    print(await utf8.decodeStream(fontSubsetProcess.stderr));
    throw IconTreeShakerException._(
      'Font subsetting failed with exit code $code.',
    );
  }
  print(getSubsetSummaryMessage(input, File(outputPath)));
  return FontAsset(
    file: Uri.file(outputPath),
    weight: font.weight,
    family: font.family,
    package: font.package,
  );
}