harfrust/hb/ot/gsub/
reverse_chain.rs1use 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 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 return Some(());
75 }
76 }
77
78 ctx.buffer
79 .unsafe_to_concat_from_outbuffer(Some(start_index), Some(end_index));
80 None
81 }
82}