更新:23/10/25 更新脚本,保留更多字体细节

更新:23/07/26 补充一个实用小脚本

最近尝试为博客添加自定义字体,以在不同的浏览器上实现视觉一致性。你可能已经了解了 @font-face 这个 CSS 属性:

@font-face {
  font-family: "FontName";
  src: url("/assets/FontFile.ttf");
}

但是在某些特定情况下,我们只需要字体文件的一小部分(英文字母或某些特殊符号),但是字体创建者没有提供小字体集版本。

简易方法

我们可以使用 Python fontTools 库手动减少字体文件大小,这个工具专注于合并、裁剪子集和转换字体文件。对于减小字体文件大小的场景,可以使用这个库提供的 pyftsubset 命令,最简单的方法是:

# 安装 fonttools,我使用的是 4.32.0 版本。
pip install fonttools
pyftsubset Input.ttf --output-file=Output.ttf --unicodes=U+0000-007F

两个基本的参数含义分别为:

--output-file=:输出文件名。

--unicodes=:以十六进制数字指定 Unicode 范围。比如 U+0000-0007F 表示 ASCII 码。

要查看更多选项,请访问 fontTools 文档

实用小脚本版本 2(23.10.25 更新)

下方的脚本补充了更丰富的参数,使用方法同版本 1,区别在于可以保留 Features 和一些必要的扩展字符集合等等,最终文件会略大一些。如果只是简易的裁剪,仍然推荐使用版本 1

#!/bin/bash

if [[ $# -lt 1 || !($1 == *.otf || $1 == *.ttf) ]]; then
  echo "Use VENV: source ./env/bin/activate"
  echo "Usage: subascii <fontfile.otf/ttf> [pyftsubset options...]"
  exit 1
fi

filename=$(basename -- "$1")
extension="${filename##*.}"
filename="${filename%.*}"

pyftsubset "$1" --output-file="${filename}-Sub.${extension}" --unicodes="U+0000-007F" "${@:2}" \
  --layout-features='*' --glyph-names --symbol-cmap --legacy-cmap \
  --notdef-glyph --notdef-outline --recommended-glyphs \
  --name-IDs='*' --name-legacy --name-languages='*'

实用小脚本版本 1(2023.07.26 更新)

分享一个小脚本,要求已经安装fonttools,运行后会产生一个 ASCII 子集的新文件,文件名结尾加-Sub

用法举例:./subascii.sh Rubik.ttf 得到 Rubik-sub.ttf

下面的保存为subascii.sh

#!/bin/bash

if [[ $# -lt 1 || !($1 == *.otf || $1 == *.ttf) ]]; then
  echo "Use VENV: source ./env/bin/activate"
  echo "Usage: subascii <fontfile.otf/ttf> [pyftsubset options...]"
  exit 1
fi

filename=$(basename -- "$1")
extension="${filename##*.}"
filename="${filename%.*}"

pyftsubset "$1" --output-file="${filename}-Sub.${extension}" --unicodes=U+0000-007F "${@:2}"

实际效果

这个结果可能没有实际意义,因为它取决于指定的 Unicode 范围大小,以及具体参数配置。以下是基于 RobotoCondensed-Bold.ttf 裁剪后的比对。

Input.ttf   162K
Output.ttf   22K

在哪里找到字体文件?

注意,字体并不总是被允许修改,请仔细查看字体使用许可证。

在哪里找到 Unicode 编码?