use std::borrow::Cow;
use ttf_parser::{Face, GlyphId};
#[deprecated(since = "1.14.1", note = "use `dejavu_sans_ttf()`")]
pub static DEJAVU_SANS_TTF: &[u8] = include_bytes!("fonts/DejaVuSans.ttf");
#[must_use]
pub fn dejavu_sans_ttf() -> &'static [u8] {
#[allow(deprecated)]
DEJAVU_SANS_TTF
}
#[derive(Clone, Default)]
pub struct FontSource {
faces: Vec<Cow<'static, [u8]>>,
}
impl FontSource {
#[must_use]
pub fn new() -> Self {
Self { faces: Vec::new() }
}
#[must_use]
pub fn dejavu_sans() -> Self {
Self {
faces: vec![Cow::Borrowed(dejavu_sans_ttf())],
}
}
pub fn register_face(&mut self, data: &[u8]) {
self.faces.push(Cow::Owned(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)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn embedded_font_inflates_to_the_vendored_ttf() {
let ttf = dejavu_sans_ttf();
assert_eq!(ttf.len(), 756_072);
let fnv = ttf.iter().fold(0xcbf2_9ce4_8422_2325_u64, |h, &b| {
(h ^ u64::from(b)).wrapping_mul(0x0000_0100_0000_01b3)
});
assert_eq!(fnv, 0xc6bb_b6aa_5af4_6d0b);
}
#[test]
fn default_sources_share_the_inflated_font() {
let (a, b) = (FontSource::dejavu_sans(), FontSource::dejavu_sans());
assert!(std::ptr::eq(a.faces[0].as_ref(), b.faces[0].as_ref()));
}
}