use crate::{FileRef, FontRead};
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum FontFormat {
Sfnt(u32),
Type1,
Cff(u32),
}
impl FontFormat {
pub fn new(data: &[u8]) -> Option<Self> {
if let Ok(file) = FileRef::new(data) {
let format = match file {
FileRef::Collection(collection) => Self::Sfnt(collection.len()),
FileRef::Font(_) => Self::Sfnt(1),
};
Some(format)
} else if check_type1(data) {
Some(Self::Type1)
} else if let Ok(cff) = crate::ps::cff::v1::Cff::read(data.into()) {
Some(Self::Cff(cff.top_dicts().count() as u32))
} else {
None
}
}
pub fn is_sfnt(&self) -> bool {
matches!(self, Self::Sfnt(_))
}
pub fn num_fonts(&self) -> u32 {
match self {
Self::Sfnt(n) | Self::Cff(n) => *n,
_ => 1,
}
}
}
fn check_type1(data: &[u8]) -> bool {
fn check(data: &[u8]) -> bool {
data.starts_with(b"%!PS-AdobeFont") || data.starts_with(b"%!FontType")
}
check(data) || data.get(6..).map(check).unwrap_or(false)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{FontRef, TableProvider};
#[test]
fn check_formats() {
let pure_cff = FontRef::new(font_test_data::MATERIAL_ICONS_SUBSET)
.unwrap()
.cff()
.unwrap()
.offset_data()
.as_bytes();
use FontFormat::*;
#[rustfmt::skip]
let pairs = [
(font_test_data::CANTARELL_VF_TRIMMED, Sfnt(1)),
(font_test_data::TINOS_SUBSET, Sfnt(1)),
(pure_cff, Cff(1)),
(font_test_data::ttc::TTC, Sfnt(2)),
(font_test_data::type1::NOTO_SERIF_REGULAR_SUBSET_PFA, Type1),
];
for (data, expected_format) in pairs {
assert_eq!(FontFormat::new(data).unwrap(), expected_format);
}
assert!(FontFormat::new(b"I'm not a font").is_none());
}
}