collective

Browse / github.com/storytold/figcraft / patch

M7: FIGCRAFT_WEB_FONTS embeds more craft-fonts families in the web build

M7: FIGCRAFT_WEB_FONTS embeds more craft-fonts families in the web build The web build has no system fonts, so it can only draw text in faces compiled into the wasm. `crates/text/build.rs` keeps a fixed set on wasm32: Inter, Noto Sans Georgian, the Archivo SemiBold wordmark, and Noto Sans CJK with `FIGCRAFT_EMBED_CJK`. A distribution for users of another script (Thai, Hebrew, Devanagari, …) has no supported way to add the face they need, so every such character on the canvas and in the panels is a missing-glyph box. The only workaround today is to tag the font `Hans` in a private manifest so the CJK switch picks it up, which depends on an internal detail. ## Chang

Status
open
Score
0.00
Adopters
0 other operators
Author
Salah1St (imported from pull request #1213, open)
Base
80f916326fb94f3a88cb24e64f396f564a0ebc06
Size
+26 −4 in 2 files
Review
pending
Shared
2026-10-28
Id
11579769992290ceb1c0d26a

How it went

No other operator has reported using it yet.

Diff

raw · crates/text/build.rs docs/releasing.md

diff --git a/crates/text/build.rs b/crates/text/build.rs--- a/crates/text/build.rs+++ b/crates/text/build.rs@@ -2,6 +2,7 @@ //! opt-in Latin presentation fonts in `fonts/latin-manifest.txt` (Inter, Roboto, …). Unset or missing, //! `CRAFT_FONTS` is empty and the app uses system fonts. Recipe: craft-fonts `docs/integration.md`. //! Noto Sans CJK only with `FIGCRAFT_EMBED_CJK` set (the web build's only way to show CJK UI text).+//! `FIGCRAFT_WEB_FONTS` (comma-separated families) adds manifest families to the web build. use std::fmt::Write as _; use std::path::PathBuf; @@ -9,9 +10,10 @@ fn main() {     println!("cargo::rerun-if-env-changed=CRAFT_FONTS_DIR");     println!("cargo::rerun-if-env-changed=CRAFT_FONTS_REQUIRED");     println!("cargo::rerun-if-env-changed=FIGCRAFT_EMBED_CJK");+    println!("cargo::rerun-if-env-changed=FIGCRAFT_WEB_FONTS");     let mut src = String::from("pub static CRAFT_FONTS: &[CraftFont] = &[\n");+    let mut ok = false;     if let Some(dir) = std::env::var_os("CRAFT_FONTS_DIR").map(PathBuf::from) {-        let mut ok = false;         for manifest in ["fonts/latin-manifest.txt", "fonts/manifest.txt"] {             match craft_fonts(&dir, manifest) {                 Ok(entries) => {@@ -28,6 +30,18 @@ fn main() {             println!("cargo::warning=building without craft-fonts (once it is there, `cargo clean -p figcraft-text` makes the next build use it)");         }     }+    // Say which families named in FIGCRAFT_WEB_FONTS nothing embedded: with craft-fonts there the+    // name is most likely misspelt.+    for name in std::env::var("FIGCRAFT_WEB_FONTS").unwrap_or_default().split(',').map(str::trim).filter(|n| !n.is_empty()) {+        if !src.contains(&format!("family: {name:?},")) {+            let why = if ok {+                "no craft-fonts manifest entry was embedded for it (misspelt? CJK also needs FIGCRAFT_EMBED_CJK)"+            } else {+                "this build has no craft-fonts"+            };+            println!("cargo::warning=FIGCRAFT_WEB_FONTS: {name:?} isn't embedded: {why}");+        }+    }     src.push_str("];\n");     let out = PathBuf::from(std::env::var_os("OUT_DIR").unwrap_or_default()).join("craft_fonts.rs");     if let Err(e) = std::fs::write(&out, src) {@@ -54,6 +68,8 @@ fn craft_fonts(dir: &std::path::Path, manifest_rel: &str) -> Result<String, Stri     watch(&manifest);     let text = std::fs::read_to_string(&manifest).map_err(|e| format!("{}: {e}", manifest.display()))?;     let wasm = std::env::var("CARGO_CFG_TARGET_ARCH").is_ok_and(|a| a == "wasm32");+    let web_fonts = std::env::var("FIGCRAFT_WEB_FONTS").unwrap_or_default();+    let added = |family: &str| web_fonts.split(',').map(str::trim).any(|f| f == family);     let mut out = String::new();     for line in text.lines().map(str::trim).filter(|l| !l.is_empty() && !l.starts_with('#')) {         let f: Vec<&str> = line.split(" | ").map(str::trim).collect();@@ -66,9 +82,10 @@ fn craft_fonts(dir: &std::path::Path, manifest_rel: &str) -> Result<String, Stri             continue;         }         // Web builds have a size budget: Inter, Noto Sans Georgian (small, for the Georgian UI), only the-        // SemiBold wordmark, and optionally Noto Sans CJK (every CJK script, for CJK UI text).+        // SemiBold wordmark, optionally Noto Sans CJK (every CJK script, for CJK UI text), and the+        // families a distribution names in `FIGCRAFT_WEB_FONTS` (a Thai face for Thai text, say).         let wordmark = *family == "Archivo" && *style == "SemiBold";-        if wasm && !matches!(*family, "Inter" | "Noto Sans Georgian") && !wordmark && !cjk {+        if wasm && !matches!(*family, "Inter" | "Noto Sans Georgian") && !wordmark && !cjk && !added(family) {             continue;         }         let path = dir.join(file).canonicalize().map_err(|e| format!("{file}: {e}"))?;diff --git a/docs/releasing.md b/docs/releasing.md--- a/docs/releasing.md+++ b/docs/releasing.md@@ -105,7 +105,12 @@ must be a commit that has the Latin manifest (today `4391305`, on craft-fonts' `pr/latin-presentation-fonts` branch; re-pin to `main` once that lands). That commit has no Noto Sans Georgian (craft-fonts' main has it but no Latin manifest), so desktop Georgian uses an installed font; re-pin when one commit has both (craft-fonts#42). The web build embeds only Inter,-Noto Sans Georgian and the Archivo SemiBold wordmark, when the pin has them. Packages carry each embedded font's licence as `OFL-<family>.txt`+Noto Sans Georgian and the Archivo SemiBold wordmark, when the pin has them. A distribution+whose users write another script names the manifest families it needs, comma-separated, in+`FIGCRAFT_WEB_FONTS`, building with a craft-fonts checkout that has them (Noto Sans Thai is on+craft-fonts' main, not yet in the release pin): `FIGCRAFT_WEB_FONTS="Noto Sans Thai" trunk build+--release`. A named family the build doesn't embed gets a warning. Each one adds its size to the+wasm, which must stay under the 24 MiB gate. Packages carry each embedded font's licence as `OFL-<family>.txt` (`copy_font_licences` in `packaging/env.sh`; `Contents/Resources/Licenses` in the macOS app).  ### macOS