use alloc::vec::Vec;
use crate::bake;
use crate::ecs::{FontHandle, PipelineContext};
use crate::resource::{FontTable, ResourceEntry};
use crate::result::CnResult;
pub const HUD_FONT_SIZE_PX: u32 = 20;
#[derive(Debug, Clone, Copy)]
pub struct HudFont(pub FontHandle);
static PAYLOAD: spin::Once<Vec<u8>> = spin::Once::new();
fn payload() -> Result<&'static [u8], CnResult> {
PAYLOAD
.try_call_once(|| {
bake::font::compile(
bake::font::BUILTIN_FONT_BYTES,
HUD_FONT_SIZE_PX,
bake::font::BUILTIN_FONT_FILE,
)
.map_err(|_| CnResult::InvalidArgument)
})
.map(Vec::as_slice)
}
pub fn hud_font(ctx: &mut PipelineContext) -> Result<FontHandle, CnResult> {
if let Some(HudFont(handle)) = ctx.resource::<HudFont>().copied() {
return Ok(handle);
}
let payload = payload()?.to_vec();
if ctx.resource::<FontTable>().is_none() {
ctx.insert_resource(FontTable::default());
}
let table = ctx
.resource_mut::<FontTable>()
.ok_or(CnResult::InvalidState)?;
let handle = FontHandle(table.append(ResourceEntry::baked(payload)));
ctx.insert_resource(HudFont(handle));
Ok(handle)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ecs::World;
#[test]
fn the_bundled_atlas_compiles_once_for_the_process() {
let first = payload().expect("the bundled face compiles");
let second = payload().expect("the bundled face compiles");
assert!(!first.is_empty());
assert_eq!(
first.as_ptr(),
second.as_ptr(),
"the second call reads the stored atlas"
);
}
#[test]
fn each_world_gets_its_own_entry_holding_the_same_atlas() {
let mut first = World::new();
let mut second = World::new();
hud_font(&mut first.context()).expect("a face for the first world");
hud_font(&mut second.context()).expect("a face for the second world");
let bytes = |world: &World| {
world
.resource::<FontTable>()
.expect("a font table")
.0
.first()
.expect("the appended face")
.baked_bytes()
.expect("the face is baked")
.to_vec()
};
assert_eq!(bytes(&first), bytes(&second));
assert!(!bytes(&first).is_empty());
}
#[test]
fn a_second_call_on_one_world_reuses_the_handle() {
let mut world = World::new();
let first = hud_font(&mut world.context()).expect("a face");
let second = hud_font(&mut world.context()).expect("the same face");
assert_eq!(first, second);
assert_eq!(
world.resource::<FontTable>().expect("a font table").len(),
1
);
}
}