use crate::model::font::{Font, Tables};
use alloc::{boxed::Box, sync::Arc};
use core::any::Any;
pub fn _get_or_init_shaping_data(
font: &Font,
f: impl FnOnce() -> Box<dyn Any + Send + Sync>,
) -> &dyn Any {
&**font.shared().0.shaping_data.get_or_init(|| f())
}
pub fn _get_or_init_scaling_data(
font: &Font,
f: impl FnOnce() -> Box<dyn Any + Send + Sync>,
) -> &dyn Any {
&**font.scaling_data().get_or_init(|| f())
}
pub fn _table_cache_host(font: &Font) -> Option<Arc<Tables>> {
font.shared().tables_arc().cloned()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn recover_shaping_data() {
struct ShapingData {
arg: i32,
}
let font = Font::new(font_test_data::AHEM, 0).unwrap();
let data = _get_or_init_shaping_data(&font, || Box::new(ShapingData { arg: -42 }));
let actual = data.downcast_ref::<ShapingData>().unwrap();
assert_eq!(actual.arg, -42);
}
#[test]
fn scaling_data_is_per_location() {
struct Data(i32);
let read = |data: &dyn Any| data.downcast_ref::<Data>().unwrap().0;
let font = Font::new(font_test_data::VAZIRMATN_VAR, 0).unwrap();
let bold = font
.instance_builder()
.variations([("wght", 700.0)])
.build();
let _ = _get_or_init_scaling_data(&font, || Box::new(Data(1)));
assert_eq!(
read(_get_or_init_scaling_data(&bold, || Box::new(Data(2)))),
2
);
assert_eq!(
read(_get_or_init_scaling_data(&bold.clone(), || Box::new(Data(
3
)))),
2
);
assert_eq!(
read(_get_or_init_scaling_data(&bold.default_instance(), || {
Box::new(Data(4))
})),
1
);
let plain = Font::new(font_test_data::AHEM, 0).unwrap();
let _ = _get_or_init_scaling_data(&plain, || Box::new(Data(5)));
let asked = plain
.instance_builder()
.variations([("wght", 700.0)])
.build();
assert_eq!(
read(_get_or_init_scaling_data(&asked, || Box::new(Data(6)))),
5
);
}
#[test]
fn table_cache_host_shares_tables() {
let font = Font::new(font_test_data::AHEM, 0).unwrap();
let host = _table_cache_host(&font).unwrap();
assert!(core::ptr::eq(&*host, font.tables()));
}
}