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