#!/usr/bin/env python3
"""
Build a monochrome Noto Emoji subset for the chat/message UI.

Dear ImGui rasterizes fonts with stb_truetype, which handles only monochrome
(outline `glyf`) fonts — NOT color emoji (CBDT/sbix/COLR). So we use Google's
*monochrome* Noto Emoji (github.com/google/fonts, ofl/notoemoji, OFL-licensed)
and merge it into the text fonts (see Typography::loadFont, the block after the
CJK merge). ImGui renders one glyph per codepoint with no shaping, so ZWJ
sequences / regional-indicator flags won't compose — single-codepoint emoji
(😀 🎉 ❤ 🔥 👍 …) render fine, which covers the overwhelming majority of use.

Source is the variable font pinned to wght=400 → static, then subset to the
emoji planes plus the higher symbol/star ranges the base UI font doesn't cover.
The base Ubuntu font already owns U+2600–26FF etc.; ImGui's MergeMode gives the
first-loaded glyph precedence, so those stay text-styled and only the codepoints
the base lacks fall through to this font.

Get the source once (OFL, redistributable):
  curl -fsSL -o /tmp/NotoEmoji-VF.ttf \
    'https://github.com/google/fonts/raw/main/ofl/notoemoji/NotoEmoji%5Bwght%5D.ttf'

Then: python3 scripts/build_emoji_subset.py
Output: res/fonts/NotoEmoji-Subset.ttf  (committed; embedded via INCBIN)
"""
import os
from fontTools import ttLib, subset
from fontTools.varLib.instancer import instantiateVariableFont

ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SOURCE_VF = '/tmp/NotoEmoji-VF.ttf'
STATIC = '/tmp/NotoEmoji-Static.ttf'
OUTPUT = os.path.join(ROOT, 'res', 'fonts', 'NotoEmoji-Subset.ttf')

# Emoji codepoints to keep. Ranges are inclusive.
RANGES = [
    (0x1F000, 0x1FAFF),  # all the main emoji planes (emoticons, pictographs, transport, supplement, extended)
    (0x2600, 0x27BF),    # Miscellaneous Symbols + Dingbats
    (0x2B00, 0x2BFF),    # stars (⭐ 2B50) and misc arrows
    (0xFE00, 0xFE0F),    # variation selectors (VS16 emoji-style)
    (0x2194, 0x21AA),    # arrows used as emoji
    (0x231A, 0x231B),    # ⌚ ⌛
    (0x23E9, 0x23FA),    # media-control emoji
    (0x25AA, 0x25FE),    # small squares
]
SINGLES = [0x200D, 0x2934, 0x2935, 0x3030, 0x303D, 0x3297, 0x3299,
           0x00A9, 0x00AE, 0x2122, 0x2139, 0x24C2]


def main():
    if not os.path.exists(SOURCE_VF):
        raise SystemExit(f"missing source font {SOURCE_VF} — see the header for the curl command")

    # 1. Pin the weight axis so stb_truetype rasterizes a clean static instance.
    f = ttLib.TTFont(SOURCE_VF)
    if 'fvar' in f:
        instantiateVariableFont(f, {'wght': 400}, inplace=True)
    f.save(STATIC)

    unicodes = list(SINGLES)
    for lo, hi in RANGES:
        unicodes.extend(range(lo, hi + 1))

    opts = subset.Options()
    opts.layout_features = []          # ImGui does no shaping — drop GSUB/GPOS
    opts.name_IDs = []
    opts.notdef_outline = True
    opts.glyph_names = False
    opts.drop_tables = ['GSUB', 'GPOS', 'GDEF', 'morx', 'kern']

    font = subset.load_font(STATIC, opts)
    ss = subset.Subsetter(options=opts)
    ss.populate(unicodes=unicodes)
    ss.subset(font)
    subset.save_font(font, OUTPUT, opts)

    out = ttLib.TTFont(OUTPUT)
    cmap = out.getBestCmap()
    color = any(t in out.reader.keys() for t in ('CBDT', 'sbix', 'COLR'))
    print(f"Output: {OUTPUT}")
    print(f"Size: {os.path.getsize(OUTPUT)//1024} KB | glyphs: {len(cmap)} | color tables: {color}")
    if color:
        raise SystemExit("ERROR: subset has color tables — stb_truetype cannot render it")


if __name__ == '__main__':
    main()
