Files
YataiDONNijiiro/tools/font/FONT.md
T
TaikoZhongandClaude Fable 5.1 d5ef78970e font_zh.ttf: Simplified Chinese glyph set first, tw/jp only for what it lacks
With the interface language set to Simplified Chinese the engine now loads
Graphics/font_zh.ttf, built with the cn atlas first (7 588 glyphs from cn,
11 966 from tw, 8 from jp) so shared characters take the Simplified face too,
as the cabinet does with its per-language atlas families.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-14 05:56:37 +08:00

4.2 KiB
Raw Blame History

Graphics/font.ttf — how it is made, and how the cabinet actually uses its fonts

What the cabinet ships

The cabinet has no vector font. Data\x64\font\ holds pre-rasterised BC7 glyph atlases, one family per language and one atlas per size/weight bucket, each with an XML sidecar (codepoint → rect; no bearings, no kerning):

language buckets on disk distinct codepoints face (as drawn in the atlas)
jp 30, 32_B, 32_DB, 32_EB, 64 7 532 30/32: rounded gothic in three weights; 64: brush/勘亭流-style display face
tw 30, 32, 64 17 678 same split
cn 30, 32, 64 7 608 same split (the 64 face is a heavier brush)
kr 30, 32, 64 8 407 same split
en 30, 32, 64 299 same split

(The JP 39.06 dump has the same files minus cn_*; the CN 05 dump adds cn_*. The jp/tw/kr/en XMLs are byte-identical between the two.)

How a text record picks its atlas

  • Language comes from the cabinet language setting: wordlist rows are looked up in the language's column and rendered from that language's atlas family. Rows flagged fontType 0 (untranslated) always render from jp.
  • Size/weight bucket is authored per text record in the .nulm (DefineFont entry symbol "0".."4" → 64, 30, 32_EB, 32_B, 32_DB). It is not language dependent. For en/tw/kr/cn the three weighted 32_* buckets are registered onto the plain 32 atlas, so a record that asks for 32_EB on a cn cabinet is drawn from cn_32.
  • The only fallback is jp_64 when the language itself is unknown; a codepoint missing from the chosen atlas is simply not drawn. Of the 692 text records in the shipped movies, 449 use the 30/32 (rounded gothic) buckets and 168 use the 64 (brush) bucket.

YataiDON draws every string through a single .ttf, so one face has to serve all of it. This skin's font.ttf is built from the _64 (brush) atlases, which is the face used for headings, song titles and most of the large text.

Building font.ttf

tools/font/build_font.py merges the five _64 atlases into one TrueType font:

  1. Decode each <lang>_64.nutexb to a DDS (BC7, nutexb_dump -o) next to its XML.
  2. For each language in priority order jp, tw, cn, kr, en, every codepoint that does not yet have an inked glyph takes its bitmap from that atlas (blank placeholder cells are skipped so a later atlas can supply the character).
  3. Each bitmap is upscaled 4× (bicubic), thresholded at alpha ≥ 128, traced with potrace and converted to quadratic outlines (cu2qu).
  4. Metrics: unitsPerEm 1024, scale = 1024 / fontPoint of the atlas (16 units per pixel for jp_64), advance = cell width × scale, baseline = the atlas's median bottom ink row of its Han/Hangul glyphs, so the five families sit on one baseline with equal Han height. ascender 880 / descender −144, as the earlier build.
pip install potracer fonttools pillow numpy
python build_font.py <dir with *_64.dds + *_64.xml> font.ttf --order jp,tw,cn,kr,en

Result (version 3.000): 22 382 glyphs — 7 499 from jp, 10 107 from tw, 1 956 from cn, 2 737 from kr, 82 from en. Coverage of each atlas's repertoire: jp 7521/7532, tw 17651/17678, cn 7589/7608, kr 8070/8407, en 268/295 (the remainder are blank cells in the atlases themselves). Version 2.000 had no cn or kr glyphs, which is why Simplified Chinese and Korean text showed ?.

Per-language fonts (Graphics/font_<lang>.ttf)

The engine loads Graphics/font_<language>.ttf when the skin has one and falls back to font.ttf (the settings screen reloads the skin, so switching language switches the font). This mirrors the cabinet, which draws everything from the language's own atlas family and only lacks what that family does not have.

file atlas priority meaning
font.ttf jp, tw, cn, kr, en Japanese / English (and any language without its own file)
font_zh.ttf cn, tw, jp, kr, en Simplified Chinese: every character the cn family has comes from it (7 588), the rest from tw (11 966), then jp
python build_font.py <dir> font_zh.ttf --order cn,tw,jp,kr,en