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 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}