1 | use crate::hb::ot::layout::GPOS::mark_array::MarkArrayExt; |
2 | use crate::hb::ot_layout::{ |
3 | _hb_glyph_info_get_lig_comp, _hb_glyph_info_get_lig_id, _hb_glyph_info_is_mark, |
4 | }; |
5 | use crate::hb::ot_layout_common::lookup_flags; |
6 | use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t; |
7 | use crate::hb::ot_layout_gsubgpos::{skipping_iterator_t, Apply}; |
8 | use ttf_parser::gpos::MarkToMarkAdjustment; |
9 | |
10 | impl 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 | // Now we search backwards for a suitable mark glyph until a non-mark glyph |
17 | 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 | // Marks belonging to the same base |
41 | // or marks belonging to the same ligature component. |
42 | id1 == 0 || comp1 == comp2 |
43 | } else { |
44 | // If ligature ids don't match, it may be the case that one of the marks |
45 | // itself is a ligature. In which case match. |
46 | (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 | } |
62 | |