1use crate::image13h;
15use std::io;
16
17pub const ROWS: usize = 3;
19
20pub const CHARACTERS: usize = 91;
22
23pub const CHARACTER_HEIGHT: usize = 13;
24
25pub const ROW_OFFSETS: [(usize, usize); ROWS] = [(7, 8), (8, 32), (7, 56)];
27
28pub const ROW_CHARACTERS: [usize; ROWS] = [33, 31, 27];
30
31pub const MINIMUM_IMAGE_DIMENSIONS: (usize, usize) = (223, 69);
33
34pub const CHARACTER_WIDTHS: [usize; CHARACTERS] = [
36 4, 2, 4, 6, 6, 6, 6, 6, 4, 4, 6, 6, 2, 4, 2, 6, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 8, 6, 8, 6,
38 7, 8, 7, 7, 7, 6, 6, 8, 7, 2, 5, 7, 6, 8, 7, 8, 6, 8, 7, 7, 6, 7, 8, 11, 7, 8, 7, 7, 7, 7, 6, 7,
40 4, 6, 6, 6, 6, 6, 4, 6, 6, 2, 2, 5, 2, 8, 6, 6, 6, 6, 4, 6, 3, 6, 6, 10, 6, 6, 6,
42];
43
44pub const CHARACTER_X_POSITIONS: [usize; CHARACTERS] = [
46 7, 11, 13, 17, 23, 29, 35, 41, 47, 51, 55, 61, 67, 69, 73, 75, 81, 87, 92, 98, 104, 110, 116,
48 122, 128, 134, 140, 142, 144, 152, 158, 166, 172, 8, 16, 23, 30, 37, 43, 49, 57, 64, 66, 71, 78, 84, 92, 99, 107, 113, 121, 128, 135, 141, 148,
50 156, 167, 174, 182, 189, 196, 203, 210, 216, 7, 11, 17, 23, 29, 35, 41, 45, 51, 57, 59, 61, 66, 68, 76, 82, 88, 94, 100, 104, 110, 113, 119,
52 125, 135, 141, 147,
53];
54
55#[derive(Debug, Eq, PartialEq)]
56pub struct Fontdat {
57 glyphs: Vec<image13h::Image13h>,
58}
59
60impl Fontdat {
61 pub fn load<T: io::Read>(reader: T) -> Option<Fontdat> {
66 let image = match image13h::Image13h::load(reader) {
67 None => return None,
68 Some(image) => image,
69 };
70 if (image.width(), image.height()) < MINIMUM_IMAGE_DIMENSIONS {
71 return None;
72 }
73 let mut glyphs = Vec::new();
74 for character in 0..CHARACTERS {
75 let rect = character_rect(character);
76 let glyph = image.subimage(&rect);
77 glyphs.push(glyph);
78 }
79 Some(Fontdat { glyphs })
80 }
81
82 pub fn empty() -> Fontdat {
84 let mut glyphs = Vec::new();
85 for character in 0..CHARACTERS {
86 let rect = character_rect(character);
87 let glyph = image13h::Image13h::empty(rect.width, rect.height);
88 glyphs.push(glyph);
89 }
90 Fontdat { glyphs }
91 }
92
93 pub fn save<T: io::Write>(&self, writer: T) {
95 let mut image =
96 image13h::Image13h::empty(MINIMUM_IMAGE_DIMENSIONS.0, MINIMUM_IMAGE_DIMENSIONS.1);
97 for character in 0..CHARACTERS {
98 let rect = character_rect(character);
99 image.blit(&self.glyphs[character], &rect);
100 }
101 image.save(writer);
102 }
103
104 pub fn glyph(&self, character: usize) -> &image13h::Image13h {
106 &self.glyphs[character]
107 }
108
109 pub fn glyph_mut(&mut self, character: usize) -> &mut image13h::Image13h {
111 &mut self.glyphs[character]
112 }
113}
114
115pub fn character_rect(character: usize) -> image13h::Rect {
116 debug_assert!(character < CHARACTERS);
117 let line = if character < ROW_CHARACTERS[0] {
118 0
119 } else if character < ROW_CHARACTERS[0] + ROW_CHARACTERS[1] {
120 1
121 } else {
122 2
123 };
124
125 let x = CHARACTER_X_POSITIONS[character];
126 let y = ROW_OFFSETS[line].1;
127 image13h::Rect::from_ranges(x..x + CHARACTER_WIDTHS[character], y..y + CHARACTER_HEIGHT)
128}
129
130#[cfg(test)]
131mod tests {
132 use crate::fontdat::{Fontdat, CHARACTERS};
133 use std::fs;
134
135 #[test]
136 fn test_loading_and_saving_works() {
137 let dummy_font_dat = fs::read("dummy_font.dat").unwrap();
140 let fontdat = Fontdat::load(&dummy_font_dat[..]).unwrap();
141 let mut expected_fontdat = Fontdat::empty();
142 for i in 0..CHARACTERS {
143 expected_fontdat.glyph_mut(i).fill(100 + i as u8);
144 }
145 assert_eq!(fontdat, expected_fontdat);
147 let mut buf = Vec::new();
149 fontdat.save(&mut buf);
150 assert_eq!(buf, dummy_font_dat);
151 }
152}