use std::ops::Deref;
use bevy::{prelude::*, utils::HashMap};
use tinyvec::TinyVec;
#[derive(Debug, Default, Resource)]
pub struct FontRegistry {
asset_to_font_id: HashMap<AssetId<Font>, TinyVec<[fontdb::ID; 8]>>,
font_to_asset_id: HashMap<fontdb::ID, AssetId<Font>>,
font_db: fontdb::Database,
}
impl FontRegistry {
pub fn add(&mut self, asset_id: AssetId<Font>, font_assets: impl Deref<Target = Assets<Font>>) {
let Some(font) = font_assets.get(asset_id) else {
return;
};
let data = font.data.clone();
let font_ids = self.font_db.load_font_source(fontdb::Source::Binary(data));
for font_id in &font_ids {
self.font_to_asset_id.insert(*font_id, asset_id);
}
self.asset_to_font_id.insert(asset_id, font_ids);
}
pub fn remove(&mut self, asset_id: AssetId<Font>) {
let Some(font_ids) = self.asset_to_font_id.get(&asset_id) else {
return;
};
for font_id in font_ids {
self.font_db.remove_face(*font_id);
}
for font_id in font_ids {
self.font_to_asset_id.remove(font_id);
}
self.asset_to_font_id.remove(&asset_id);
}
pub fn update(
&mut self,
asset_id: AssetId<Font>,
font_assets: impl Deref<Target = Assets<Font>>,
) {
self.remove(asset_id);
self.add(asset_id, font_assets);
}
pub fn query_id(&self, query: &fontdb::Query) -> Option<AssetId<Font>> {
let font_id = self.font_db.query(query);
font_id
.and_then(|font_id| self.font_to_asset_id.get(&font_id))
.copied()
}
pub fn query_handle(&self, query: &fontdb::Query) -> Option<Handle<Font>> {
self.query_id(query).map(Handle::Weak)
}
}