swash/shape/
cluster.rs

1/*!
2Glyph cluster modeling-- output from the shaper.
3*/
4
5use super::buffer::MARK_ATTACH;
6use crate::text::cluster::{ClusterInfo, SourceRange, UserData};
7use crate::GlyphId;
8
9/// Information for a glyph.
10#[derive(Copy, Clone, Default, Debug)]
11pub struct GlyphInfo(pub u16);
12
13impl GlyphInfo {
14    /// Returns true if the glyph is an attached mark.
15    pub fn is_mark(self) -> bool {
16        self.0 & MARK_ATTACH != 0
17    }
18}
19
20/// Glyph identifier and positioning information as a result of shaping.
21#[derive(Copy, Clone, Default, Debug)]
22pub struct Glyph {
23    /// Glyph identifier.
24    pub id: GlyphId,
25    /// Glyph flags.
26    pub info: GlyphInfo,
27    /// Horizontal offset.
28    pub x: f32,
29    /// Vertical offset.
30    pub y: f32,
31    /// Advance width or height.
32    pub advance: f32,
33    /// Arbitrary user data.
34    pub data: UserData,
35}
36
37/// Collection of glyphs and associated metadata corresponding to one or
38/// more source clusters.
39#[derive(Copy, Clone, Debug)]
40pub struct GlyphCluster<'a> {
41    /// Full source range of the cluster in original units supplied to the
42    /// shaper.
43    pub source: SourceRange,
44    /// Information about the textual content of the cluster.
45    pub info: ClusterInfo,
46    /// Sequence of glyphs for the cluster. May be empty for clusters whose
47    /// source consisted entirely of control characters.
48    pub glyphs: &'a [Glyph],
49    /// If the cluster is a ligature, this contains the source range
50    /// of each ligature component. Empty otherwise.
51    pub components: &'a [SourceRange],
52    /// Arbitrary user data-- taken from the initial character of the cluster.
53    pub data: UserData,
54}
55
56impl<'a> GlyphCluster<'a> {
57    /// Returns true if the cluster is empty. Empty clusters still represent
58    /// characters in the source text, but contain no glyphs. This will be
59    /// true, for example, with newline sequences (\n or \r\n) as well as other
60    /// control characters.
61    pub fn is_empty(&self) -> bool {
62        self.glyphs.is_empty()
63    }
64
65    /// Returns true if the cluster contains a single glyph. Note that a simple
66    /// cluster can also be a ligature.
67    pub fn is_simple(&self) -> bool {
68        self.glyphs.len() == 1
69    }
70
71    /// Returns true if the cluster corresponds to multiple source clusters.
72    /// Note that a ligature cluster can also be complex.
73    pub fn is_ligature(&self) -> bool {
74        !self.components.is_empty()
75    }
76
77    /// Returns true if the cluster is complex-- that is if it contains more
78    /// than one glyph. This will be true for clusters containing marks and is
79    /// also commonly true for syllabic languages such as those in the Indic
80    /// family.
81    pub fn is_complex(&self) -> bool {
82        self.glyphs.len() > 1
83    }
84
85    /// Computes the full advance width or height of the cluster.
86    pub fn advance(&self) -> f32 {
87        let mut advance = 0.;
88        for g in self.glyphs {
89            advance += g.advance;
90        }
91        advance
92    }
93}