"""Reproduce the OFL CJK TrueType subset used only by the Web renderer.

Install fonttools==4.61.1 in a private directory, then run with that directory
on PYTHONPATH. The input is a verified official Google Fonts Git blob; the
transport mirror never changes its expected identity.
"""
import hashlib
import json
from pathlib import Path

import fontTools
from fontTools import subset
from fontTools.ttLib import TTFont
from fontTools.varLib.instancer import instantiateVariableFont

ROOT = Path(__file__).resolve().parents[2]
OUTPUT = ROOT / "assets/fonts/noto-sans-sc-2.004"
SOURCE = OUTPUT / "NotoSansSC-Wght.ttf"
EXPECTED_SHA256 = "a3041811a78c361b1de50f953c805e0244951c21c5bd412f7232ef0d899af0da"
EXPECTED_BLOB = "fb0637bafbcd804fe32152370a1225990745b4bc"
# Same BMP ranges as CanvasAdapter's existing Unicode fallback bank. ASCII is
# deliberately not included: Latin and Monaco keep their existing font path.
RANGES = [(128,2047),(8192,8303),(8592,8703),(12288,12351),
          (13312,40959),(65280,65519),(65533,65533)]

def digest(path):
    return hashlib.sha256(path.read_bytes()).hexdigest()

def compact_ranges(values):
    result = []
    for point in sorted(values):
        if result and result[-1][1] + 1 == point:
            result[-1][1] = point
        else:
            result.append([point, point])
    return [f"U+{start:04X}" + (f"-U+{end:04X}" if end != start else "") for start,end in result]

assert fontTools.__version__ == "4.61.1", "Use pinned FontTools 4.61.1."
source = SOURCE.read_bytes()
assert hashlib.sha256(source).hexdigest() == EXPECTED_SHA256
assert hashlib.sha1(b"blob " + str(len(source)).encode() + b"\0" + source).hexdigest() == EXPECTED_BLOB
requested = {point for start,end in RANGES for point in range(start,end+1)}
original = TTFont(SOURCE, recalcTimestamp=False)
available = set(original.getBestCmap())
assert "glyf" in original and "CFF " not in original and "CFF2" not in original
source_time = original["head"].modified
files = []
outputs = []
for weight,label in [(400,"Regular"),(700,"Bold")]:
    font = TTFont(SOURCE, recalcTimestamp=False)
    instantiateVariableFont(font,{"wght":weight},inplace=True,optimize=True,static=True)
    options = subset.Options()
    options.recalc_timestamp = False
    options.notdef_glyph = True
    options.notdef_outline = True
    options.layout_features = []
    options.name_IDs = [0,1,2,3,4,5,6,7,8,9,10,11,13,14,16,17]
    options.name_legacy = True
    options.name_languages = [0x409]
    operation = subset.Subsetter(options=options)
    operation.populate(unicodes=requested)
    operation.subset(font)
    names = {1:"XFE Web CJK",2:label,3:f"XFEWebCJK-2.004-{weight}",
             4:f"XFE Web CJK {label}",6:f"XFEWebCJK-{label}",16:"XFE Web CJK",17:label}
    for name_id,value in names.items():
        font["name"].setName(value,name_id,3,1,0x409)
        font["name"].setName(value,name_id,1,0,0)
    font["OS/2"].usWeightClass = weight
    font["OS/2"].fsSelection = (font["OS/2"].fsSelection & ~(0x20 | 0x40)) | (0x20 if weight >= 700 else 0x40)
    font["head"].macStyle = (font["head"].macStyle & ~1) | (1 if weight >= 700 else 0)
    font["head"].modified = source_time
    path = OUTPUT / f"XfeWebCjk-{label}.ttf"
    font.save(path,reorderTables=True)
    verified = TTFont(path,recalcTimestamp=False)
    assert "glyf" in verified and not any(tag in verified for tag in ("fvar","gvar","CFF ","CFF2"))
    coverage = set(verified.getBestCmap())
    assert coverage == requested & available
    assert all(point in coverage for point in map(ord,"文档预览这是中文测试，加粗。"))
    outputs.append({"Path":path.name,"Weight":weight,"GlyphCount":len(verified.getGlyphOrder()),
                    "UnicodeCoverageCount":len(coverage),"Outline":"Static TrueType glyf",
                    "Sha256":digest(path),"Bytes":path.stat().st_size})
for path in [SOURCE,OUTPUT/"OFL.txt",*(OUTPUT/entry["Path"] for entry in outputs)]:
    files.append({"Path":path.name,"Bytes":path.stat().st_size,"Sha256":digest(path)})
manifest = {"Schema":"XfeWebCjkFont1","Family":"XFE Web CJK","DerivedFrom":"Noto Sans SC Version 2.004-H2",
 "SourceUrl":"https://raw.githubusercontent.com/google/fonts/main/ofl/notosanssc/NotoSansSC%5Bwght%5D.ttf",
 "OfficialContentsUrl":"https://api.github.com/repos/google/fonts/contents/ofl/notosanssc/NotoSansSC%5Bwght%5D.ttf",
 "SourceGitBlobSha1":EXPECTED_BLOB,"SourceSha256":EXPECTED_SHA256,"SourceBytes":len(source),
 "DownloadTransport":"https://gh-proxy.com/https://raw.githubusercontent.com/google/fonts/main/ofl/notosanssc/NotoSansSC%5Bwght%5D.ttf",
 "TransportVerifiedAgainstOfficialGitBlob":True,"License":"SIL Open Font License 1.1; OFL.txt",
 "Transformation":{"Tool":"FontTools","Version":fontTools.__version__,"Script":"Tools/BrowserCompatibility/BuildWebCjkFont.py",
   "ScriptSha256":digest(Path(__file__).resolve()),"StaticWeights":[400,700],"LayoutFeatures":[],"ModifiedFamily":"XFE Web CJK",
   "Notes":"Axis instantiation and BMP Unicode subsetting, preserving original glyf outlines at the selected weights. Simple glyph rendering; no complex shaping or supplementary-plane coverage."},
 "RequestedUnicodeRanges":compact_ranges(requested),"RequestedUnicodeCount":len(requested),
 "AvailableRequestedCount":len(requested & available),"UnavailableRequestedRanges":compact_ranges(requested-available),
 "UnavailableRequestedCount":len(requested-available),"AsciiIncluded":False,
 "FallbackOrder":"Existing primary Web family when HasGlyph succeeds, then XFE Web CJK 400/700 when HasGlyph succeeds, finally existing Unifont bitmap for remaining missing BMP glyphs",
 "DesktopAndTerminalChanged":False,"WindowsFontsBundled":False,"Outputs":outputs,"Files":files}
(OUTPUT/"Manifest.json").write_text(json.dumps(manifest,ensure_ascii=False,indent=2)+"\n",encoding="utf-8")
print(json.dumps({"Manifest":str(OUTPUT/"Manifest.json"),"Outputs":outputs,"UnavailableRequestedCount":len(requested-available)},indent=2))
