Files
craft-libs/crates/fonts-build/tests/fixture/subset/make-fonts.py
aiongg a414736c67 craft-fonts-build: subset_to cuts the role ui faces to the catalogs' characters at build time
The interface faces in craft-fonts are full Regular TrueType sources. With the
subset feature (build-dependencies only), Embed::subset_to cuts each one with
skera to the catalogs' characters from U+2E80 up plus CJK punctuation, kana and
full-width forms, keeping every layout feature, and embeds the cut from OUT_DIR.
for_ui without catalogs leaves the interface faces out with a warning; a CFF
interface face is an error. check_text and the catalogs warn only about
characters no embedded face covers.
2026-10-21 13:31:26 +00:00

81 lines
2.5 KiB
Python
Executable File

#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.10"
# dependencies = ["fonttools==4.67.0"]
# ///
"""Write the subsetting fixtures next to this script: Tiny-glyf.ttf (TrueType outlines) and
Tiny-cff.otf (CFF outlines). Both map the same characters, have a `vert` feature that swaps
U+300C for a vertical form, and draw every glyph as a square.
"""
from pathlib import Path
from fontTools.feaLib.builder import addOpenTypeFeaturesFromString
from fontTools.fontBuilder import FontBuilder
from fontTools.pens.t2CharStringPen import T2CharStringPen
from fontTools.pens.ttGlyphPen import TTGlyphPen
HERE = Path(__file__).resolve().parent
CMAP = {
0x20: "space",
0x41: "A",
0x3001: "uni3001",
0x300C: "uni300C",
0x3042: "uni3042",
0x4E00: "uni4E00",
0x4E01: "uni4E01",
0x4E03: "uni4E03",
0xFF01: "uniFF01",
}
GLYPHS = [".notdef", *CMAP.values(), "uni300C.vert"]
FEATURES = "languagesystem DFLT dflt;\nfeature vert { sub uni300C by uni300C.vert; } vert;\n"
# 2026-01-01, so the files are the same on every run.
TIMESTAMP = 3_850_000_000
def square(pen, size):
pen.moveTo((100, 0))
pen.lineTo((100, size))
pen.lineTo((100 + size, size))
pen.lineTo((100 + size, 0))
pen.closePath()
def build(cff: bool) -> FontBuilder:
fb = FontBuilder(1000, isTTF=not cff)
fb.setupGlyphOrder(GLYPHS)
fb.setupCharacterMap(CMAP)
if cff:
charstrings = {}
for i, name in enumerate(GLYPHS):
pen = T2CharStringPen(1000, None)
square(pen, 100 + 10 * i)
charstrings[name] = pen.getCharString()
fb.setupCFF("Tiny-Regular", {"FullName": "Tiny Regular"}, charstrings, {})
else:
glyphs = {}
for i, name in enumerate(GLYPHS):
pen = TTGlyphPen(None)
square(pen, 100 + 10 * i)
glyphs[name] = pen.glyph()
fb.setupGlyf(glyphs)
fb.setupHorizontalMetrics({name: (1000, 100) for name in GLYPHS})
fb.setupHorizontalHeader(ascent=880, descent=-120)
fb.setupNameTable({"familyName": "Tiny", "styleName": "Regular"})
fb.setupOS2(sTypoAscender=880, sTypoDescender=-120, usWinAscent=880, usWinDescent=120)
fb.setupPost()
addOpenTypeFeaturesFromString(fb.font, FEATURES)
fb.font["head"].created = TIMESTAMP
fb.font["head"].modified = TIMESTAMP
fb.font.recalcTimestamp = False
return fb
def main() -> None:
build(cff=False).save(HERE / "Tiny-glyf.ttf")
build(cff=True).save(HERE / "Tiny-cff.otf")
if __name__ == "__main__":
main()