harfrust/hb/ot/gsub/
alternate.rs1use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
2use crate::hb::ot_layout_gsubgpos::{Apply, WouldApply, WouldApplyContext};
3use read_fonts::tables::gsub::{AlternateSet, AlternateSubstFormat1};
4
5impl Apply for AlternateSet<'_> {
6 fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
7 let alternates = self.alternate_glyph_ids();
8 let len = alternates.len() as u16;
9 if len == 0 {
10 return None;
11 }
12
13 let glyph_mask = ctx.buffer.cur(0).mask;
14
15 let shift = ctx.lookup_mask().trailing_zeros();
17 let mut alt_index = (ctx.lookup_mask() & glyph_mask) >> shift;
18
19 if alt_index == crate::hb::ot_map::hb_ot_map_t::MAX_VALUE && ctx.random {
21 ctx.buffer.unsafe_to_break(Some(0), Some(ctx.buffer.len));
24 alt_index = ctx.random_number() % u32::from(len) + 1;
25 }
26
27 let idx = u16::try_from(alt_index).ok()?.checked_sub(1)?;
28 ctx.replace_glyph(alternates.get(idx as usize)?.get().into());
29
30 Some(())
31 }
32}
33
34impl WouldApply for AlternateSubstFormat1<'_> {
35 fn would_apply(&self, ctx: &WouldApplyContext) -> bool {
36 ctx.glyphs.len() == 1
37 && self
38 .coverage()
39 .is_ok_and(|cov| cov.get(ctx.glyphs[0]).is_some())
40 }
41}
42
43impl Apply for AlternateSubstFormat1<'_> {
44 fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
45 let glyph = ctx.buffer.cur(0).as_glyph();
46 let index = self.coverage().ok()?.get(glyph)?;
47 let set = self.alternate_sets().get(index as usize).ok()?;
48 set.apply(ctx)
49 }
50}