use macroquad::prelude::*;
use raster_font::{
backend::prelude::*,
builder::prelude::*,
core::{FontMeta, InputResolver, UGlyphSize},
};
use thiserror::Error;
#[derive(Clone, Copy, Debug)]
pub struct MacroquadBackend;
impl Backend for MacroquadBackend {
type Resources = FontAtlas;
}
#[derive(Debug)]
pub struct FontAtlas {
pub texture: Texture2D,
pub glyphs: Vec<UTokenProps>,
}
impl SpriteSheet for FontAtlas {
type Props = Option<UTokenProps>;
fn props(&self, index: &raster_font::core::AtlasIndex) -> Self::Props {
self.glyphs.get(**index).cloned()
}
}
pub struct BuildMacroquadFont {
filter: FilterMode,
}
impl BackendBuilder for BuildMacroquadFont {
type Backend = MacroquadBackend;
type Error = std::convert::Infallible;
type Sheet = Texture2D;
fn build_resources(
self,
raw_font: raster_font::builder::RawFont<Self::Sheet>,
) -> Result<<Self::Backend as Backend>::Resources, Self::Error> {
raw_font.sheet.image.set_filter(self.filter);
Ok(FontAtlas {
texture: raw_font.sheet.image,
glyphs: raw_font.glyphs,
})
}
}
#[derive(Debug, Error)]
enum Error {
#[error("{0}")]
FontBuilderError(#[from] FontBuilderError<<BuildMacroquadFont as BackendBuilder>::Error>),
#[error("{0}")]
Macroquad(#[from] macroquad::Error),
#[error("TOML deserialization error: {0}")]
Toml(#[from] toml::de::Error),
}
#[macroquad::main("Raster Font Example")]
async fn main() -> Result<(), Error> {
macroquad::file::set_pc_assets_folder("assets");
let meta = macroquad::file::load_file("fonts/m5x7/font.toml").await?;
let meta = toml::from_slice::<FontMeta>(&meta)?;
let sheet = {
let image = macroquad::texture::load_texture("fonts/m5x7/font.png").await?;
GlyphSheet {
size: {
let Vec2 { x, y } = image.size();
UGlyphSize::new(x as u32, y as u32)
},
image,
}
};
let font = FontAtlasBuilder::from(meta.layout.unique())
.with_name(meta.name)
.with_image(sheet)
.populate_layout(&meta.layout)
.custom_glyphs(meta.layout.custom())
.map_err(FontBuilderError::UnknownSequence)?
.build(BuildMacroquadFont {
filter: FilterMode::Nearest,
})?;
println!(
"Font loaded successfully: {}",
font.name.as_deref().unwrap_or("<unnamed>"),
);
for glyph in font.valid("m5x7") {
println!("{glyph:?}");
}
Ok(())
}