feat(client): 字体改本地打包(拉丁全量 + Noto Sans SC GB2312 子集)

生产 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>
This commit is contained in:
wangjia
2026-06-22 07:48:21 +08:00
parent 14498a3ccd
commit 6fc032bac8
19 changed files with 163 additions and 7 deletions
+8 -5
View File
@@ -154,12 +154,14 @@ class PangolinFonts {
static const cjk = 'Noto Sans SC';
static const mono = 'JetBrains Mono';
/// 测试钩子:true 时用 bundled familytest/fonts/ 经 FontLoader 注册),不走 google_fonts
static bool useBundled = false;
/// 生产默认 true:用本地打包 ttfpubspec fonts: 段),离线可用,不走 google_fonts
/// 运行时拉取。测试态由 flutter_test_config.dart 经 FontLoader 注册 test/fonts/。
/// 中文经 [cjk]Noto Sans SC 子集)走 fontFamilyFallback;子集外字符再兜系统 CJK 字体。
static bool useBundled = true;
static TextStyle sora({double? fontSize, FontWeight? fontWeight, double? height, double? letterSpacing}) =>
useBundled
? TextStyle(fontFamily: display, fontSize: fontSize, fontWeight: fontWeight, height: height, letterSpacing: letterSpacing)
? TextStyle(fontFamily: display, fontFamilyFallback: const [cjk], fontSize: fontSize, fontWeight: fontWeight, height: height, letterSpacing: letterSpacing)
: GoogleFonts.sora(fontSize: fontSize, fontWeight: fontWeight, height: height, letterSpacing: letterSpacing);
static TextStyle manrope(
@@ -167,6 +169,7 @@ class PangolinFonts {
useBundled
? TextStyle(
fontFamily: sans,
fontFamilyFallback: const [cjk],
fontSize: fontSize,
fontWeight: fontWeight,
height: height,
@@ -177,11 +180,11 @@ class PangolinFonts {
static TextStyle jetBrainsMono({double? fontSize, FontWeight? fontWeight, List<FontFeature>? fontFeatures}) =>
useBundled
? TextStyle(fontFamily: mono, fontSize: fontSize, fontWeight: fontWeight, fontFeatures: fontFeatures)
? TextStyle(fontFamily: mono, fontFamilyFallback: const [cjk], fontSize: fontSize, fontWeight: fontWeight, fontFeatures: fontFeatures)
: GoogleFonts.jetBrainsMono(fontSize: fontSize, fontWeight: fontWeight, fontFeatures: fontFeatures);
static TextTheme manropeTextTheme(TextTheme base) =>
useBundled ? base.apply(fontFamily: sans) : GoogleFonts.manropeTextTheme(base);
useBundled ? base.apply(fontFamily: sans, fontFamilyFallback: const [cjk]) : GoogleFonts.manropeTextTheme(base);
}
/// ── Type scale ──────────────────────────────────────────────────────