iced_markdown_editor/
fonts.rs1use ab_glyph::{Font as _, FontRef};
9use iced::Font;
10use iced::font::{Style as FontStyle, Weight};
11
12pub const SANS_REGULAR_BYTES: &[u8] = include_bytes!("../assets/fonts/DejaVuSans.ttf");
13pub const SANS_BOLD_BYTES: &[u8] = include_bytes!("../assets/fonts/DejaVuSans-Bold.ttf");
14pub const SANS_ITALIC_BYTES: &[u8] = include_bytes!("../assets/fonts/DejaVuSans-Oblique.ttf");
15pub const SANS_BOLD_ITALIC_BYTES: &[u8] =
16 include_bytes!("../assets/fonts/DejaVuSans-BoldOblique.ttf");
17pub const MONO_REGULAR_BYTES: &[u8] = include_bytes!("../assets/fonts/DejaVuSansMono.ttf");
18pub const MONO_BOLD_BYTES: &[u8] = include_bytes!("../assets/fonts/DejaVuSansMono-Bold.ttf");
19
20pub const FONTS: [&[u8]; 6] = [
29 SANS_REGULAR_BYTES,
30 SANS_BOLD_BYTES,
31 SANS_ITALIC_BYTES,
32 SANS_BOLD_ITALIC_BYTES,
33 MONO_REGULAR_BYTES,
34 MONO_BOLD_BYTES,
35];
36
37pub const SANS: Font = Font::with_name("DejaVu Sans");
38pub const SANS_BOLD: Font = Font {
39 weight: Weight::Bold,
40 ..SANS
41};
42pub const SANS_ITALIC: Font = Font {
43 style: FontStyle::Italic,
44 ..SANS
45};
46pub const SANS_BOLD_ITALIC: Font = Font {
47 weight: Weight::Bold,
48 style: FontStyle::Italic,
49 ..SANS
50};
51pub const MONO: Font = Font::with_name("DejaVu Sans Mono");
52pub const MONO_BOLD: Font = Font {
53 weight: Weight::Bold,
54 ..MONO
55};
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub enum Face {
61 Sans = 0,
62 SansBold = 1,
63 SansItalic = 2,
64 SansBoldItalic = 3,
65 Mono = 4,
66 MonoBold = 5,
67}
68
69impl Face {
70 pub fn select(bold: bool, italic: bool, mono: bool) -> Face {
71 match (mono, bold, italic) {
72 (true, true, _) => Face::MonoBold,
73 (true, false, _) => Face::Mono,
74 (false, true, true) => Face::SansBoldItalic,
75 (false, true, false) => Face::SansBold,
76 (false, false, true) => Face::SansItalic,
77 (false, false, false) => Face::Sans,
78 }
79 }
80
81 pub fn font(self) -> Font {
82 match self {
83 Face::Sans => SANS,
84 Face::SansBold => SANS_BOLD,
85 Face::SansItalic => SANS_ITALIC,
86 Face::SansBoldItalic => SANS_BOLD_ITALIC,
87 Face::Mono => MONO,
88 Face::MonoBold => MONO_BOLD,
89 }
90 }
91}
92
93pub struct Fonts {
95 faces: Vec<FontRef<'static>>,
96 units_per_em: Vec<f32>,
97}
98
99impl Fonts {
100 pub fn load() -> Self {
101 let mut faces = Vec::with_capacity(FONTS.len());
102 let mut units_per_em = Vec::with_capacity(FONTS.len());
103
104 for bytes in FONTS {
105 let face = FontRef::try_from_slice(bytes).expect("bundled font must be valid");
106 units_per_em.push(face.units_per_em().unwrap_or(2048.0));
107 faces.push(face);
108 }
109
110 Self {
111 faces,
112 units_per_em,
113 }
114 }
115
116 pub fn advance(&self, face: Face, c: char, size: f32) -> f32 {
118 let index = face as usize;
119 let font = &self.faces[index];
120 let glyph = font.glyph_id(c);
121 font.h_advance_unscaled(glyph) * size / self.units_per_em[index]
122 }
123
124 pub fn width(&self, face: Face, text: &str, size: f32) -> f32 {
126 text.chars().map(|c| self.advance(face, c, size)).sum()
127 }
128}