返回 CodeWhale
subset-shannon-sans.py
根目录 / web / scripts / subset-shannon-sans.py
1 #!/usr/bin/env python3
2 """Split ShannonSans-Variable.woff2 into a Latin face and an "extended" face.
3
4 The full variable font is ~531 KB. Nearly every page only needs Latin, so the
5 site preloads the Latin subset and lets the browser fetch the extended subset
6 only when a page actually contains a glyph in its unicode-range (latin-ext,
7 Greek, Cyrillic, Devanagari, ...). Both subsets keep the wght axis and every
8 OpenType layout feature.
9
10 The pinned full font stays in public/brand/fonts/ as the source of truth
11 (see lib/public-auth-routes.test.ts); rerun this after replacing it:
12
13 python3 web/scripts/subset-shannon-sans.py
14
15 Needs fontTools with the brotli module (pip install fonttools brotli). The
16 ranges printed at the end must match the `unicode-range` declarations in
17 app/[locale]/layout.tsx.
18 """
19 from __future__ import annotations
20
21 from pathlib import Path
22
23 from fontTools import subset
24 from fontTools.ttLib import TTFont
25
26 FONTS = Path(__file__).resolve().parent.parent / "public" / "brand" / "fonts"
27 SOURCE = FONTS / "ShannonSans-Variable.woff2"
28
29 # Google Fonts' "latin" range plus the arrows and minus/division signs the
30 # site's copy uses, so a plain English page never needs the second file.
31 LATIN = (
32 [(0x0000, 0x00FF), (0x0131, 0x0131), (0x0152, 0x0153), (0x02BB, 0x02BC)]
33 + [(0x02C6, 0x02C6), (0x02DA, 0x02DA), (0x02DC, 0x02DC), (0x0304, 0x0304)]
34 + [(0x0308, 0x0308), (0x0329, 0x0329), (0x2000, 0x206F), (0x20AC, 0x20AC)]
35 + [(0x2122, 0x2122), (0x2190, 0x2199), (0x2212, 0x2215), (0xFEFF, 0xFEFF)]
36 + [(0xFFFD, 0xFFFD)]
37 )
38
39
40 def in_ranges(cp: int, ranges: list[tuple[int, int]]) -> bool:
41 return any(lo <= cp <= hi for lo, hi in ranges)
42
43
44 def to_ranges(cps: list[int]) -> list[tuple[int, int]]:
45 out: list[tuple[int, int]] = []
46 for cp in sorted(cps):
47 if out and cp == out[-1][1] + 1:
48 out[-1] = (out[-1][0], cp)
49 else:
50 out.append((cp, cp))
51 return out
52
53
54 def css_range(ranges: list[tuple[int, int]]) -> str:
55 return ", ".join(
56 f"U+{lo:04X}" if lo == hi else f"U+{lo:04X}-{hi:04X}" for lo, hi in ranges
57 )
58
59
60 def write_subset(unicodes: list[int], dest: Path) -> None:
61 options = subset.Options()
62 options.flavor = "woff2"
63 options.layout_features = ["*"]
64 options.name_IDs = ["*"]
65 options.name_languages = ["*"]
66 options.notdef_outline = True
67 options.glyph_names = False
68 font = TTFont(SOURCE)
69 subsetter = subset.Subsetter(options)
70 subsetter.populate(unicodes=unicodes)
71 subsetter.subset(font)
72 font.save(dest)
73
74
75 def main() -> None:
76 cmap = TTFont(SOURCE).getBestCmap()
77 latin = [cp for cp in cmap if in_ranges(cp, LATIN)]
78 ext = [cp for cp in cmap if not in_ranges(cp, LATIN)]
79 write_subset(latin, FONTS / "ShannonSans-Variable-latin.woff2")
80 write_subset(ext, FONTS / "ShannonSans-Variable-ext.woff2")
81 print("latin unicode-range:", css_range(LATIN))
82 print("ext unicode-range: ", css_range(to_ranges(ext)))
83
84
85 if __name__ == "__main__":
86 main()
87
87 lines PYTHON