use ab_glyph::{Font as _, FontRef};
use iced::Font;
use iced::font::{Style as FontStyle, Weight};
pub const SANS_REGULAR_BYTES: &[u8] = include_bytes!("../assets/fonts/DejaVuSans.ttf");
pub const SANS_BOLD_BYTES: &[u8] = include_bytes!("../assets/fonts/DejaVuSans-Bold.ttf");
pub const SANS_ITALIC_BYTES: &[u8] = include_bytes!("../assets/fonts/DejaVuSans-Oblique.ttf");
pub const SANS_BOLD_ITALIC_BYTES: &[u8] =
include_bytes!("../assets/fonts/DejaVuSans-BoldOblique.ttf");
pub const MONO_REGULAR_BYTES: &[u8] = include_bytes!("../assets/fonts/DejaVuSansMono.ttf");
pub const MONO_BOLD_BYTES: &[u8] = include_bytes!("../assets/fonts/DejaVuSansMono-Bold.ttf");
pub const FONTS: [&[u8]; 6] = [
SANS_REGULAR_BYTES,
SANS_BOLD_BYTES,
SANS_ITALIC_BYTES,
SANS_BOLD_ITALIC_BYTES,
MONO_REGULAR_BYTES,
MONO_BOLD_BYTES,
];
pub const SANS: Font = Font::with_name("DejaVu Sans");
pub const SANS_BOLD: Font = Font {
weight: Weight::Bold,
..SANS
};
pub const SANS_ITALIC: Font = Font {
style: FontStyle::Italic,
..SANS
};
pub const SANS_BOLD_ITALIC: Font = Font {
weight: Weight::Bold,
style: FontStyle::Italic,
..SANS
};
pub const MONO: Font = Font::with_name("DejaVu Sans Mono");
pub const MONO_BOLD: Font = Font {
weight: Weight::Bold,
..MONO
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Face {
Sans = 0,
SansBold = 1,
SansItalic = 2,
SansBoldItalic = 3,
Mono = 4,
MonoBold = 5,
}
impl Face {
pub fn select(bold: bool, italic: bool, mono: bool) -> Face {
match (mono, bold, italic) {
(true, true, _) => Face::MonoBold,
(true, false, _) => Face::Mono,
(false, true, true) => Face::SansBoldItalic,
(false, true, false) => Face::SansBold,
(false, false, true) => Face::SansItalic,
(false, false, false) => Face::Sans,
}
}
pub fn font(self) -> Font {
match self {
Face::Sans => SANS,
Face::SansBold => SANS_BOLD,
Face::SansItalic => SANS_ITALIC,
Face::SansBoldItalic => SANS_BOLD_ITALIC,
Face::Mono => MONO,
Face::MonoBold => MONO_BOLD,
}
}
}
pub struct Fonts {
faces: Vec<FontRef<'static>>,
units_per_em: Vec<f32>,
}
impl Fonts {
pub fn load() -> Self {
let mut faces = Vec::with_capacity(FONTS.len());
let mut units_per_em = Vec::with_capacity(FONTS.len());
for bytes in FONTS {
let face = FontRef::try_from_slice(bytes).expect("bundled font must be valid");
units_per_em.push(face.units_per_em().unwrap_or(2048.0));
faces.push(face);
}
Self {
faces,
units_per_em,
}
}
pub fn advance(&self, face: Face, c: char, size: f32) -> f32 {
let index = face as usize;
let font = &self.faces[index];
let glyph = font.glyph_id(c);
font.h_advance_unscaled(glyph) * size / self.units_per_em[index]
}
pub fn width(&self, face: Face, text: &str, size: f32) -> f32 {
text.chars().map(|c| self.advance(face, c, size)).sum()
}
}