forked from LiveSplit/livesplit-core
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathglyph_cache.rs
82 lines (72 loc) · 2.29 KB
/
glyph_cache.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
use super::mesh::{fill_builder, Mesh};
use super::Backend;
use hashbrown::HashMap;
use lyon::{
path::{self, math::point, Path},
tessellation::{FillOptions, FillTessellator},
};
use rusttype::{Font, GlyphId, OutlineBuilder, Scale};
struct PathBuilder(path::Builder);
impl OutlineBuilder for PathBuilder {
fn move_to(&mut self, x: f32, y: f32) {
self.0.move_to(point(x, y));
}
fn line_to(&mut self, x: f32, y: f32) {
self.0.line_to(point(x, y));
}
fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32) {
self.0.quadratic_bezier_to(point(x1, y1), point(x, y));
}
fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) {
self.0
.cubic_bezier_to(point(x1, y1), point(x2, y2), point(x, y));
}
fn close(&mut self) {
self.0.close();
}
}
pub struct GlyphCache<M> {
glyphs: HashMap<GlyphId, M>,
}
impl<M> Default for GlyphCache<M> {
fn default() -> Self {
Self {
glyphs: Default::default(),
}
}
}
impl<M> GlyphCache<M> {
pub fn new() -> Self {
Default::default()
}
pub fn lookup_or_insert(
&mut self,
font: &Font<'_>,
glyph: GlyphId,
backend: &mut impl Backend<Mesh = M>,
) -> &M {
self.glyphs.entry(glyph).or_insert_with(|| {
let metrics = font.v_metrics(Scale::uniform(1.0));
let delta_h = metrics.ascent - metrics.descent;
let offset_h = metrics.descent;
let glyph = font.glyph(glyph).scaled(Scale::uniform(1.0));
let mut builder = PathBuilder(Path::builder());
let mut glyph_mesh = Mesh::new();
if glyph.build_outline(&mut builder) {
let path = builder.0.build();
let mut tessellator = FillTessellator::new();
tessellator
.tessellate_path(
&path,
&FillOptions::tolerance(0.005),
&mut fill_builder(&mut glyph_mesh),
)
.unwrap();
for vertex in glyph_mesh.vertices_mut() {
vertex.v = (-vertex.y - offset_h) * delta_h;
}
}
backend.create_mesh(&glyph_mesh)
})
}
}