Skip to main content

ferroui_pretext_contracts/
text_shaping_contracts.rs

1use std::rc::Rc;
2
3use crate::PretextError;
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6pub enum PretextGlyphRunKind {
7    Shaped = 0,
8    Mapped = 1,
9}
10
11#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
12pub enum PretextTextDirection {
13    #[default]
14    Auto = 0,
15    LeftToRight = 1,
16    RightToLeft = 2,
17}
18
19/// A value snapshot: changing the caller's options cannot mutate cached output.
20#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
21pub struct PretextShapeOptions {
22    pub direction: PretextTextDirection,
23}
24
25#[derive(Clone, Copy, Debug, PartialEq)]
26pub struct PretextShapedGlyph {
27    pub glyph_id: u32,
28    /// UTF-16 code-unit offset into the shaped input.
29    pub cluster: usize,
30    pub x: f64,
31    pub y: f64,
32    pub x_advance: f64,
33    pub y_advance: f64,
34    pub x_offset: f64,
35    pub y_offset: f64,
36    pub font_run_index: usize,
37}
38
39#[derive(Clone, Debug, PartialEq, Eq)]
40pub struct PretextShapedFontRun {
41    pub index: usize,
42    pub font: String,
43    pub first_glyph_index: usize,
44    pub glyph_count: usize,
45}
46
47/// Immutable positioned glyphs and the font runs that produced them.
48#[derive(Clone, Debug, PartialEq)]
49pub struct PretextShapedRun {
50    kind: PretextGlyphRunKind,
51    glyphs: Vec<PretextShapedGlyph>,
52    font_runs: Vec<PretextShapedFontRun>,
53    advance_x: f64,
54    advance_y: f64,
55    has_missing_glyphs: bool,
56}
57
58impl PretextShapedRun {
59    pub fn new(
60        kind: PretextGlyphRunKind,
61        glyphs: Vec<PretextShapedGlyph>,
62        font_runs: Vec<PretextShapedFontRun>,
63        advance_x: f64,
64        advance_y: f64,
65    ) -> Self {
66        let has_missing_glyphs = glyphs.iter().any(|glyph| glyph.glyph_id == 0);
67        Self {
68            kind,
69            glyphs,
70            font_runs,
71            advance_x,
72            advance_y,
73            has_missing_glyphs,
74        }
75    }
76
77    pub fn kind(&self) -> PretextGlyphRunKind {
78        self.kind
79    }
80    pub fn glyphs(&self) -> &[PretextShapedGlyph] {
81        &self.glyphs
82    }
83    pub fn font_runs(&self) -> &[PretextShapedFontRun] {
84        &self.font_runs
85    }
86    pub fn advance_x(&self) -> f64 {
87        self.advance_x
88    }
89    pub fn advance_y(&self) -> f64 {
90        self.advance_y
91    }
92    pub fn has_missing_glyphs(&self) -> bool {
93        self.has_missing_glyphs
94    }
95    pub fn is_shaped(&self) -> bool {
96        self.kind == PretextGlyphRunKind::Shaped
97    }
98}
99
100pub trait IPretextTextShaper {
101    fn shape_text(
102        &self,
103        text: &str,
104        options: PretextShapeOptions,
105    ) -> Result<PretextShapedRun, PretextError>;
106}
107
108pub trait IPretextTextShaperFactory {
109    fn name(&self) -> &str;
110    fn is_supported(&self) -> bool {
111        true
112    }
113    fn priority(&self) -> i32 {
114        0
115    }
116    fn create_shaper(&self, font: &str) -> Result<Rc<dyn IPretextTextShaper>, PretextError>;
117}