6a9352cde1
font_plugin's module doc claimed a parse failure aborts the program, but the code warns and continues with glyph-less UI; fix the doc to match. CLAUDE.md §4.2 listed only audio and the card theme as embedded while saying "do not embed user fonts"; document that the bundled FiraMono face is legitimately embedded via include_bytes! as the canonical UI font. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
47 lines
1.9 KiB
Rust
47 lines
1.9 KiB
Rust
//! Embeds FiraMono-Medium into the binary and exposes it via [`FontResource`].
|
|
//!
|
|
//! Bundling rather than runtime-loading guarantees the canonical UI face is
|
|
//! always available regardless of install or platform. The bytes are
|
|
//! validated at startup; a parse failure logs a warning and continues with
|
|
//! glyph-less UI rather than aborting, since crashing on a corrupt embed is
|
|
//! worse than degraded text.
|
|
|
|
use bevy::prelude::*;
|
|
|
|
/// FiraMono-Medium bytes embedded at compile time. Single source of truth for
|
|
/// the project's UI face — `solitaire_engine::assets::svg_loader` embeds the
|
|
/// same path independently for SVG rasterisation so the two layers can't
|
|
/// drift.
|
|
const BUNDLED_FONT_BYTES: &[u8] = include_bytes!("../../assets/fonts/main.ttf");
|
|
|
|
/// Holds the project-wide [`Handle<Font>`] registered at startup.
|
|
#[derive(Resource)]
|
|
pub struct FontResource(pub Handle<Font>);
|
|
|
|
/// Registers the bundled FiraMono with [`Assets<Font>`] at startup.
|
|
pub struct FontPlugin;
|
|
|
|
impl Plugin for FontPlugin {
|
|
fn build(&self, app: &mut App) {
|
|
app.add_systems(Startup, load_font);
|
|
}
|
|
}
|
|
|
|
fn load_font(fonts: Option<ResMut<Assets<Font>>>, mut commands: Commands) {
|
|
// Headless test fixtures use MinimalPlugins (no AssetPlugin → no
|
|
// Assets<Font>). FontPlugin in that context is a no-op — consumers
|
|
// already query `Option<Res<FontResource>>` and degrade cleanly.
|
|
let Some(mut fonts) = fonts else { return };
|
|
let font = match Font::try_from_bytes(BUNDLED_FONT_BYTES.to_vec()) {
|
|
Ok(f) => f,
|
|
Err(e) => {
|
|
// A corrupt embedded font is unusual but should not crash the
|
|
// process — UI will render without glyphs rather than panicking.
|
|
warn!("bundled FiraMono failed to parse ({e}); UI text may be invisible");
|
|
return;
|
|
}
|
|
};
|
|
let handle = fonts.add(font);
|
|
commands.insert_resource(FontResource(handle));
|
|
}
|