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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use rusttype;
use rusttype::FontCollection;
use Texture;
use Sprite;
use Model;
use TexCoords;
use SpriteList;
use Window;
use window::WindowFunctions;
use Transform;
pub const DEFAULT_FONT: &'static [u8] =
include_bytes!("res/font/SourceCodePro-Regular.ttf");
pub struct Text(Option<(Texture, Sprite)>, (f32, f32), (f32, f32));
impl Text {
pub fn new(_: &mut Window, pos: (f32,f32), wh: (f32,f32)) -> Text {
Text(None, pos, wh)
}
pub fn update(&mut self, window: &mut Window, text: &str, font: &[u8]) {
let win_size = window.wh();
let w = ((win_size.0 as f32 * self.2 .0) as u32) * (text.len() as u32) / 2;
let h = (win_size.0 as f32 * self.2 .1) as u32;
let mut texture = Texture::empty(window, w, h);
let model = Model::new(window,
(&[0, 1, 2, 1, 0, 3],
&[
0.0, 0.0, 0.0, 1.0,
self.2 .0 * 0.5 * (text.len() as f32), self.2 .1, 0.0, 1.0,
self.2 .0 * 0.5 * (text.len() as f32), 0.0, 0.0, 1.0,
0.0, self.2 .1, 0.0, 1.0,
])
);
let tc = TexCoords::new(window, &[
0.0, 0.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0,
1.0, 0.0, 1.0, 1.0,
0.0, 1.0, 1.0, 1.0,
]);
let sprite = SpriteList::new(model)
.transform(Transform::new().translate(self.1 .0, self.1 .1, 0.0))
.gui()
.texture(window, texture, tc)
.only();
let font = Font::new(font);
let mut buf = vec![0; (texture.wh().0 * texture.wh().1) as usize];
font.render(w as usize, h as f32, buf.as_mut_slice(),
(255, 255, 255, 255), text);
texture.set(window, buf.as_slice());
self.0 = Some((texture, sprite));
}
pub fn position(&mut self, x: f32, y: f32) {
self.1 = (x, y);
}
}
pub struct Font<'a>(&'a [u8], rusttype::Font<'a>);
impl<'a> Font<'a> {
pub fn new(font_data: &'a [u8]) -> Font<'a> {
Font(font_data, FontCollection::from_bytes(font_data).into_font().unwrap())
}
pub(crate) fn render(&self, width: usize, height: f32, buffer: &mut [u32],
color: (u8, u8, u8, u8), text: &str) -> ()
{
let pixel_height = height.ceil() as usize;
let scale = rusttype::Scale { x: height, y: height };
let v_metrics = self.1.v_metrics(scale);
let offset = rusttype::point(0.0, v_metrics.ascent);
let glyphs: Vec<rusttype::PositionedGlyph> = self.1
.layout(text, scale, offset)
.collect();
for g in glyphs {
if let Some(bb) = g.pixel_bounding_box() {
g.draw(|x, y, v| {
let c = unsafe { ::std::mem::transmute([
(color.0 as f32 * v) as u8,
(color.1 as f32 * v) as u8,
(color.2 as f32 * v) as u8,
(color.3 as f32 * v) as u8
]) };
let x = x as i32 + bb.min.x;
let y = y as i32 + bb.min.y;
if x >= 0 && x < width as i32 && y >= 0 && y < pixel_height as i32 {
let x = x as usize;
let y = y as usize;
buffer[(x + y * width)] = c;
}
});
}
}
}
}