Skip to main content

harfrust/hb/ot/gsub/
reverse_chain.rs

1use crate::hb::buffer::GlyphInfo;
2use crate::hb::ot_layout::MAX_NESTING_LEVEL;
3use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
4use crate::hb::ot_layout_gsubgpos::{
5    match_backtrack, match_lookahead, Apply, WouldApply, WouldApplyContext,
6};
7use read_fonts::tables::gsub::ReverseChainSingleSubstFormat1;
8
9impl WouldApply for ReverseChainSingleSubstFormat1<'_> {
10    fn would_apply(&self, ctx: &WouldApplyContext) -> bool {
11        ctx.glyphs.len() == 1
12            && self
13                .coverage()
14                .ok()
15                .and_then(|coverage| coverage.get(ctx.glyphs[0]))
16                .is_some()
17    }
18}
19
20impl Apply for ReverseChainSingleSubstFormat1<'_> {
21    fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
22        // No chaining to this type.
23        if ctx.nesting_level_left != MAX_NESTING_LEVEL {
24            return None;
25        }
26
27        let glyph = ctx.buffer.cur(0).as_glyph();
28        let coverage = self.coverage().ok()?;
29        let index = coverage.get(glyph)? as usize;
30        let substitutes = self.substitute_glyph_ids();
31        if index >= substitutes.len() {
32            return None;
33        }
34
35        let subst = substitutes.get(index)?.get();
36
37        let backtrack_coverages = self.backtrack_coverages();
38        let lookahead_coverages = self.lookahead_coverages();
39
40        let f1 = |info: &mut GlyphInfo, index| {
41            backtrack_coverages
42                .get(index as usize)
43                .ok()
44                .and_then(|coverage| coverage.get(info.glyph_id))
45                .is_some()
46        };
47
48        let f2 = |info: &mut GlyphInfo, index| {
49            lookahead_coverages
50                .get(index as usize)
51                .ok()
52                .and_then(|coverage| coverage.get(info.glyph_id))
53                .is_some()
54        };
55
56        let mut start_index = 0;
57        let mut end_index = 0;
58
59        if match_backtrack(ctx, backtrack_coverages.len() as u16, f1, &mut start_index) {
60            if match_lookahead(
61                ctx,
62                lookahead_coverages.len() as u16,
63                f2,
64                ctx.buffer.idx + 1,
65                &mut end_index,
66            ) {
67                ctx.buffer
68                    .unsafe_to_break_from_outbuffer(Some(start_index), Some(end_index));
69                ctx.replace_glyph_inplace(subst.into());
70
71                // Note: We DON'T decrease buffer.idx.  The main loop does it
72                // for us.  This is useful for preventing surprises if someone
73                // calls us through a Context lookup.
74                return Some(());
75            }
76        }
77
78        ctx.buffer
79            .unsafe_to_concat_from_outbuffer(Some(start_index), Some(end_index));
80        None
81    }
82}