fea_rs/common/
glyph_class.rs

1use write_fonts::{read::collections::IntSet, types::GlyphId16};
2
3use super::GlyphOrClass;
4
5/// A glyph class, as used in the FEA spec.
6///
7/// This should not be confused with the `ClassDef` table used in OpenType.
8/// In a feature file, a glyph class is an ordered sequence of glyphs, and
9/// may contain duplicates.
10///
11/// For example, single sub format C can take the form,
12///
13/// ```fea
14/// sub [a b c] by [z z d];
15/// # equivalent to:
16/// sub a by z;
17/// sub b by z;
18/// sub c by d;
19/// ```
20///
21/// See the [spec docs] for more information.
22///
23/// [spec docs]: http://adobe-type-tools.github.io/afdko/OpenTypeFeatureFileSpecification.html#2g-glyph-classes
24#[derive(Clone, Debug, PartialEq, Eq, Hash)]
25pub(crate) struct GlyphClass(Vec<GlyphId16>);
26
27/// A sorted set of unique glyph ids.
28///
29/// This type exists to clearly separate the use of 'glyph class' in the fea spec
30/// from how we use it when building tables that contain OpenType glyph ClassDefs.
31pub type GlyphSet = IntSet<GlyphId16>;
32
33impl GlyphClass {
34    /// An empty glyph class
35    pub const EMPTY: Self = GlyphClass(Vec::new());
36
37    pub(crate) fn items(&self) -> &[GlyphId16] {
38        &self.0
39    }
40
41    /// Return a `GlyphSet` containing the unique glyphs in this class.
42    pub(crate) fn to_glyph_set(&self) -> GlyphSet {
43        self.iter().collect()
44    }
45
46    pub(crate) fn iter(&self) -> impl Iterator<Item = GlyphId16> + '_ {
47        self.items().iter().copied()
48    }
49
50    pub(crate) fn len(&self) -> usize {
51        self.0.len()
52    }
53}
54
55impl std::iter::FromIterator<GlyphId16> for GlyphClass {
56    fn from_iter<T: IntoIterator<Item = GlyphId16>>(iter: T) -> Self {
57        GlyphClass(iter.into_iter().collect())
58    }
59}
60
61impl<'a> std::iter::IntoIterator for &'a GlyphClass {
62    type Item = &'a GlyphId16;
63
64    type IntoIter = std::slice::Iter<'a, GlyphId16>;
65
66    fn into_iter(self) -> Self::IntoIter {
67        self.0.iter()
68    }
69}
70
71impl From<Vec<GlyphId16>> for GlyphClass {
72    fn from(src: Vec<GlyphId16>) -> GlyphClass {
73        GlyphClass(src)
74    }
75}
76
77impl From<GlyphClass> for GlyphSet {
78    fn from(value: GlyphClass) -> Self {
79        value.iter().collect()
80    }
81}
82
83impl From<GlyphId16> for GlyphClass {
84    fn from(src: GlyphId16) -> GlyphClass {
85        let slice: &[_] = &[src];
86        GlyphClass(slice.into())
87    }
88}
89
90impl From<GlyphOrClass> for GlyphClass {
91    fn from(src: GlyphOrClass) -> GlyphClass {
92        match src {
93            GlyphOrClass::Class(class) => class,
94            GlyphOrClass::Glyph(id) => id.into(),
95            GlyphOrClass::Null => GlyphClass::EMPTY,
96        }
97    }
98}