use skrifa::raw::TableProvider;
use skrifa::string::StringId;
use skrifa::{FontRef, MetadataProvider};
use super::{FaceInfo, Source, Stretch, Style, Weight};
#[derive(Debug)]
pub(super) enum LoadError {
Malformed,
Unnamed,
}
impl core::fmt::Display for LoadError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
LoadError::Malformed => write!(f, "malformed font"),
LoadError::Unnamed => write!(f, "font doesn't have a family name"),
}
}
}
pub(super) fn parse_face_info(
font: &FontRef,
source: Source,
index: u32,
) -> Result<FaceInfo, LoadError> {
let families = parse_families(font).ok_or(LoadError::Unnamed)?;
let attrs = font.attributes();
let mut style = convert_style(attrs.style);
if style == Style::Normal
&& let Ok(post) = font.post()
&& post.italic_angle().to_f64() != 0.0
{
style = Style::Italic;
}
let weight = Weight(attrs.weight.value().round() as u16);
let stretch = convert_stretch(attrs.stretch);
Ok(FaceInfo {
source,
index,
families,
style,
weight,
stretch,
})
}
fn parse_families(font: &FontRef) -> Option<Vec<(String, Option<String>)>> {
let mut families = collect_localized(font, StringId::TYPOGRAPHIC_FAMILY_NAME);
if families.is_empty() {
families = collect_localized(font, StringId::FAMILY_NAME);
}
if families.is_empty() {
return None;
}
if let Some(index) = families
.iter()
.position(|(_, lang)| lang.as_deref().is_some_and(|l| l.starts_with("en")))
&& index != 0
{
families.swap(0, index);
}
Some(families)
}
fn collect_localized(font: &FontRef, id: StringId) -> Vec<(String, Option<String>)> {
font.localized_strings(id)
.map(|s| (s.to_string(), s.language().map(str::to_string)))
.collect()
}
fn convert_style(style: skrifa::attribute::Style) -> Style {
match style {
skrifa::attribute::Style::Normal => Style::Normal,
skrifa::attribute::Style::Italic => Style::Italic,
skrifa::attribute::Style::Oblique(_) => Style::Oblique,
}
}
fn convert_stretch(stretch: skrifa::attribute::Stretch) -> Stretch {
use skrifa::attribute::Stretch as SkrifaStretch;
match stretch {
s if s == SkrifaStretch::ULTRA_CONDENSED => Stretch::UltraCondensed,
s if s == SkrifaStretch::EXTRA_CONDENSED => Stretch::ExtraCondensed,
s if s == SkrifaStretch::CONDENSED => Stretch::Condensed,
s if s == SkrifaStretch::SEMI_CONDENSED => Stretch::SemiCondensed,
s if s == SkrifaStretch::SEMI_EXPANDED => Stretch::SemiExpanded,
s if s == SkrifaStretch::EXPANDED => Stretch::Expanded,
s if s == SkrifaStretch::EXTRA_EXPANDED => Stretch::ExtraExpanded,
s if s == SkrifaStretch::ULTRA_EXPANDED => Stretch::UltraExpanded,
_ => Stretch::Normal,
}
}