1 | use super::buffer::{hb_buffer_t, HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE}; |
2 | use super::{hb_font_t, hb_glyph_info_t}; |
3 | use crate::BufferFlags; |
4 | |
5 | pub 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 | ) -> bool { |
13 | if buffer |
14 | .flags |
15 | .contains(BufferFlags::DO_NOT_INSERT_DOTTED_CIRCLE) |
16 | { |
17 | return false; |
18 | } |
19 | |
20 | if (buffer.scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE) == 0 { |
21 | return false; |
22 | } |
23 | |
24 | let dottedcircle_glyph = match face.get_nominal_glyph(0x25CC) { |
25 | Some(g) => g.0 as u32, |
26 | None => return false, |
27 | }; |
28 | |
29 | let mut dottedcircle = hb_glyph_info_t { |
30 | glyph_id: 0x25CC, |
31 | ..hb_glyph_info_t::default() |
32 | }; |
33 | dottedcircle.set_ot_shaper_var_u8_category(dottedcircle_category); |
34 | if let Some(dottedcircle_position) = dottedcircle_position { |
35 | dottedcircle.set_ot_shaper_var_u8_auxiliary(dottedcircle_position); |
36 | } |
37 | dottedcircle.glyph_id = dottedcircle_glyph; |
38 | |
39 | buffer.clear_output(); |
40 | |
41 | buffer.idx = 0; |
42 | let mut last_syllable = 0; |
43 | while buffer.idx < buffer.len { |
44 | let syllable = buffer.cur(0).syllable(); |
45 | if last_syllable != syllable && (syllable & 0x0F) == broken_syllable_type { |
46 | last_syllable = syllable; |
47 | |
48 | let mut ginfo = dottedcircle; |
49 | ginfo.cluster = buffer.cur(0).cluster; |
50 | ginfo.mask = buffer.cur(0).mask; |
51 | ginfo.set_syllable(buffer.cur(0).syllable()); |
52 | |
53 | // Insert dottedcircle after possible Repha. |
54 | if let Some(repha_category) = repha_category { |
55 | while buffer.idx < buffer.len |
56 | && last_syllable == buffer.cur(0).syllable() |
57 | && buffer.cur(0).ot_shaper_var_u8_category() == repha_category |
58 | { |
59 | buffer.next_glyph(); |
60 | } |
61 | } |
62 | |
63 | buffer.output_info(ginfo); |
64 | } else { |
65 | buffer.next_glyph(); |
66 | } |
67 | } |
68 | |
69 | buffer.sync(); |
70 | |
71 | true |
72 | } |
73 | |