#!/usr/bin/env python3 """Structural, shaping and deterministic-build checks for Brinewake. Run with the compiler requirements plus uharfbuzz==0.56.1 and pillow==12.3.0. Pass --proof /absolute/path.png to render an optional, public-safe proof sheet. """ import argparse import hashlib import importlib.util from pathlib import Path import subprocess import sys import tempfile from fontTools.ttLib import TTFont import uharfbuzz as hb from PIL import Image, ImageDraw, ImageFont ROOT = Path(__file__).resolve().parents[1] FONT = ROOT / 'public/fonts/brinewake-regular.ttf' WEB = FONT.with_suffix('.woff2') SOURCE = ROOT / 'scripts/generate-brinewake-font.py' FILES = [FONT, WEB, ROOT / 'public/fonts/brinewake-source.py'] def digest(): return [hashlib.sha256(p.read_bytes()).hexdigest() for p in FILES] before = digest() subprocess.run([sys.executable, str(SOURCE)], check=True) assert before == digest(), 'Rebuild changed tracked font output' assert SOURCE.read_bytes() == FILES[2].read_bytes(), 'Download source differs' with tempfile.TemporaryDirectory(prefix='brinewake-download-') as directory: folder = Path(directory) downloaded = folder / 'brinewake-source.py' downloaded.write_bytes(FILES[2].read_bytes()) subprocess.run([sys.executable, str(downloaded)], check=True, cwd=folder) assert (folder / FONT.name).read_bytes() == FONT.read_bytes() assert (folder / WEB.name).read_bytes() == WEB.read_bytes() expected = set(range(32, 127)) | {160, 8211, 8212, 8216, 8217, 8220, 8221, 8230} tt = TTFont(FONT) web = TTFont(WEB) assert set(tt.getBestCmap()) == expected assert tt.getBestCmap() == web.getBestCmap() assert tt['name'].getDebugName(1) == 'Brinewake' for font_file in (tt, web): assert 'Designed with Co and Letta Code.' in font_file['name'].getDebugName(10) assert all('Astra' not in record.toUnicode() for record in font_file['name'].names) assert 'Designed with Co and Letta Code' in (ROOT / 'public/fonts/brinewake-license.txt').read_text() assert tt['OS/2'].fsType == 0 assert tt['OS/2'].sCapHeight == 700 assert tt['OS/2'].sxHeight == 490 for code, name in tt.getBestCmap().items(): glyph = tt['glyf'][name] assert glyph.compile(tt['glyf']) == web['glyf'][name].compile(web['glyf']), name advance, lsb = tt['hmtx'][name] assert advance > 0, name if code in (32, 160): assert glyph.numberOfContours == 0 else: assert glyph.numberOfContours > 0, name assert -270 <= glyph.yMin < glyph.yMax <= 820, (name, glyph.yMin, glyph.yMax) assert glyph.xMax <= advance + 20, (name, glyph.xMax, advance) assert lsb == glyph.xMin for upper in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ': assert tt['glyf'][upper].compile(tt['glyf']) != tt['glyf'][upper.lower()].compile(tt['glyf']) face = hb.Face(FONT.read_bytes()) font = hb.Font(face) font.scale = (1000, 1000) def shape(text, kern=True): buf=hb.Buffer(); buf.add_str(text); buf.guess_segment_properties() hb.shape(font, buf, {'kern': kern}) return buf for text in ['Brinewake', 'Soft water. Sharp stone.', 'Hamburgefontsiv', 'AVATAR To Wa Yo ffl fj gy pq', '“An ebb, a swell; a shore.”', ''.join(chr(c) for c in sorted(expected))]: buf=shape(text) assert all(g.codepoint != 0 for g in buf.glyph_infos), text assert all(p.x_advance > 0 for p in buf.glyph_positions), text for pair in ['AV', 'To', 'Wa', 'Yo', 'ov', 'fi']: on=sum(p.x_advance for p in shape(pair).glyph_positions) off=sum(p.x_advance for p in shape(pair, False).glyph_positions) assert on < off, (pair,on,off) # The font advertises fallback honestly, not a substituted fake accent. assert shape('é').glyph_infos[0].codepoint == 0 spec=importlib.util.spec_from_file_location('brinewake_source', SOURCE) module=importlib.util.module_from_spec(spec);spec.loader.exec_module(module) for text in ['Brinewake', 'Soft water. Sharp stone.', 'Hamburgefontsiv', 'AVATAR To Wa Yo ffl fj gy pq']: run=shape(text); x=0; previous=None for c,pos in zip(text,run.glyph_positions): g=module.move(module.G[c][0],x) if previous is not None: assert g.intersection(previous).area < 1, f'Colliding outlines in {text}: {c}' previous=g;x+=pos.x_advance args=argparse.ArgumentParser();args.add_argument('--proof', type=Path);opt=args.parse_args() if opt.proof: im=Image.new('RGB',(1800,1950),'#ede9df');d=ImageDraw.Draw(im) y=30 for size,text in [(170,'Brinewake'),(110,'Soft water. Sharp stone.'),(100,'Hamburgefontsiv'), (82,'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),(100,'abcdefghijklmnopqrstuvwxyz'), (100,'0123456789 & @ ? !'),(100,'AVATAR To Wa Yo ffl fj gy pq'), (72,'“An ebb, a swell; a shore.”'),(48,'Brinewake moves between a cut and a curve.'), (32,'Minimum recommended size: 32 pixels. Soft water, sharp stone.'), (150,'a e s g R &'),(88,'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'), (90,'00112233445566778899')]: f=ImageFont.truetype(str(FONT),size) d.text((35,y),text,font=f,fill='#163b39') y+=size*1.32 im.save(opt.proof) print('PASS: 103-character cmap; distinct cases; bounded outlines; TTF/WOFF2 parity;') print(' HarfBuzz coverage + kerning; proof-word noncollision; byte-identical rebuild.') print('TTF SHA256', digest()[0]) print('WOFF2 SHA256', digest()[1])