wgpu_font_renderer/
typewriter.rs

1use owned_ttf_parser::{AsFaceRef, GlyphId};
2use swash::{shape::ShapeContext, text::Script, CacheKey};
3
4use crate::{loader::Glyph, FontStore};
5
6pub struct Paragraph {
7    pub glyphs: Vec<(GlyphId, f32)>,
8    pub position: [f32; 2],
9    pub width: f32,
10    pub size: u16,
11    pub font_key: CacheKey,
12    pub color: [f32; 4],
13}
14
15impl Paragraph {
16    pub fn new(position: [f32; 2], size: u16, color: [f32; 4], font_key: CacheKey) -> Self {
17        Self {
18            glyphs: Vec::new(),
19            position,
20            width: 0.,
21            size,
22            font_key,
23            color,
24        }
25    }
26
27    pub fn append(&mut self, glyph_id: GlyphId, left: f32) {
28        self.width += left;
29        self.glyphs.push((glyph_id, left));
30    }
31
32
33}
34
35pub struct TypeWriter {
36    context: ShapeContext,
37}
38
39impl TypeWriter {
40
41    pub fn new() -> Self {
42        Self {
43            context: ShapeContext::new()
44        }
45    }
46
47    pub fn shape_text(&mut self, font_store: &FontStore, font_key: CacheKey, position: [f32; 2], size: u16, color: [f32; 4], text: &str) -> Option<Paragraph> {
48        if let Some(font) = font_store.get(font_key) {
49            let mut shaper = self.context.builder(font.as_ref())
50                .script(Script::Latin)
51                .size(size as f32)
52                .build();
53
54            let face = font.face.as_face_ref();
55
56            let mut paragraph = Paragraph::new(position, size, color, font_key);
57
58            shaper.add_str(text);
59            shaper.shape_with(|cluster| {
60                let glyph_id = GlyphId(cluster.glyphs[0].id);
61                paragraph.append(glyph_id, cluster.glyphs[0].advance)
62            });
63
64            Some(paragraph)
65        } else {
66            None
67        }
68    } 
69}