rustybuzz/hb/ot/layout/GSUB/
ligature.rs

1use crate::hb::ot_layout::MAX_CONTEXT_LENGTH;
2use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
3use crate::hb::ot_layout_gsubgpos::{
4    ligate_input, match_glyph, match_input, Apply, WouldApply, WouldApplyContext,
5};
6use ttf_parser::gsub::Ligature;
7
8impl WouldApply for Ligature<'_> {
9    fn would_apply(&self, ctx: &WouldApplyContext) -> bool {
10        ctx.glyphs.len() == usize::from(self.components.len()) + 1
11            && self
12                .components
13                .into_iter()
14                .enumerate()
15                .all(|(i, comp)| ctx.glyphs[i + 1] == comp)
16    }
17}
18
19impl Apply for Ligature<'_> {
20    fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
21        // Special-case to make it in-place and not consider this
22        // as a "ligated" substitution.
23        if self.components.is_empty() {
24            ctx.replace_glyph(self.glyph);
25            Some(())
26        } else {
27            let f = |glyph, num_items| {
28                let index = self.components.len() - num_items;
29                let value = self.components.get(index).unwrap();
30                match_glyph(glyph, value.0)
31            };
32
33            let mut match_end = 0;
34            let mut match_positions = [0; MAX_CONTEXT_LENGTH];
35            let mut total_component_count = 0;
36
37            if !match_input(
38                ctx,
39                self.components.len(),
40                &f,
41                &mut match_end,
42                &mut match_positions,
43                Some(&mut total_component_count),
44            ) {
45                ctx.buffer
46                    .unsafe_to_concat(Some(ctx.buffer.idx), Some(match_end));
47                return None;
48            }
49
50            let count = usize::from(self.components.len()) + 1;
51            ligate_input(
52                ctx,
53                count,
54                &match_positions,
55                match_end,
56                total_component_count,
57                self.glyph,
58            );
59            return Some(());
60        }
61    }
62}