rustybuzz/hb/ot/layout/GPOS/
mark_base_pos.rs1use crate::hb::buffer::hb_buffer_t;
2use crate::hb::ot::layout::GPOS::mark_array::MarkArrayExt;
3use crate::hb::ot_layout::{
4 _hb_glyph_info_get_lig_comp, _hb_glyph_info_get_lig_id, _hb_glyph_info_is_mark,
5 _hb_glyph_info_multiplied,
6};
7use crate::hb::ot_layout_common::lookup_flags;
8use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
9use crate::hb::ot_layout_gsubgpos::{match_t, skipping_iterator_t, Apply};
10use ttf_parser::gpos::MarkToBaseAdjustment;
11
12impl Apply for MarkToBaseAdjustment<'_> {
13 fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
14 let buffer = &ctx.buffer;
15 let mark_glyph = ctx.buffer.cur(0).as_glyph();
16 let mark_index = self.mark_coverage.get(mark_glyph)?;
17
18 if ctx.last_base_until > buffer.idx as u32 {
21 ctx.last_base_until = 0;
22 ctx.last_base = -1;
23 }
24
25 let mut iter = skipping_iterator_t::new(ctx, 0, false);
28 iter.set_lookup_props(u32::from(lookup_flags::IGNORE_MARKS));
29
30 let mut j = buffer.idx;
31 while j > ctx.last_base_until as usize {
32 let mut _match = iter.match_(&buffer.info[j - 1]);
33 if _match == match_t::MATCH {
34 if !accept(buffer, j - 1)
36 && !self.base_coverage.contains(buffer.info[j - 1].as_glyph())
37 {
38 _match = match_t::SKIP;
39 }
40 }
41
42 if _match == match_t::MATCH {
43 ctx.last_base = j as i32 - 1;
44 break;
45 }
46
47 j -= 1;
48 }
49 ctx.last_base_until = buffer.idx as u32;
50
51 if ctx.last_base == -1 {
52 ctx.buffer
53 .unsafe_to_concat_from_outbuffer(Some(0), Some(buffer.idx + 1));
54 return None;
55 }
56
57 let idx = ctx.last_base as u32;
58
59 let info = &buffer.info;
60
61 let base_glyph = info[idx as usize].as_glyph();
63 let Some(base_index) = self.base_coverage.get(base_glyph) else {
64 ctx.buffer
65 .unsafe_to_concat_from_outbuffer(Some(idx as usize), Some(buffer.idx + 1));
66 return None;
67 };
68
69 self.marks
70 .apply(ctx, self.anchors, mark_index, base_index, idx as usize)
71 }
72}
73
74fn accept(buffer: &hb_buffer_t, idx: usize) -> bool {
75 !_hb_glyph_info_multiplied(&buffer.info[idx])
81 || 0 == _hb_glyph_info_get_lig_comp(&buffer.info[idx])
82 || (idx == 0
83 || _hb_glyph_info_is_mark(&buffer.info[idx - 1])
84 || !_hb_glyph_info_multiplied(&buffer.info[idx - 1])
85 || _hb_glyph_info_get_lig_id(&buffer.info[idx])
86 != _hb_glyph_info_get_lig_id(&buffer.info[idx - 1])
87 || _hb_glyph_info_get_lig_comp(&buffer.info[idx])
88 != _hb_glyph_info_get_lig_comp(&buffer.info[idx - 1]) + 1)
89}