Skip to main content

write_fonts/tables/
gsub.rs

1//! the [GSUB] table
2//!
3//! [GSUB]: https://docs.microsoft.com/en-us/typography/opentype/spec/gsub
4
5include!("../../generated/generated_gsub.rs");
6
7use super::layout::{
8    ChainedSequenceContext, CoverageTable, FeatureList, FeatureVariations, Lookup, LookupList,
9    LookupSubtable, LookupType, ScriptList, SequenceContext,
10};
11
12pub mod builders;
13#[cfg(test)]
14mod extended;
15#[cfg(test)]
16mod spec_tests;
17
18/// A GSUB lookup list table.
19pub type SubstitutionLookupList = LookupList<SubstitutionLookup>;
20
21/// A lookup list with the original 16-bit offsets.
22pub type OriginalSubstitutionLookupList = SubstitutionLookupList;
23
24/// A lookup list with 32-bit offsets.
25pub type SubstitutionLookupList2 = super::layout::LookupList2<SubstitutionLookup>;
26
27super::layout::table_newtype!(
28    SubstitutionSequenceContext,
29    SequenceContext,
30    read_fonts::tables::layout::SequenceContext<'a>
31);
32
33super::layout::table_newtype!(
34    SubstitutionChainContext,
35    ChainedSequenceContext,
36    read_fonts::tables::layout::ChainedSequenceContext<'a>
37);
38
39impl Gsub {
40    /// Creates a GSUB table using the original 16-bit header offsets.
41    pub fn new(
42        script_list: ScriptList,
43        feature_list: FeatureList,
44        lookup_list: SubstitutionLookupList,
45    ) -> Self {
46        Self {
47            script_list: Some(script_list).into(),
48            feature_list: Some(feature_list).into(),
49            lookup_list: Some(lookup_list).into(),
50            ..Default::default()
51        }
52    }
53
54    fn compute_version(&self) -> MajorMinor {
55        if self.script_list2.is_some()
56            || self.feature_list2.is_some()
57            || self.lookup_list2.is_some()
58        {
59            MajorMinor::new(1, 2)
60        } else if self.feature_variations.is_none() {
61            MajorMinor::VERSION_1_0
62        } else {
63            MajorMinor::VERSION_1_1
64        }
65    }
66}
67
68super::layout::lookup_type!(gsub, SingleSubst, 1);
69super::layout::lookup_type!(gsub, MultipleSubstFormat1, 2);
70super::layout::lookup_type!(gsub, AlternateSubstFormat1, 3);
71super::layout::lookup_type!(gsub, LigatureSubstFormat1, 4);
72super::layout::lookup_type!(gsub, SubstitutionSequenceContext, 5);
73super::layout::lookup_type!(gsub, SubstitutionChainContext, 6);
74super::layout::lookup_type!(gsub, ExtensionSubtable, 7);
75super::layout::lookup_type!(gsub, ReverseChainSingleSubstFormat1, 8);
76
77impl<T: LookupSubtable + FontWrite> FontWrite for ExtensionSubstFormat1<T> {
78    fn write_into(&self, writer: &mut TableWriter) {
79        1u16.write_into(writer);
80        T::TYPE.write_into(writer);
81        self.extension.write_into(writer);
82    }
83}
84
85// these can't have auto impls because the traits don't support generics
86impl ReadArgs for SubstitutionLookup {
87    type Args = ();
88}
89
90impl<'a> FontRead<'a> for SubstitutionLookup {
91    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
92        read_fonts::tables::gsub::SubstitutionLookup::read(data).map(|x| x.to_owned_table())
93    }
94}
95
96impl ReadArgs for SubstitutionLookupList {
97    type Args = ();
98}
99
100impl<'a> FontRead<'a> for SubstitutionLookupList {
101    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
102        read_fonts::tables::gsub::OriginalSubstitutionLookupList::read(data)
103            .map(|x| x.to_owned_table())
104    }
105}
106
107super::layout::lookup_type!(gsub, MultipleSubst, 2);
108super::layout::lookup_type!(gsub, MultipleSubstFormat2, 2);
109super::layout::original_lookup!(
110    SubstitutionLookup,
111    Multiple,
112    MultipleSubstFormat1,
113    MultipleSubst
114);
115
116super::layout::lookup_type!(gsub, AlternateSubst, 3);
117super::layout::lookup_type!(gsub, AlternateSubstFormat2, 3);
118super::layout::original_lookup!(
119    SubstitutionLookup,
120    Alternate,
121    AlternateSubstFormat1,
122    AlternateSubst
123);
124
125super::layout::lookup_type!(gsub, LigatureSubst, 4);
126super::layout::lookup_type!(gsub, LigatureSubstFormat2, 4);
127super::layout::original_lookup!(
128    SubstitutionLookup,
129    Ligature,
130    LigatureSubstFormat1,
131    LigatureSubst
132);
133
134super::layout::lookup_type!(gsub, ReverseChainSingleSubst, 8);
135super::layout::lookup_type!(gsub, ReverseChainSingleSubstFormat2, 8);
136super::layout::original_lookup!(
137    SubstitutionLookup,
138    Reverse,
139    ReverseChainSingleSubstFormat1,
140    ReverseChainSingleSubst
141);
142
143impl ReadArgs for SubstitutionLookupList2 {
144    type Args = ();
145}
146
147impl<'a> FontRead<'a> for SubstitutionLookupList2 {
148    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
149        read_fonts::tables::gsub::SubstitutionLookupList2::read(data).map(|x| x.to_owned_table())
150    }
151}