swash/shape/
aat.rs

1use super::buffer::*;
2use super::internal::aat::*;
3
4pub fn apply_morx(
5    data: &[u8],
6    morx: u32,
7    buffer: &mut Buffer,
8    selectors: &[(u16, u16)],
9) -> Option<()> {
10    use morx::*;
11    let max_ops = buffer.glyphs.len() * 16;
12    for chain in chains(data, morx) {
13        let mut ops = 0;
14        let mut flags = chain.default_flags();
15        if !selectors.is_empty() {
16            for feature in chain.features() {
17                let key = (feature.selector, feature.setting_selector);
18                if selectors.binary_search(&key).is_ok() {
19                    flags = flags & feature.disable_flags | feature.enable_flags;
20                }
21            }
22        }
23        for (_i, subtable) in chain.subtables().enumerate() {
24            if subtable.flags() & flags == 0 {
25                // if TRACE {
26                //     println!("    <SKIP chain subtable {}>", i);
27                // }
28                continue;
29            } else {
30                // if TRACE {
31                //     println!("    <chain subtable {} order: {:?}>", i, subtable.order());
32                // }
33            }
34            let reverse = subtable.should_reverse(buffer.is_rtl);
35            buffer.ensure_order(reverse);
36            let kind = match subtable.kind() {
37                Some(kind) => kind,
38                _ => continue,
39            };
40            match kind {
41                SubtableKind::Rearrangement(t) => {
42                    //println!(".. rearrangement");
43                    let mut i = 0;
44                    let mut state = RearrangementState::new();
45                    while i < buffer.glyphs.len() && ops < max_ops {
46                        let g = buffer.glyphs[i].id;
47                        match t.next(&mut state, i, g, false, |r| {
48                            // if TRACE {
49                            //     println!("Rearrange!");
50                            // }
51                            r.apply(&mut buffer.glyphs);
52                            Some(())
53                        }) {
54                            Some(advance) => i += advance,
55                            None => break,
56                        }
57                        ops += 1;
58                    }
59                    // Apply END_OF_TEXT state
60                    t.next(&mut state, i, 0, true, |r| {
61                        r.apply(&mut buffer.glyphs);
62                        Some(())
63                    });
64                }
65                SubtableKind::Contextual(t) => {
66                    //println!(".. contextual");
67                    let mut state = ContextualState::new();
68                    for i in 0..buffer.glyphs.len() {
69                        let g = buffer.glyphs[i].id;
70                        t.next(&mut state, i, g, false, |i, g| {
71                            buffer.substitute(i, g);
72                            Some(())
73                        });
74                    }
75                    // Apply END_OF_TEXT state
76                    if let Some(last_id) = buffer.glyphs.last().map(|g| g.id) {
77                        t.next(
78                            &mut state,
79                            buffer.glyphs.len() - 1,
80                            last_id,
81                            true,
82                            |i, g| {
83                                buffer.substitute(i, g);
84                                Some(())
85                            },
86                        );
87                    }
88                }
89                SubtableKind::NonContextual(t) => {
90                    //println!(".. non-contextual");
91                    for (_i, g) in buffer.glyphs.iter_mut().enumerate() {
92                        if let Some(s) = t.substitute(g.id) {
93                            // if TRACE {
94                            //     println!("NonContextual[{}] {} -> {}", i, g.id, s);
95                            // }
96                            g.id = s;
97                        }
98                    }
99                }
100                SubtableKind::Ligature(t) => {
101                    //println!(".. ligature");
102                    let mut i = 0;
103                    let mut state = LigatureState::new();
104                    while i < buffer.glyphs.len() && ops < max_ops {
105                        let g = buffer.glyphs[i].id;
106                        let f = |i, g, comps: &[usize]| {
107                            buffer.substitute_ligature(i, g, comps);
108                            Some(())
109                        };
110                        if t.next(&mut state, i, g, false, f).is_none() {
111                            break;
112                        }
113                        i += 1;
114                        ops += 1;
115                    }
116                    // Apply END_OF_TEXT state
117                    t.next(
118                        &mut state,
119                        buffer.glyphs.len().saturating_sub(1),
120                        0,
121                        true,
122                        |i, g, comps| {
123                            buffer.substitute_ligature(i, g, comps);
124                            Some(())
125                        },
126                    );
127                }
128                SubtableKind::Insertion(t) => {
129                    //println!(".. insertion");
130                    let mut i = 0;
131                    let mut state = InsertionState::new();
132                    while i < buffer.glyphs.len() && ops < max_ops {
133                        let g = buffer.glyphs[i].id;
134                        match t.next(&mut state, i, g, false, |i, array| {
135                            // if TRACE {
136                            //     let rep = array.iter().collect::<Vec<_>>();
137                            //     println!("Insert[{}] {:?}", i, &rep);
138                            // }
139                            buffer.multiply(i, array.len());
140                            let start = i;
141                            let end = start + array.len();
142                            for (g, s) in buffer.glyphs[start..end].iter_mut().zip(array.iter()) {
143                                g.id = s;
144                                g.flags = 0;
145                            }
146                            Some(())
147                        }) {
148                            Some(advance) => i += advance,
149                            None => break,
150                        }
151                        ops += 1;
152                    }
153                    // Apply END_OF_TEXT state
154                    t.next(
155                        &mut state,
156                        buffer.glyphs.len().saturating_sub(1),
157                        0,
158                        true,
159                        |i, array| {
160                            buffer.multiply(i, array.len());
161                            let start = i;
162                            let end = start + array.len();
163                            for (g, s) in buffer.glyphs[start..end].iter_mut().zip(array.iter()) {
164                                g.id = s;
165                                g.flags = 0;
166                            }
167                            Some(())
168                        },
169                    );
170                }
171            }
172        }
173    }
174    buffer.ensure_order(false);
175    Some(())
176}
177
178pub fn apply_kerx(
179    data: &[u8],
180    kerx: u32,
181    ankr: u32,
182    buffer: &mut Buffer,
183    disable_kern: bool,
184) -> Option<()> {
185    use kerx::*;
186    for (_i, subtable) in subtables(data, kerx, ankr).enumerate() {
187        // if TRACE {
188        //     println!("    <kerx subtable {}>", i);
189        // }
190        let reverse = subtable.should_reverse(buffer.is_rtl);
191        buffer.ensure_order(reverse);
192        let kind = match subtable.kind() {
193            Some(kind) => kind,
194            _ => continue,
195        };
196        if subtable.is_vertical() || subtable.is_cross_stream() {
197            continue;
198        }
199        match kind {
200            SubtableKind::Format0(t) => {
201                if disable_kern {
202                    continue;
203                }
204                let len = buffer.len();
205                let mut left_index = if let Some((index, _)) = buffer
206                    .glyphs
207                    .iter()
208                    .enumerate()
209                    .find(|(_, g)| g.joining_type != 6)
210                {
211                    index
212                } else {
213                    continue;
214                };
215                let mut left = buffer.glyphs[left_index].id;
216                for i in left_index + 1..len {
217                    if buffer.glyphs[i].joining_type == 6 {
218                        continue;
219                    }
220                    let right = buffer.glyphs[i].id;
221                    if let Some(kerning) = t.get(left, right) {
222                        if kerning != 0 {
223                            // if TRACE {
224                            //     println!("KERN [{} & {}] {}", left_index, i, kerning);
225                            // }
226                            buffer.positions[left_index].advance += kerning as f32;
227                        }
228                    }
229                    left_index = i;
230                    left = right;
231                }
232            }
233            SubtableKind::Format1(t) => {
234                if disable_kern {
235                    continue;
236                }
237                let mut i = 0;
238                let len = buffer.glyphs.len();
239                let mut state = ContextualState::new();
240                while i < len {
241                    match t.next(&mut state, i, buffer.glyphs[i].id, |i, kerning| {
242                        buffer.positions[i].advance += kerning as f32;
243                        Some(())
244                    }) {
245                        Some(advance) => i += advance,
246                        None => break,
247                    }
248                }
249            }
250            SubtableKind::Format2(t) => {
251                if disable_kern {
252                    continue;
253                }
254                //println!("142/116 = {:?}", t.get(142, 116));
255                let len = buffer.len();
256                let mut left_index = if let Some((index, _)) = buffer
257                    .glyphs
258                    .iter()
259                    .enumerate()
260                    .find(|(_, g)| g.joining_type != 6)
261                {
262                    index
263                } else {
264                    continue;
265                };
266                let mut left = buffer.glyphs[left_index].id;
267                for i in left_index + 1..len {
268                    if buffer.glyphs[i].joining_type == 6 {
269                        continue;
270                    }
271                    let right = buffer.glyphs[i].id;
272                    if let Some(kerning) = t.get(left, right) {
273                        if kerning != 0 {
274                            // if TRACE {
275                            //     println!("KERN [{} & {}] {}", left_index, i, kerning);
276                            // }
277                            buffer.positions[left_index].advance += kerning as f32;
278                        }
279                    }
280                    left_index = i;
281                    left = right;
282                }
283            }
284            SubtableKind::Format4(t) => {
285                let mut i = 0;
286                let len = buffer.glyphs.len();
287                let mut state = Format4State::new();
288                while i < len {
289                    match t.next(&mut state, i, buffer.glyphs[i].id, |i, base, x, y| {
290                        buffer.position_mark(i, base, x, y);
291                        Some(())
292                    }) {
293                        Some(advance) => i += advance,
294                        None => break,
295                    }
296                }
297            }
298        }
299    }
300    buffer.ensure_order(false);
301    Some(())
302}
303
304pub fn apply_kern(data: &[u8], kern: u32, buffer: &mut Buffer) -> Option<()> {
305    use kern::*;
306    for (_i, subtable) in subtables(data, kern).enumerate() {
307        let kind = match subtable.kind() {
308            Some(kind) => kind,
309            _ => continue,
310        };
311        if !subtable.is_horizontal() {
312            continue;
313        }
314        buffer.ensure_order(buffer.is_rtl);
315        let cross_stream = subtable.cross_stream();
316        match kind {
317            SubtableKind::Format0(t) => {
318                buffer.ensure_order(false);
319                let len = buffer.len();
320                let mut left_index = if let Some((index, _)) = buffer
321                    .glyphs
322                    .iter()
323                    .enumerate()
324                    .find(|(_, g)| g.joining_type != 6)
325                {
326                    index
327                } else {
328                    continue;
329                };
330                let mut left = buffer.glyphs[left_index].id;
331                for i in left_index + 1..len {
332                    if buffer.glyphs[i].joining_type == 6 {
333                        continue;
334                    }
335                    let right = buffer.glyphs[i].id;
336                    if let Some(kerning) = t.get(left, right) {
337                        if kerning != 0 {
338                            // if TRACE {
339                            //     println!("KERN [{} & {}] {}", left_index, i, kerning);
340                            // }
341                            buffer.positions[left_index].advance += kerning as f32;
342                        }
343                    }
344                    left_index = i;
345                    left = right;
346                }
347            }
348            SubtableKind::Format1(t) => {
349                let mut i = 0;
350                let len = buffer.glyphs.len();
351                let mut state = Format1State::new();
352                while i < len {
353                    match t.next(&mut state, i, buffer.glyphs[i].id, |i, kerning| {
354                        let g = &buffer.glyphs[i];
355                        if g.joining_type == 6 {
356                            if cross_stream {
357                                let pos = &mut buffer.positions[i];
358                                if pos.y == 0. {
359                                    pos.y = kerning as f32;
360                                }
361                            } else if let Some(base) = find_base(buffer, buffer.is_rtl, i) {
362                                let diff = if base >= i { base - i } else { i - base };
363                                if diff < 255 {
364                                    let pos = &mut buffer.positions[i];
365                                    if pos.base == 0 {
366                                        pos.flags |= MARK_ATTACH;
367                                        pos.base = diff as u8;
368                                        pos.x = kerning as f32;
369                                        buffer.has_marks = true;
370                                    }
371                                }
372                            }
373                        }
374                        Some(())
375                    }) {
376                        Some(advance) => i += advance,
377                        None => break,
378                    }
379                }
380            }
381        }
382    }
383    buffer.ensure_order(false);
384    Some(())
385}
386
387fn find_base(buffer: &Buffer, reverse: bool, index: usize) -> Option<usize> {
388    use crate::text::cluster::ShapeClass;
389    let cluster = buffer.glyphs[index].cluster;
390    if reverse {
391        for i in index + 1..buffer.len() {
392            let g = &buffer.glyphs[i];
393            if g.cluster != cluster {
394                return None;
395            }
396            if g.char_class == ShapeClass::Base {
397                return Some(i);
398            }
399        }
400    } else if index > 0 {
401        for i in (0..index).rev() {
402            let g = &buffer.glyphs[i];
403            if g.cluster != cluster {
404                return None;
405            }
406            if g.char_class == ShapeClass::Base {
407                return Some(i);
408            }
409        }
410    }
411    None
412}