rustybuzz/hb/
ot_shape_complex_syllabic.rs

1use super::buffer::hb_buffer_t;
2use super::{hb_font_t, hb_glyph_info_t};
3use crate::BufferFlags;
4
5pub fn insert_dotted_circles(
6    face: &hb_font_t,
7    buffer: &mut hb_buffer_t,
8    broken_syllable_type: u8,
9    dottedcircle_category: u8,
10    repha_category: Option<u8>,
11    dottedcircle_position: Option<u8>,
12) {
13    if buffer
14        .flags
15        .contains(BufferFlags::DO_NOT_INSERT_DOTTED_CIRCLE)
16    {
17        return;
18    }
19
20    // Note: This loop is extra overhead, but should not be measurable.
21    // TODO Use a buffer scratch flag to remove the loop.
22    let has_broken_syllables = buffer
23        .info_slice()
24        .iter()
25        .any(|info| info.syllable() & 0x0F == broken_syllable_type);
26
27    if !has_broken_syllables {
28        return;
29    }
30
31    let dottedcircle_glyph = match face.get_nominal_glyph(0x25CC) {
32        Some(g) => g.0 as u32,
33        None => return,
34    };
35
36    let mut dottedcircle = hb_glyph_info_t {
37        glyph_id: 0x25CC,
38        ..hb_glyph_info_t::default()
39    };
40    dottedcircle.set_complex_var_u8_category(dottedcircle_category);
41    if let Some(dottedcircle_position) = dottedcircle_position {
42        dottedcircle.set_complex_var_u8_auxiliary(dottedcircle_position);
43    }
44    dottedcircle.glyph_id = dottedcircle_glyph;
45
46    buffer.clear_output();
47
48    buffer.idx = 0;
49    let mut last_syllable = 0;
50    while buffer.idx < buffer.len {
51        let syllable = buffer.cur(0).syllable();
52        if last_syllable != syllable && (syllable & 0x0F) == broken_syllable_type {
53            last_syllable = syllable;
54
55            let mut ginfo = dottedcircle;
56            ginfo.cluster = buffer.cur(0).cluster;
57            ginfo.mask = buffer.cur(0).mask;
58            ginfo.set_syllable(buffer.cur(0).syllable());
59
60            // Insert dottedcircle after possible Repha.
61            if let Some(repha_category) = repha_category {
62                while buffer.idx < buffer.len
63                    && last_syllable == buffer.cur(0).syllable()
64                    && buffer.cur(0).complex_var_u8_category() == repha_category
65                {
66                    buffer.next_glyph();
67                }
68            }
69
70            buffer.output_info(ginfo);
71        } else {
72            buffer.next_glyph();
73        }
74    }
75
76    buffer.sync();
77}