mod blob;
mod format;
mod instance;
mod source;
mod tables;
pub use blob::FontBlob;
pub use format::FontFormat;
pub use instance::{
FontFeatureVariations, FontInstance, FontInstanceBuilder, FontVariation, NormalizedCoord,
};
pub use source::FontSource;
pub use tables::{FontTableFunction, FontTables};
#[doc(hidden)]
#[rust_analyzer::completions(hidden_from_completion)]
pub mod interop;
use super::once::Once;
use crate::{ps::type1::Type1Font, ReadError};
use alloc::{boxed::Box, sync::Arc};
use core::any::Any;
#[derive(Clone)]
pub struct Font(Arc<FontRepr>);
impl Font {
pub fn new(source: impl Into<FontSource>, index: u32) -> Result<Self, ReadError> {
let source = source.into();
let kind = if let Ok(tables) = FontTables::new(source.clone(), index) {
Some(FontKindRepr::Sfnt(tables, index))
} else if let FontSource::Blob(blob) = &source {
match FontFormat::new(blob) {
Some(FontFormat::Type1) => Type1Font::new(blob).ok().map(FontKindRepr::Type1),
_ => None,
}
} else {
None
};
let kind = kind.ok_or(ReadError::MalformedData("Data isn't a font"))?;
let repr = FontRepr {
source,
kind,
shaping_data: Once::new(),
};
Ok(Self(Arc::new(repr)))
}
pub fn source(&self) -> &FontSource {
&self.0.source
}
pub fn kind(&self) -> FontKind<'_> {
match &self.0.kind {
FontKindRepr::Sfnt(tables, index) => FontKind::Sfnt(tables, *index),
FontKindRepr::Type1(font) => FontKind::Type1(font),
}
}
pub fn tables(&self) -> &FontTables {
if let FontKindRepr::Sfnt(tables, _) = &self.0.kind {
tables
} else {
&tables::EMPTY_FONT_TABLES
}
}
}
struct FontRepr {
source: FontSource,
kind: FontKindRepr,
shaping_data: Once<Box<dyn Any + Send + Sync>>,
}
#[derive(Clone)]
pub enum FontKind<'a> {
Sfnt(&'a FontTables, u32),
Type1(&'a Type1Font),
}
#[expect(clippy::large_enum_variant)]
enum FontKindRepr {
Sfnt(FontTables, u32),
Type1(Type1Font),
}