diff --git a/slint-frontend/fonts/Nunito.ttf b/slint-frontend/fonts/Nunito.ttf new file mode 100644 index 0000000..2ec1f4b Binary files /dev/null and b/slint-frontend/fonts/Nunito.ttf differ diff --git a/slint-frontend/fonts/README.md b/slint-frontend/fonts/README.md new file mode 100644 index 0000000..0630664 --- /dev/null +++ b/slint-frontend/fonts/README.md @@ -0,0 +1,9 @@ +Nunito, the face the design is drawn in, as a variable TTF. + +`web/public/fonts/` has the same family as woff2, which is right for a browser and +useless here: Slint cannot read woff2. This is the upstream variable TTF (weights +200-1000), which `SLINT_DEFAULT_FONT` is pointed at - by `shell.nix` for development, +and by the launcher `roles/pi_slint_frontend` installs on the device. + +Nunito is licensed under the SIL Open Font License 1.1: +https://github.com/googlefonts/nunito diff --git a/slint-frontend/shell.nix b/slint-frontend/shell.nix index 4253eea..bb08d9d 100644 --- a/slint-frontend/shell.nix +++ b/slint-frontend/shell.nix @@ -33,12 +33,10 @@ pkgs.mkShell { python3 ]; - # Nunito is the face the design is drawn in. The web front-end self-hosts it as - # woff2, which Slint cannot read, so the dev shell points Slint at the TTF instead - # (`SLINT_DEFAULT_FONT` takes one file and makes it the primary font). Without it - # everything still renders, in whatever sans fontconfig hands back. - SLINT_DEFAULT_FONT = - "${pkgs.nunito}/share/fonts/truetype/Nunito/Nunito[wght].ttf"; + # Nunito is the face the design is drawn in. `SLINT_DEFAULT_FONT` takes one file and + # makes it the primary font. This points at the copy vendored in `fonts/` rather than + # at nixpkgs, so development and the device render from the identical file. + SLINT_DEFAULT_FONT = toString ./fonts/Nunito.ttf; buildInputs = runtimeLibs ++ (with pkgs; [ fontconfig diff --git a/slint-frontend/src/main.rs b/slint-frontend/src/main.rs index 362f281..bbb8477 100644 --- a/slint-frontend/src/main.rs +++ b/slint-frontend/src/main.rs @@ -637,14 +637,28 @@ fn main() -> Result<(), Box> { .unwrap_or_else(|| api::DEFAULT_BASE_URL.to_string()); println!("musicmouse-slint → {base}"); - // Nunito is the face the design is drawn in. Slint takes one file as the primary - // font through `SLINT_DEFAULT_FONT`; the dev shell sets it, and a deployment can - // drop the TTF next to the binary instead. Neither present just means the system - // sans - a missing font should change how this looks, not whether it runs. + // Nunito is the face the design is drawn in, vendored as a TTF in `fonts/` because + // Slint cannot read the woff2 the web front-end self-hosts. Slint takes one file as + // the primary font through `SLINT_DEFAULT_FONT`; the dev shell and the device's + // launcher both set it, and this is the fallback for running the binary directly. + // None of them finding it just means the system sans - a missing font should change + // how this looks, not whether it runs. if std::env::var_os("SLINT_DEFAULT_FONT").is_none() { - let local = std::path::Path::new("fonts/Nunito.ttf"); - if local.exists() { - std::env::set_var("SLINT_DEFAULT_FONT", local); + let beside_exe = std::env::current_exe() + .ok() + // target/release/ -> the crate root + .and_then(|exe| Some(exe.parent()?.parent()?.parent()?.join("fonts/Nunito.ttf"))); + for candidate in [ + Some(std::path::PathBuf::from("fonts/Nunito.ttf")), + beside_exe, + ] + .into_iter() + .flatten() + { + if candidate.exists() { + std::env::set_var("SLINT_DEFAULT_FONT", candidate); + break; + } } }