#!/usr/bin/env python3
"""build_custom_font.py - graft the BLACK STAR (U+2605) into Noto Color Emoji.

Produces the never-tofu master font: every Noto Color Emoji glyph PLUS a real
outline glyph for U+2605, donated from Dela Gothic One. The star lives in `glyf`
only (no COLR layer), so it renders in currentColor (a themed/black star) while
the emoji keep their color. Dela is upem 1000, Noto is upem 1024, so the donor
outline is scaled 1024/1000. Noto OFL has no Reserved Font Name, but we rename to
a custom family anyway so it's unambiguously ours.

  python build_custom_font.py            # -> C:\\fonts\\TrioEmojiStar.woff2

Requires: fonttools, brotli (for woff2)
"""
from fontTools.ttLib import TTFont
from fontTools.pens.ttGlyphPen import TTGlyphPen
from fontTools.pens.transformPen import TransformPen
from fontTools.pens.recordingPen import DecomposingRecordingPen

NOTO = r'C:\fonts\NotoColorEmoji.v2.woff2'
DELA = r'C:\fonts\DelaGothicOne-Regular.ttf'
OUT = r'C:\fonts\TrioEmojiStar.woff2'
CP = 0x2605
NEWNAME = 'star2605'
FAMILY = 'Trio Emoji Star'
PS = 'TrioEmojiStar-Regular'


def main():
    noto = TTFont(NOTO)
    dela = TTFont(DELA)
    scale = noto['head'].unitsPerEm / dela['head'].unitsPerEm
    print(f'scale donor {dela["head"].unitsPerEm} -> {noto["head"].unitsPerEm} = {scale:.4f}')

    src = dela.getBestCmap()[CP]
    print('donor glyph for U+2605:', src)

    # decompose donor outline (flatten any components), then scale into Noto's em
    dela_gs = dela.getGlyphSet()
    rec = DecomposingRecordingPen(dela_gs)
    dela_gs[src].draw(rec)
    pen = TTGlyphPen(None)
    rec.replay(TransformPen(pen, (scale, 0, 0, scale, 0, 0)))
    glyph = pen.glyph()

    glyf = noto['glyf']
    order = list(glyf.glyphOrder)            # COPY (getGlyphOrder aliases this same list)
    name = NEWNAME
    while name in order:
        name += '_'
    glyf.glyphs[name] = glyph                # raw dict add; we manage glyphOrder ourselves
    glyph.recalcBounds(glyf)
    order.append(name)
    glyf.glyphOrder = order                  # glyphs dict and glyphOrder now in sync (+1 each)
    noto.setGlyphOrder(order)                # sync the font-level order cache

    adv = round(dela['hmtx'][src][0] * scale)
    noto['hmtx'][name] = (adv, getattr(glyph, 'xMin', 0))
    if 'vmtx' in noto:                        # Noto carries vertical metrics; give the glyph one
        noto['vmtx'][name] = (noto['head'].unitsPerEm, 0)

    added = 0
    for t in noto['cmap'].tables:
        if t.isUnicode():
            t.cmap[CP] = name
            added += 1
    print('cmap subtables updated:', added)

    nm = noto['name']
    for nid, val in ((1, FAMILY), (4, FAMILY), (6, PS), (16, FAMILY), (3, PS)):
        nm.setName(val, nid, 3, 1, 0x409)   # Windows
        nm.setName(val, nid, 1, 0, 0)       # Mac (best-effort)

    noto.flavor = 'woff2'
    noto.save(OUT)
    print('saved', OUT)

    v = TTFont(OUT)
    vc = v.getBestCmap()
    print(f'VERIFY  U+2605 present: {CP in vc}  -> glyph {vc.get(CP)!r}')
    print(f'VERIFY  family: {v["name"].getDebugName(1)!r}  nglyphs: {len(v.getGlyphOrder())}')


if __name__ == '__main__':
    main()
