use ttf_parser::{Face, GlyphId};
pub static DEJAVU_SANS_TTF: &[u8] = include_bytes!("fonts/DejaVuSans.ttf");
#[derive(Clone, Default)]
pub struct FontSource {
faces: Vec<Vec<u8>>,
}
impl FontSource {
#[must_use]
pub fn new() -> Self {
Self { faces: Vec::new() }
}
#[must_use]
pub fn dejavu_sans() -> Self {
let mut source = Self::new();
source.register_face(DEJAVU_SANS_TTF);
source
}
pub fn register_face(&mut self, data: &[u8]) {
self.faces.push(data.to_vec());
}
#[must_use]
pub fn len(&self) -> usize {
self.faces.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.faces.is_empty()
}
#[must_use]
pub fn has_glyph(&self, ch: char) -> bool {
self.primary_face()
.and_then(|face| face.glyph_index(ch))
.is_some()
}
#[must_use]
pub(crate) fn primary_face(&self) -> Option<Face<'_>> {
let bytes = self.faces.first()?;
Face::parse(bytes, 0).ok()
}
}
#[must_use]
pub(crate) fn horizontal_kerning(face: &Face<'_>, left: GlyphId, right: GlyphId) -> f64 {
let Some(kern) = face.tables().kern else {
return 0.0;
};
let mut units: i32 = 0;
for subtable in kern.subtables {
if !subtable.horizontal || subtable.variable {
continue;
}
if let Some(value) = subtable.glyphs_kerning(left, right) {
units += i32::from(value);
}
}
f64::from(units)
}