use crate::ecs::FontHandle;
use crate::gfx::text::{LoadedFont, derive_cap_px};
const BAKED_ATLAS: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/builtin_font.bin"));
pub(crate) struct BuiltinFont {
pub(crate) loaded: LoadedFont,
pub(crate) atlas: (u32, u32, Vec<u8>),
}
pub(crate) fn load(handle: FontHandle) -> Option<BuiltinFont> {
let (atlas_w, atlas_h, supersample, size_px, rgba, metrics) =
match concinnity_core::bake::font::deserialise(BAKED_ATLAS) {
Ok(decoded) => decoded,
Err(e) => {
tracing::error!("built-in font atlas failed to decode: {e}");
return None;
}
};
let metrics: crate::gfx::text::FontMetrics =
metrics.into_iter().map(|m| (m.char_code, m)).collect();
let size_px = size_px as f32;
Some(BuiltinFont {
loaded: LoadedFont {
atlas_slot: handle.0 as usize,
cap_px: derive_cap_px(&metrics, size_px),
metrics,
atlas_w,
atlas_h,
size_px,
supersample: supersample.max(1) as f32,
},
atlas: (atlas_w, atlas_h, rgba),
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_baked_atlas_decodes_with_printable_ascii() {
let font = load(FontHandle(0)).expect("the baked atlas decodes");
let loaded = &font.loaded;
assert_eq!(loaded.size_px, 24.0);
assert!(loaded.cap_px > 0.0, "cap height derives from real metrics");
assert_eq!(loaded.metrics.len(), (32u8..=126u8).count());
for ch in [' ', 'A', 'z', '/', '.', '~'] {
assert!(
loaded.metrics.contains_key(&(ch as u32)),
"{ch:?} is rasterised"
);
}
let (w, h, rgba) = &font.atlas;
assert_eq!(rgba.len(), (*w as usize) * (*h as usize) * 4);
}
#[test]
fn the_face_takes_its_handle_as_its_atlas_slot() {
assert_eq!(load(FontHandle(0)).expect("decodes").loaded.atlas_slot, 0);
assert_eq!(load(FontHandle(3)).expect("decodes").loaded.atlas_slot, 3);
}
}