1#![no_std]
2
3mod char_size;
4mod draw_target;
5mod framebuf;
6mod generated;
7pub mod mapping;
8mod mono_image;
9mod multi_mono_text_style;
10mod static_text;
11mod sub_image;
12
13use core::fmt;
14
15pub use char_size::CharSize;
16pub use framebuf::{BulkFlushTarget, Framebuffer};
17pub use generated::*;
18use mapping::StrGlyphMapping;
19pub use mono_image::MonoImage;
20pub use multi_mono_text_style::{
21 MultiMonoLineHeight, MultiMonoTextStyle, MultiMonoTextStyleBuilder,
22};
23pub use static_text::StaticText;
24
25pub type MultiMonoFontList<'a> = &'a [&'a MultiMonoFont<'a>];
26
27use embedded_graphics::{
28 geometry::{OriginDimensions, Point},
29 image::ImageRaw,
30 pixelcolor::BinaryColor,
31 primitives::Rectangle,
32};
33use sub_image::SubImage;
34
35#[cfg(not(feature = "big-character-size"))]
36pub type ChSzTy = u8;
37#[cfg(feature = "big-character-size")]
38pub type ChSzTy = u16;
39
40pub trait Scalable {
42 type T;
43 fn set_scale(&mut self, scale: Self::T);
44 fn get_scale(&self) -> Self::T;
45}
46
47#[derive(Clone, Copy)]
53pub struct MultiMonoFont<'a> {
54 pub image: ImageRaw<'a, BinaryColor>,
56
57 pub character_size: CharSize,
59
60 pub character_spacing: ChSzTy,
65
66 pub baseline: ChSzTy,
70
71 pub glyph_mapping: &'a StrGlyphMapping<'a>,
73}
74
75impl MultiMonoFont<'_> {
76 pub(crate) fn glyph(&self, c: char) -> SubImage<'_, ImageRaw<'_, BinaryColor>> {
78 if self.character_size.width == 0
79 || self.image.size().width < self.character_size.width as u32
80 {
81 return SubImage::new_unchecked(&self.image, Rectangle::zero());
82 }
83
84 let glyphs_per_row = self.image.size().width / self.character_size.width as u32;
85
86 let glyph_index = self.glyph_mapping.index(c) as u32;
89 let row = glyph_index / glyphs_per_row;
90
91 let char_x = (glyph_index - (row * glyphs_per_row)) * self.character_size.width as u32;
93 let char_y = row * self.character_size.height as u32;
94
95 SubImage::new_unchecked(
96 &self.image,
97 Rectangle::new(
98 Point::new(char_x as i32, char_y as i32),
99 self.character_size.size(),
100 ),
101 )
102 }
103}
104
105impl PartialEq for MultiMonoFont<'_> {
106 #[allow(trivial_casts)]
107 fn eq(&self, other: &Self) -> bool {
108 self.image == other.image
109 && self.character_size == other.character_size
110 && self.character_spacing == other.character_spacing
111 && self.baseline == other.baseline
112 && core::ptr::eq(self.glyph_mapping, other.glyph_mapping)
113 }
114}
115
116impl fmt::Debug for MultiMonoFont<'_> {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 f.debug_struct("MultiMonoFont")
119 .field("image", &self.image)
120 .field("character_size", &self.character_size)
121 .field("character_spacing", &self.character_spacing)
122 .field("baseline", &self.baseline)
123 .field("glyph_mapping", &"?")
124 .finish_non_exhaustive()
125 }
126}
127
128#[cfg(feature = "defmt")]
129impl ::defmt::Format for MultiMonoFont<'_> {
130 fn format(&self, f: ::defmt::Formatter) {
131 ::defmt::write!(
132 f,
133 "MultiMonoFont {{ image: {}, character_size: {}, character_spacing: {}, baseline: {}, strikethrough: {}, underline: {}, .. }}",
134 &self.image,
135 &self.character_size,
136 &self.character_spacing,
137 &self.baseline,
138 &self.strikethrough,
139 &self.underline,
140
141 )
142 }
143}
144
145const NULL_FONT: MultiMonoFont = MultiMonoFont {
146 image: ImageRaw::new(&[], 1),
147 character_size: CharSize::zero(),
148 character_spacing: 0,
149 baseline: 0,
150 glyph_mapping: &StrGlyphMapping::new("", 0),
151};