# /// script # requires-python = ">=3.11" # dependencies = [ # "brotli==1.1.0", # "fonttools==4.59.0", # ] # /// """Generate the deterministic fixed fonts used by Phase 3 layout 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" 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() 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()