为你的博客制作简化字体文件TTF
通过指定 Unicode 范围裁剪 TTF 字体文件
最近尝试为博客添加自定义字体,以在不同的浏览器上实现视觉一致性。你可能已经了解了 @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 码。
要查看更多选项,请访问
实用小脚本版本 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
在Windows上运行简单脚本
基于以上bash,笔者还给出了cmd/bat版本使用
@echo off
setlocal enabledelayedexpansion
if "%~1"=="" (
echo Use VENV: .\env\Scripts\activate
echo Usage: subascii.bat ^<fontfile.otf/ttf^> [pyftsubset options...]
exit /b 1
)
set "fullname=%~nx1"
set "filename=%~n1"
set "extension=%~x1"
if /i not "%extension%"==".otf" if /i not "%extension%"==".ttf" (
echo Use VENV: .\env\Scripts\activate
echo Usage: subascii.bat ^<fontfile.otf/ttf^> [pyftsubset options...]
exit /b 1
)
:: 添加 --ignore-missing-glyphs 选项
pyftsubset "%~1" --output-file="%filename%-Sub%extension%" --unicodes=U+0000-007F --ignore-missing-glyphs %*
需要注意的是,为了方便使用添加 了--ignore-missing-glyphs
选项,这样在遇到缺失的字形时就不会报错。
功能概述
此脚本用于创建 OTF 或 TTF 字体文件的 ASCII 子集,生成的新字体仅包含基本 ASCII 字符(U+0000 - U+007F),有助于减小字体文件大小。
使用前提
Python 环境:需要安装 Python 并配置好环境变量,一般来说pip自带
Fonttools 库:需提前安装 fonttools(通过
pip install fonttools
安装)
基本用法
subascii.bat <字体文件.otf/ttf> [pyftsubset 选项...]
必选参数:
<字体文件.otf/ttf>
:指定要处理的字体文件路径(需为 OTF 或 TTF 格式)
可选参数:
[pyftsubset 选项...]
:传递给pyftsubset
命令的额外参数(例如:--desubroutinize
、--with-zopfli
等)
使用示例
简单处理:
subascii.bat C:\Fonts\SourceHanSans-Regular.otf
输出文件:
SourceHanSans-Regular-Sub.otf
带额外选项:
subascii.bat C:\Fonts\Roboto-Regular.ttf --desubroutinize --with-zopfli
输出文件:
Roboto-Regular-Sub.ttf
同时应用了额外的优化选项
输出说明
脚本会在原字体文件所在目录生成新文件,文件名格式为
原文件名-Sub.原扩展名
生成的字体仅包含 ASCII 字符集(0-127 编码范围)
注意事项
文件路径:若字体文件路径包含空格,需用双引号包裹整个路径,所以说尽量不要使用空格路径
权限问题:确保对输出目录有写入权限,尤其是服务器系统
参数传递:额外选项会直接传递给
pyftsubset
,请参考https://fonttools.readthedocs.io/en/latest/subset/index.html 获取可用选项列表
在哪里找到字体文件?
注意,字体并不总是被允许修改,请仔细查看字体使用许可证。