accessibility_tree/
text.rs

1use crate::fonts::{Em, Font, FontError, GlyphId};
2use crate::primitives::Length;
3use std::sync::Arc;
4
5#[derive(Clone)]
6pub struct ShapedSegment {
7    pub font: Arc<Font>,
8    pub glyphs: Vec<GlyphId>,
9    pub advance_width: Length<Em>,
10}
11
12pub struct ShapedSegmentState {
13    glyphs: usize,
14    advance_width: Length<Em>,
15}
16
17impl std::fmt::Debug for ShapedSegment {
18    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
19        fmt.write_str("ShapedSegment")
20    }
21}
22
23impl ShapedSegment {
24    /// Simplistic text shaping:
25    ///
26    /// * No font fallback
27    /// * No support for complex scripts
28    /// * No ligatures
29    /// * No kerning
30    pub fn naive_shape(text: &str, font: Arc<Font>) -> Result<Self, FontError> {
31        let mut s = Self::new_with_naive_shaping(font);
32        s.append(text.chars())?;
33        Ok(s)
34    }
35
36    pub fn new_with_naive_shaping(font: Arc<Font>) -> Self {
37        Self {
38            font,
39            glyphs: Vec::new(),
40            advance_width: Length::new(0.),
41        }
42    }
43
44    pub fn append(&mut self, mut text: impl Iterator<Item = char>) -> Result<(), FontError> {
45        text.try_for_each(|ch| self.append_char(ch))
46    }
47
48    pub fn append_char(&mut self, ch: char) -> Result<(), FontError> {
49        let id = self.font.glyph_id(ch)?;
50        self.advance_width += self.font.glyph_width(id)?;
51        self.glyphs.push(id);
52        Ok(())
53    }
54
55    pub fn save(&self) -> ShapedSegmentState {
56        ShapedSegmentState {
57            glyphs: self.glyphs.len(),
58            advance_width: self.advance_width,
59        }
60    }
61
62    pub fn restore(&mut self, state: &ShapedSegmentState) {
63        self.glyphs.truncate(state.glyphs);
64        self.advance_width = state.advance_width;
65    }
66}