wgpu_font_renderer/
typewriter.rs1use 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}