1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use std::io::Read;
use crate::*;
pub use rusttype::Font;
pub fn load_font(path: impl AsRef<std::path::Path>) -> Result<Font<'static>, Error> {
let mut font_file = std::fs::File::open(path)?;
let mut data = Vec::new();
font_file.read_to_end(&mut data)?;
match Font::try_from_vec(data) {
Some(x) => Ok(x),
None => Err(Error::Message("Unable to load font".into())),
}
}
pub fn font(data: &[u8]) -> Result<Font<'_>, Error> {
match Font::try_from_bytes(data) {
Some(x) => Ok(x),
None => Err(Error::Message("Unable to load font".into())),
}
}
pub fn width(text: impl AsRef<str>, font: &Font, size: f32) -> usize {
if text.as_ref().is_empty() {
return 0;
}
let scale = rusttype::Scale::uniform(size);
let layout = font.layout(text.as_ref(), scale, rusttype::point(0., 0.));
let mut w = 0;
for glyph in layout {
if let Some(bounding_box) = glyph.pixel_bounding_box() {
w = bounding_box.max.x as usize;
}
}
w
}
impl<T: Type, C: Color> Image<T, C> {
pub fn draw_text<'a>(
&mut self,
text: impl AsRef<str>,
font: &Font<'a>,
size: f32,
pos: impl Into<Point>,
color: &Pixel<C>,
) {
let pos = pos.into();
let scale = rusttype::Scale::uniform(size);
let layout = font.layout(
text.as_ref(),
scale,
rusttype::point(pos.x as f32, pos.y as f32),
);
let mut data = vec![T::from_f64(0.0); C::CHANNELS];
let mut tmp = Pixel::new();
for glyph in layout {
if let Some(bounding_box) = glyph.pixel_bounding_box() {
glyph.draw(|x, y, v| {
let pt = (
(x as isize + bounding_box.min.x as isize) as usize,
(y as isize + bounding_box.min.y as isize) as usize,
);
if self.at(pt, &mut data) {
tmp.copy_from_slice(&data);
let color = &tmp * (1.0 - v) + color * v;
self.set_pixel(pt, &color);
}
});
}
}
}
}