1use crate::hb::buffer::GlyphPropsFlags;
2use crate::hb::ot_layout::{
3 _hb_glyph_info_get_lig_id, _hb_glyph_info_is_ligature,
4 _hb_glyph_info_set_lig_props_for_component,
5};
6use crate::hb::ot_layout_gsubgpos::Apply;
7use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
8use ttf_parser::gsub::Sequence;
9
10impl Apply for Sequence<'_> {
11 fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
12 match self.substitutes.len() {
13 // Spec disallows this, but Uniscribe allows it.
14 // https://github.com/harfbuzz/harfbuzz/issues/253
15 0 => ctx.buffer.delete_glyph(),
16
17 // Special-case to make it in-place and not consider this
18 // as a "multiplied" substitution.
19 1 => ctx.replace_glyph(self.substitutes.get(0)?),
20
21 _ => {
22 let class = if _hb_glyph_info_is_ligature(ctx.buffer.cur(0)) {
23 GlyphPropsFlags::BASE_GLYPH
24 } else {
25 GlyphPropsFlags::empty()
26 };
27 let lig_id = _hb_glyph_info_get_lig_id(ctx.buffer.cur(0));
28
29 for (i, subst) in self.substitutes.into_iter().enumerate() {
30 // If is attached to a ligature, don't disturb that.
31 // https://github.com/harfbuzz/harfbuzz/issues/3069
32 if lig_id == 0 {
33 // Index is truncated to 4 bits anway, so we can safely cast to u8.
34 _hb_glyph_info_set_lig_props_for_component(ctx.buffer.cur_mut(0), i as u8);
35 }
36 ctx.output_glyph_for_component(subst, class);
37 }
38
39 ctx.buffer.skip_glyph();
40 }
41 }
42 Some(())
43 }
44}
45