rustybuzz/hb/ot/layout/GPOS/
mark_mark_pos.rs1use crate::hb::ot::layout::GPOS::mark_array::MarkArrayExt;
2use crate::hb::ot_layout::{
3 _hb_glyph_info_get_lig_comp, _hb_glyph_info_get_lig_id, _hb_glyph_info_is_mark,
4};
5use crate::hb::ot_layout_common::lookup_flags;
6use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
7use crate::hb::ot_layout_gsubgpos::{skipping_iterator_t, Apply};
8use ttf_parser::gpos::MarkToMarkAdjustment;
9
10impl Apply for MarkToMarkAdjustment<'_> {
11 fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
12 let buffer = &ctx.buffer;
13 let mark1_glyph = ctx.buffer.cur(0).as_glyph();
14 let mark1_index = self.mark1_coverage.get(mark1_glyph)?;
15
16 let mut iter = skipping_iterator_t::new(ctx, buffer.idx, false);
18 iter.set_lookup_props(ctx.lookup_props & !u32::from(lookup_flags::IGNORE_FLAGS));
19
20 let mut unsafe_from = 0;
21 if !iter.prev(Some(&mut unsafe_from)) {
22 ctx.buffer
23 .unsafe_to_concat_from_outbuffer(Some(unsafe_from), Some(ctx.buffer.idx + 1));
24 return None;
25 }
26
27 let iter_idx = iter.index();
28 if !_hb_glyph_info_is_mark(&buffer.info[iter_idx]) {
29 ctx.buffer
30 .unsafe_to_concat_from_outbuffer(Some(iter_idx), Some(buffer.idx + 1));
31 return None;
32 }
33
34 let id1 = _hb_glyph_info_get_lig_id(buffer.cur(0));
35 let id2 = _hb_glyph_info_get_lig_id(&buffer.info[iter_idx]);
36 let comp1 = _hb_glyph_info_get_lig_comp(buffer.cur(0));
37 let comp2 = _hb_glyph_info_get_lig_comp(&buffer.info[iter_idx]);
38
39 let matches = if id1 == id2 {
40 id1 == 0 || comp1 == comp2
43 } else {
44 (id1 > 0 && comp1 == 0) || (id2 > 0 && comp2 == 0)
47 };
48
49 if !matches {
50 ctx.buffer
51 .unsafe_to_concat_from_outbuffer(Some(iter_idx), Some(buffer.idx + 1));
52 return None;
53 }
54
55 let mark2_glyph = buffer.info[iter_idx].as_glyph();
56 let mark2_index = self.mark2_coverage.get(mark2_glyph)?;
57
58 self.marks
59 .apply(ctx, self.mark2_matrix, mark1_index, mark2_index, iter_idx)
60 }
61}