diff --git a/TODO.md b/TODO.md --- a/TODO.md +++ b/TODO.md @@ -5,12 +5,22 @@ ## Playability -**Glyphs render as boxes (□)** — symbols in the unit display, heat scale and -conditions overlay. Cause is `spike-webswing/fontconfig.properties` (generated by -`scripts/gen-fontconfig.sh`), which maps logical fonts to faces lacking symbol -coverage. *Already ruled out:* trusting MegaMek's `data/fonts` removed all font -rejections but did not fix the boxes. Next: fall back to MegaMek's bundled -`Noto Symbols 2` / `Icons`. Verify on the unit display, not the lobby. +**Glyphs — mostly fixed, small residue.** `scripts/gen-fontconfig.sh` now bases +the logical fonts on DejaVu (Noto Sans covered exactly 1 of the 18 codepoints +MegaMek uses) and adds a fallback chain of Noto Sans Symbols2 + MegaMek's bundled +Material Symbols. Armor pips, heat pips, wind flag, direction arrow, pressure and +light indicators all render now; verified in a deploy-phase screenshot. + +Still boxed: the temperature and gravity indicators, and a few trailing status +icons. Two causes — U+1F321/U+1F525 are supplementary-plane emoji, which the +legacy fontconfig fallback does not appear to reach, and U+23AF exists only in +Noto Sans Math / Noto Sans Symbols on this system. + +*Ruled out, do not retry:* adding "Noto Sans Symbols" (no 2) for U+23AF. Its +family name is a prefix of "Noto Sans Symbols2" and the parser mis-resolves +between them — basic punctuation (`/ : ,` parens) turns to boxes and the armor +pips disappear. Also ruled out earlier: trusting MegaMek's `data/fonts` alone, +which removed all font-load rejections but fixed nothing. **Open fullscreen** — the frame opens small inside a large viewport. Webswing already passes `webswing.screenWidth`/`screenHeight` to the app JVM. diff --git a/scripts/gen-fontconfig.sh b/scripts/gen-fontconfig.sh --- a/scripts/gen-fontconfig.sh +++ b/scripts/gen-fontconfig.sh @@ -1,30 +1,46 @@ #!/usr/bin/env bash # Generate a legacy-format fontconfig.properties for Webswing's app JVM. # -# Why this is needed: OpenJDK 9+ stopped shipping lib/fontconfig.bfc and instead -# queries libfontconfig at runtime via FcFontConfiguration. Webswing's -# WebFontConfiguration still extends the legacy sun.awt.FontConfiguration, which -# reads the old properties file. With no such file present the app JVM dies at -# startup with "Fontconfig head is null, check your fonts or fonts configuration". +# Why this exists: OpenJDK 9+ stopped shipping lib/fontconfig.bfc and queries +# libfontconfig at runtime instead. Webswing's WebFontConfiguration still extends +# the legacy sun.awt.FontConfiguration, which reads the old properties file. With +# no such file the app JVM dies at startup with "Fontconfig head is null". The JVM +# honours -Dsun.awt.fontconfig=, so we generate one. # -# The JVM honours -Dsun.awt.fontconfig=, so we generate a file rather than -# writing into the JDK. +# Font choice matters as much as existence. MegaMek draws armor pips, heat +# markers and status icons with symbol codepoints, and Noto Sans covers almost +# none of them (of the 18 codepoints MegaMek uses, Noto Sans has exactly one: +# U+00B0). Those render as boxes. So: +# +# base DejaVu - broad symbol coverage on top of normal text +# fallback Noto Sans Symbols2 U+2B1D armor pips, U+2744, U+2B71/73 +# Material Symbols Rounded MegaMek's bundled Private Use icons +# +# Do NOT add "Noto Sans Symbols" (no 2) as a further fallback for U+23AF. Its +# family name is a prefix of "Noto Sans Symbols2" and the legacy parser +# mis-resolves between them: basic punctuation (/ : , parens) starts rendering as +# boxes and the armor pips disappear. Verified by screenshot, and reverted. +# +# Verify coverage changes with the GlyphCoverage probe rather than by eye. set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" OUT="${1:-$ROOT/spike-webswing/fontconfig.properties}" +MM_HOME="${MM_HOME:-$ROOT/MegaMek-0.51.00}" mkdir -p "$(dirname "$OUT")" command -v fc-match >/dev/null || { echo "ERROR: fc-match not found (install fontconfig)" >&2; exit 1; } -# logical Java font -> a family we ask fontconfig to resolve -resolve() { fc-match -f '%{file}' "$1" || true; } +resolve() { fc-match -f '%{file}' "$1" 2>/dev/null || true; } +xlfd() { printf -- '-*-%s-%s-%s-normal--*-%%d-*-*-p-*-%s' "$1" "$2" "$3" "$4"; } +key() { printf 'filename.%s' "$(printf '%s' "$1" | tr ' ' '_')"; } +# DejaVu rather than Noto: it carries the symbol coverage MegaMek needs. declare -A FAMILY=( - [serif]="Noto Serif" - [sansserif]="Noto Sans" + [serif]="DejaVu Serif" + [sansserif]="DejaVu Sans" [monospaced]="DejaVu Sans Mono" - [dialog]="Noto Sans" + [dialog]="DejaVu Sans" [dialoginput]="DejaVu Sans Mono" ) @@ -33,48 +49,73 @@ echo "version=1" echo echo "sequence.allfonts=latin-1" + echo "sequence.fallback=symbols2,micons" echo } > "$OUT" -# Component font mappings: .