6fc032bac8
生产 PangolinFonts.useBundled=true,离线可用,不再运行时拉 google_fonts; 中文经 fontFamilyFallback=[Noto Sans SC] 兜底,子集外字符再兜系统 CJK 字体。 - 拉丁:Sora/Manrope/JetBrains Mono 静态权重(复用 test/fonts)。 - 中文:Noto Sans SC 变量字体 instance 到 Regular + subset 到 GB2312 6763 字 (单权重,粗体引擎合成),client/fonts 合计约 3.4MB。 - tools/fonts/make-cjk-subset.sh 可复现生成(GB2312 字表无需联网)。 - 新增 test/unit/fonts_test.dart 锁定接线;golden 因 notdef 占位字形微调已更新。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
68 lines
2.4 KiB
Bash
68 lines
2.4 KiB
Bash
#!/usr/bin/env bash
|
||
# 生成 Noto Sans SC 子集,用于 client 离线打包(全平台)。
|
||
#
|
||
# 策略:GB2312 一级+二级常用字(6763 字,经 Python 编解码确定性生成,无需联网)
|
||
# ∪ 仓库 client/lib 实际用到的 CJK 字符 → 子集字表;
|
||
# 源用 Noto Sans CJK SC 变量字体,先 instance 到 Regular(wght=400)再 subset
|
||
# (变量 CFF2 的字重轴体积很大;单 Regular 静态 + 引擎合成粗体,显著缩小)。
|
||
# 产物:client/fonts/NotoSansSC-Regular-subset.otf (~3MB,6763 字)。
|
||
#
|
||
# 依赖:python3 + fonttools(pip install fonttools brotli)。
|
||
# 用法:bash tools/fonts/make-cjk-subset.sh
|
||
set -euo pipefail
|
||
cd "$(dirname "$0")/../.." # 仓库根
|
||
|
||
SRC_DIR="tools/fonts/_src"
|
||
CHARS="tools/fonts/common-hanzi.txt"
|
||
OUT="client/fonts/NotoSansSC-Regular-subset.otf"
|
||
mkdir -p "$SRC_DIR"
|
||
|
||
# fonttools:优先用隔离 venv(避免污染系统 python),否则用 python3 -m。
|
||
PY="python3"
|
||
SUB="python3 -m fontTools.subset"
|
||
if [ -x "/tmp/fonttools-venv/bin/python" ]; then
|
||
PY="/tmp/fonttools-venv/bin/python"
|
||
SUB="/tmp/fonttools-venv/bin/pyftsubset"
|
||
fi
|
||
|
||
# 1) 字表:GB2312 6763 常用字 ∪ 仓库实际用字。
|
||
"$PY" - "$CHARS" <<'PYGEN'
|
||
import sys, glob
|
||
chars=set()
|
||
for hi in range(0xB0,0xF8):
|
||
for lo in range(0xA1,0xFF):
|
||
try:
|
||
ch=bytes([hi,lo]).decode('gb2312')
|
||
if '一'<=ch<='鿿': chars.add(ch)
|
||
except UnicodeDecodeError:
|
||
pass
|
||
# 仓库实际用到的 CJK(确保 UI/l10n 文案一定在子集内)
|
||
for path in glob.glob('client/lib/**/*.dart', recursive=True):
|
||
try:
|
||
for ch in open(path,encoding='utf-8').read():
|
||
if '一'<=ch<='鿿': chars.add(ch)
|
||
except (UnicodeDecodeError,OSError):
|
||
pass
|
||
open(sys.argv[1],'w',encoding='utf-8').write(''.join(sorted(chars)))
|
||
print('charset hanzi:',len(chars))
|
||
PYGEN
|
||
|
||
# 2) 源字体(变量 OTF);若已存在则跳过。失效时换 google/fonts 或 notofonts 最新路径。
|
||
SRC_TTF="$SRC_DIR/NotoSansSC.ttf"
|
||
if [ ! -f "$SRC_TTF" ]; then
|
||
curl -fsSL "https://github.com/notofonts/noto-cjk/raw/main/Sans/Variable/OTF/NotoSansCJKsc-VF.otf" -o "$SRC_TTF"
|
||
fi
|
||
|
||
# 3) instance 到 Regular(wght=400)。
|
||
STATIC="$SRC_DIR/NotoSC-Regular.otf"
|
||
"$PY" -m fontTools.varLib.instancer "$SRC_TTF" wght=400 -o "$STATIC" --quiet
|
||
|
||
# 4) subset(不用 --retain-gids,否则保留全部原 gid 致体积暴涨)。
|
||
"$SUB" "$STATIC" \
|
||
--text-file="$CHARS" \
|
||
--output-file="$OUT" \
|
||
--layout-features='*' \
|
||
--name-IDs='*'
|
||
|
||
ls -la "$OUT"
|