/
font.rs
105 lines (93 loc) · 3.4 KB
/
font.rs
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
use crate::graphics::gpu::TargetView;
use crate::graphics::{
HorizontalAlignment, Text, Transformation, VerticalAlignment,
};
use wgpu_glyph::GlyphCruncher;
pub struct Font {
glyphs: wgpu_glyph::GlyphBrush<'static>,
}
impl Font {
pub fn from_bytes(device: &mut wgpu::Device, bytes: &'static [u8]) -> Font {
Font {
glyphs: wgpu_glyph::GlyphBrushBuilder::using_font_bytes(bytes)
.texture_filter_method(wgpu::FilterMode::Nearest)
.build(device, wgpu::TextureFormat::Bgra8UnormSrgb),
}
}
pub fn add(&mut self, text: Text<'_>) {
let section: wgpu_glyph::Section<'_> = text.into();
self.glyphs.queue(section);
}
pub fn measure(&mut self, text: Text<'_>) -> (f32, f32) {
let section: wgpu_glyph::Section<'_> = text.into();
let bounds = self.glyphs.pixel_bounds(section);
match bounds {
Some(bounds) => (bounds.width() as f32, bounds.height() as f32),
None => (0.0, 0.0),
}
}
pub fn draw(
&mut self,
device: &mut wgpu::Device,
encoder: &mut wgpu::CommandEncoder,
target: &TargetView,
transformation: Transformation,
) {
self.glyphs
.draw_queued_with_transform(
transformation.into(),
device,
encoder,
target,
)
.expect("Draw font");
}
}
impl<'a> From<Text<'a>> for wgpu_glyph::Section<'a> {
fn from(text: Text<'a>) -> wgpu_glyph::Section<'a> {
let x = match text.horizontal_alignment {
HorizontalAlignment::Left => text.position.x,
HorizontalAlignment::Center => {
text.position.x + text.bounds.0 / 2.0
}
HorizontalAlignment::Right => text.position.x + text.bounds.0,
};
let y = match text.vertical_alignment {
VerticalAlignment::Top => text.position.y,
VerticalAlignment::Center => text.position.y + text.bounds.1 / 2.0,
VerticalAlignment::Bottom => text.position.y + text.bounds.1,
};
wgpu_glyph::Section {
text: &text.content,
screen_position: (x, y),
scale: wgpu_glyph::Scale {
x: text.size,
y: text.size,
},
color: text.color.into_linear(),
bounds: text.bounds,
layout: wgpu_glyph::Layout::default()
.h_align(text.horizontal_alignment.into())
.v_align(text.vertical_alignment.into()),
..Default::default()
}
}
}
impl From<HorizontalAlignment> for wgpu_glyph::HorizontalAlign {
fn from(alignment: HorizontalAlignment) -> wgpu_glyph::HorizontalAlign {
match alignment {
HorizontalAlignment::Left => wgpu_glyph::HorizontalAlign::Left,
HorizontalAlignment::Center => wgpu_glyph::HorizontalAlign::Center,
HorizontalAlignment::Right => wgpu_glyph::HorizontalAlign::Right,
}
}
}
impl From<VerticalAlignment> for wgpu_glyph::VerticalAlign {
fn from(alignment: VerticalAlignment) -> wgpu_glyph::VerticalAlign {
match alignment {
VerticalAlignment::Top => wgpu_glyph::VerticalAlign::Top,
VerticalAlignment::Center => wgpu_glyph::VerticalAlign::Center,
VerticalAlignment::Bottom => wgpu_glyph::VerticalAlign::Bottom,
}
}
}