rustybuzz/hb/ot/layout/GPOS/
pair_pos.rs1use crate::hb::ot_layout_gpos_table::ValueRecordExt;
2use crate::hb::ot_layout_gsubgpos::OT::hb_ot_apply_context_t;
3use crate::hb::ot_layout_gsubgpos::{skipping_iterator_t, Apply};
4use ttf_parser::gpos::{PairAdjustment, ValueRecord};
5
6impl Apply for PairAdjustment<'_> {
7 fn apply(&self, ctx: &mut hb_ot_apply_context_t) -> Option<()> {
8 let first_glyph = ctx.buffer.cur(0).as_glyph();
9 let first_glyph_coverage_index = self.coverage().get(first_glyph)?;
10
11 let mut iter = skipping_iterator_t::new(ctx, ctx.buffer.idx, false);
12
13 let mut unsafe_to = 0;
14 if !iter.next(Some(&mut unsafe_to)) {
15 ctx.buffer
16 .unsafe_to_concat(Some(ctx.buffer.idx), Some(unsafe_to));
17 return None;
18 }
19
20 let second_glyph_index = iter.index();
21 let second_glyph = ctx.buffer.info[second_glyph_index].as_glyph();
22
23 let finish = |ctx: &mut hb_ot_apply_context_t, iter_index: &mut usize, has_record2| {
24 if has_record2 {
25 *iter_index += 1;
26 ctx.buffer
29 .unsafe_to_break(Some(ctx.buffer.idx), Some(*iter_index + 1));
30 }
31
32 ctx.buffer.idx = *iter_index;
33
34 Some(())
35 };
36
37 let boring = |ctx: &mut hb_ot_apply_context_t, iter_index: &mut usize, has_record2| {
38 ctx.buffer
39 .unsafe_to_concat(Some(ctx.buffer.idx), Some(second_glyph_index + 1));
40 finish(ctx, iter_index, has_record2)
41 };
42
43 let success =
44 |ctx: &mut hb_ot_apply_context_t, iter_index: &mut usize, flag1, flag2, has_record2| {
45 if flag1 || flag2 {
46 ctx.buffer
47 .unsafe_to_break(Some(ctx.buffer.idx), Some(second_glyph_index + 1));
48 finish(ctx, iter_index, has_record2)
49 } else {
50 boring(ctx, iter_index, has_record2)
51 }
52 };
53
54 let bail = |ctx: &mut hb_ot_apply_context_t,
55 iter_index: &mut usize,
56 records: (ValueRecord, ValueRecord)| {
57 let has_record1 = !records.0.is_empty();
58 let has_record2 = !records.1.is_empty();
59
60 let flag1 = has_record1 && records.0.apply(ctx, ctx.buffer.idx);
61 let flag2 = has_record2 && records.1.apply(ctx, second_glyph_index);
62
63 success(ctx, iter_index, flag1, flag2, has_record2)
64 };
65
66 let records = match self {
67 Self::Format1 { sets, .. } => {
68 sets.get(first_glyph_coverage_index)?.get(second_glyph)?
69 }
70 Self::Format2 {
71 classes, matrix, ..
72 } => {
73 let classes = (classes.0.get(first_glyph), classes.1.get(second_glyph));
74
75 let records = match matrix.get(classes) {
76 Some(v) => v,
77 None => {
78 ctx.buffer
79 .unsafe_to_concat(Some(ctx.buffer.idx), Some(iter.index() + 1));
80 return None;
81 }
82 };
83
84 return bail(ctx, &mut iter.buf_idx, records);
85 }
86 };
87
88 bail(ctx, &mut iter.buf_idx, records)
89 }
90}