# /// script # requires-python = ">=3.11" # dependencies = [ # "brotli==1.1.0", # "fonttools==4.59.0", # ] # /// """Generate deterministic fonts for layout and system font matching tests.""" import hashlib import os from pathlib import Path from fontTools.fontBuilder import FontBuilder from fontTools.pens.ttGlyphPen import TTGlyphPen from fontTools.subset import Options, Subsetter from fontTools.ttLib import TTFont ROOT = Path(__file__).resolve().parents[1] FIXTURES = ROOT / "moli-layout" / "tests" / "fixtures" TTF_PATH = FIXTURES / "moli-ahem.ttf" SYSTEM_FONT_TTF_PATH = ROOT / "moli-system-fonts" / "tests" / "fixtures" / "moli-ahem.ttf" HEBREW_EMOJI_PATH = FIXTURES / "moli-hebrew-emoji.ttf" CJK_PATH = FIXTURES / "moli-cjk.ttf" DEJAVU_SOURCE = Path( os.environ.get( "MOLI_DEJAVU_FONT_SOURCE", "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", ) ) DROID_CJK_SOURCE = Path( os.environ.get( "MOLI_DROID_CJK_FONT_SOURCE", "/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf", ) ) DEJAVU_SOURCE_SHA256 = "57f73e11f51999432bf7ab22ce55b6f945d5eca1bf824404cfa9ec2e3718c84e" DROID_CJK_SOURCE_SHA256 = "acb6440a713d880a13a21b468ba7cd43f5a2b2934972e51be791c880730777b8" # OpenType stores seconds since 1904-01-01. This value is Unix epoch and avoids # FontTools treating a deliberately deterministic zero as a Unix timestamp. OPEN_TYPE_UNIX_EPOCH = 2_082_844_800 def empty_glyph(): pen = TTGlyphPen(None) return pen.glyph() def box_glyph(): pen = TTGlyphPen(None) pen.moveTo((0, 0)) pen.lineTo((600, 0)) pen.lineTo((600, 800)) pen.lineTo((0, 800)) pen.closePath() return pen.glyph() def build_ttf() -> None: builder = FontBuilder(1000, isTTF=True) codepoints = list(range(0x21, 0x7F)) codepoints += [0x00A0, 0x00DF] glyph_names = { codepoint: ( f"uni{codepoint:04X}" if codepoint <= 0xFFFF else f"u{codepoint:05X}" ) for codepoint in codepoints } glyph_order = [".notdef", "space", *glyph_names.values()] builder.setupGlyphOrder(glyph_order) # Keep glyph identities distinct so source/glyph assertions can distinguish # transformed characters without depending on a platform font. cmap = dict(glyph_names) cmap[0x20] = "space" builder.setupCharacterMap(cmap) glyphs = {name: box_glyph() for name in glyph_names.values()} glyphs.update({".notdef": box_glyph(), "space": empty_glyph()}) builder.setupGlyf(glyphs) builder.setupHorizontalMetrics({glyph: (600, 0) for glyph in glyph_order}) builder.setupHorizontalHeader(ascent=800, descent=-200, lineGap=0) builder.setupNameTable( { "familyName": "Moli Ahem", "styleName": "Regular", "uniqueFontIdentifier": "Moli Ahem Regular 1.0", "fullName": "Moli Ahem Regular", "psName": "MoliAhem-Regular", "version": "Version 1.000", } ) builder.setupOS2( sTypoAscender=800, sTypoDescender=-200, sTypoLineGap=0, usWinAscent=800, usWinDescent=200, sxHeight=800, sCapHeight=800, fsSelection=1 << 6, ) builder.setupPost() builder.setupMaxp() builder.setupHead(created=OPEN_TYPE_UNIX_EPOCH, modified=OPEN_TYPE_UNIX_EPOCH) builder.save(TTF_PATH) def verify_source(source: Path, expected_sha256: str) -> None: if not source.is_file(): raise SystemExit(f"required fixed-font source does not exist: {source}") actual_sha256 = hashlib.sha256(source.read_bytes()).hexdigest() if actual_sha256 != expected_sha256: raise SystemExit( f"fixed-font source hash mismatch for {source}: " f"expected {expected_sha256}, got {actual_sha256}" ) def subset_font(source: Path, output: Path, codepoints: list[int]) -> None: font = TTFont(source, recalcTimestamp=False) options = Options() options.recalc_timestamp = False options.retain_gids = False options.name_IDs = [0, 1, 2, 3, 4, 5, 6, 13, 14] subsetter = Subsetter(options=options) subsetter.populate(unicodes=codepoints) subsetter.subset(font) font["head"].created = OPEN_TYPE_UNIX_EPOCH font["head"].modified = OPEN_TYPE_UNIX_EPOCH font.save(output, reorderTables=False) def convert(flavor: str) -> None: font = TTFont(TTF_PATH, recalcTimestamp=False) font.flavor = flavor font.save(FIXTURES / f"moli-ahem.{flavor}", reorderTables=False) def main() -> None: FIXTURES.mkdir(parents=True, exist_ok=True) verify_source(DEJAVU_SOURCE, DEJAVU_SOURCE_SHA256) verify_source(DROID_CJK_SOURCE, DROID_CJK_SOURCE_SHA256) build_ttf() SYSTEM_FONT_TTF_PATH.parent.mkdir(parents=True, exist_ok=True) SYSTEM_FONT_TTF_PATH.write_bytes(TTF_PATH.read_bytes()) convert("woff") convert("woff2") subset_font(DEJAVU_SOURCE, HEBREW_EMOJI_PATH, [0x20, 0x05D0, 0x05D1, 0x1F600]) subset_font(DROID_CJK_SOURCE, CJK_PATH, [0x20, 0x4E2D, 0x6587]) if __name__ == "__main__": main()