#!/usr/bin/env python3 """Write common/lib/wordmarkMetrics.ts: the advance of each Latin character Archivo maps, at the wordmark's two instances (wdth 118; wght 720 for the lead, 380 for the suffix), measured from the vendored variable font (umtool/report-to-video/fonts/Archivo[wdth,wght].ttf, the same bytes the video lockup is outlined from). The export header reserves the wordmark's width from this table (common/lib/wordmarkWidth.ts), so whether a title fits beside the header's icons is decided by the display face's widths, before and after the web font loads: the fallback face is narrower, and a title that fitted in it would otherwise show and then vanish when Archivo arrived. python3 common/bin/gen-wordmark-metrics.py # rewrite the module python3 common/bin/gen-wordmark-metrics.py --stdout # print it Needs fontTools (pip install fonttools). The module records the fontTools version it was generated with. """ import hashlib import json import os import sys import fontTools from fontTools.ttLib import TTFont from fontTools.varLib import instancer HERE = os.path.dirname(os.path.abspath(__file__)) REPO = os.path.normpath(os.path.join(HERE, "..", "..")) FONT = "Archivo[wdth,wght].ttf" FONT_PATH = os.path.join(REPO, "umtool", "report-to-video", "fonts", FONT) OUT = os.path.join(REPO, "common", "lib", "wordmarkMetrics.ts") WEIGHTS = (720, 380) WDTH = 118 # Basic Latin, Latin-1 and Latin Extended-A: what a site's title is written in. WANT = [cp for a, b in ((32, 126), (160, 383)) for cp in range(a, b + 1)] def runs(cps): out = [] for cp in cps: if out and cp == out[-1][1] + 1: out[-1][1] = cp else: out.append([cp, cp]) return out def wrap(values, indent=" ", width=100): lines, line = [], "" for v in values: s = f"{v}," if line and len(indent) + len(line) + 1 + len(s) > width: lines.append(indent + line) line = s else: line = f"{line} {s}" if line else s if line: lines.append(indent + line) return "\n".join(lines) def build(): raw = open(FONT_PATH, "rb").read() sha = hashlib.sha256(raw).hexdigest() base = TTFont(FONT_PATH) upm = base["head"].unitsPerEm mapped = base.getBestCmap() cps = [cp for cp in WANT if cp in mapped] adv = {} for w in WEIGHTS: inst = instancer.instantiateVariableFont(TTFont(FONT_PATH), {"wght": w, "wdth": WDTH}) cmap = inst.getBestCmap() hmtx = inst["hmtx"].metrics adv[w] = [hmtx[cmap[cp]][0] for cp in cps] parts = [ "// GENERATED by common/bin/gen-wordmark-metrics.py -- do not edit; re-run it.", "//", f"// The advance, in font units, of each Latin character {FONT} maps, at the", f"// wordmark's instances (wdth {WDTH}; wght {' and '.join(map(str, WEIGHTS))}):", "// what lib/wordmarkWidth.ts reserves a title's width by.", "export const WORDMARK_METRICS = {", f" font: {json.dumps(FONT)},", f" sha256: {json.dumps(sha)},", f" fontTools: {json.dumps(fontTools.version)},", f" unitsPerEm: {upm},", f" wdth: {WDTH},", " // [first, last] codepoint ranges; the advances below follow them in order.", " ranges: [", wrap([f"[{a}, {b}]" for a, b in runs(cps)], indent=" "), " ] as ReadonlyArray,", " advances: {", ] for w in WEIGHTS: parts.append(f" {w}: [") parts.append(wrap(adv[w])) parts.append(" ],") parts += [" } as Readonly>,", "};", ""] return "\n".join(parts) if __name__ == "__main__": text = build() if "--stdout" in sys.argv[1:]: sys.stdout.write(text) else: with open(OUT, "w") as f: f.write(text) print(f"wrote {os.path.relpath(OUT)}")