""" Generate @font-face settings to help make the fallback font look similar to the non-fallback font. Genererated by ChatGTP 5.2-instant. Not human-modified. """ from fontTools.ttLib import TTFont USE_TYPO_METRICS = 1 << 7 def get_metrics(path): font = TTFont(path) head = font["head"] os2 = font["OS/2"] hhea = font["hhea"] use_typo = bool(os2.fsSelection & USE_TYPO_METRICS) if use_typo: asc = os2.sTypoAscender desc = os2.sTypoDescender gap = os2.sTypoLineGap source = "OS/2.sTypo*" else: asc = hhea.ascent desc = -hhea.descent gap = hhea.lineGap source = "hhea.*" # x-height ALWAYS comes from OS/2 if not hasattr(os2, "sxHeight") or os2.sxHeight <= 0: raise ValueError(f"{path} has no usable sxHeight") x_height = os2.sxHeight print("Source", path, source) return { "unitsPerEm": head.unitsPerEm, "ascender": asc, "descender": desc, "lineGap": gap, "xHeight": x_height, } def compute_overrides(target, fallback): # size-adjust: match x-height size_adjust = ( (target["xHeight"] / target["unitsPerEm"]) / (fallback["xHeight"] / fallback["unitsPerEm"]) ) # overrides: force target vertical metrics ascent_override = target["ascender"] / target["unitsPerEm"] descent_override = abs(target["descender"]) / target["unitsPerEm"] line_gap_override = target["lineGap"] / target["unitsPerEm"] return { "size_adjust": size_adjust * 100, "ascent_override": ascent_override * 100, "descent_override": descent_override * 100, "line_gap_override": line_gap_override * 100, } def emit_css(family_name, local_name, values): return f""" @font-face {{ font-family: "{family_name}"; src: local("{local_name}"); size-adjust: {values['size_adjust']:.2f}%; ascent-override: {values['ascent_override']:.2f}%; descent-override: {values['descent_override']:.2f}%; line-gap-override: {values['line_gap_override']:.2f}%; }} """.strip() # ---- Example usage ---- target = get_metrics("static/fonts/gen/Lora-Regular.woff2") fallback = get_metrics("/System/Library/Fonts/Supplemental/Times New Roman.ttf") values = compute_overrides(target, fallback) print(emit_css( family_name="Lora Fallback", local_name="Times New Roman", values=values, ))