makepad_rustybuzz/
buffer.rs

1use alloc::{string::String, vec::Vec};
2use core::convert::TryFrom;
3
4use crate::ttf_parser::GlyphId;
5
6use crate::{script, Direction, Face, Language, Mask, Script};
7use crate::unicode::{CharExt, GeneralCategory, GeneralCategoryExt, Space};
8
9const CONTEXT_LENGTH: usize = 5;
10
11
12pub mod glyph_flag {
13    /// Indicates that if input text is broken at the
14    /// beginning of the cluster this glyph is part of,
15    /// then both sides need to be re-shaped, as the
16    /// result might be different.  On the flip side,
17    /// it means that when this flag is not present,
18    /// then it's safe to break the glyph-run at the
19    /// beginning of this cluster, and the two sides
20    /// represent the exact same result one would get
21    /// if breaking input text at the beginning of
22    /// this cluster and shaping the two sides
23    /// separately.  This can be used to optimize
24    /// paragraph layout, by avoiding re-shaping
25    /// of each line after line-breaking, or limiting
26    /// the reshaping to a small piece around the
27    /// breaking point only.
28    pub const UNSAFE_TO_BREAK: u32 = 0x00000001;
29
30    /// All the currently defined flags.
31    pub const DEFINED: u32 = 0x00000001; // OR of all defined flags
32}
33
34
35/// Holds the positions of the glyph in both horizontal and vertical directions.
36///
37/// All positions are relative to the current point.
38#[repr(C)]
39#[derive(Clone, Copy, Default, Debug)]
40pub struct GlyphPosition {
41    /// How much the line advances after drawing this glyph when setting text in
42    /// horizontal direction.
43    pub x_advance: i32,
44    /// How much the line advances after drawing this glyph when setting text in
45    /// vertical direction.
46    pub y_advance: i32,
47    /// How much the glyph moves on the X-axis before drawing it, this should
48    /// not affect how much the line advances.
49    pub x_offset: i32,
50    /// How much the glyph moves on the Y-axis before drawing it, this should
51    /// not affect how much the line advances.
52    pub y_offset: i32,
53    var: u32,
54}
55
56unsafe impl bytemuck::Zeroable for GlyphPosition {}
57unsafe impl bytemuck::Pod for GlyphPosition {}
58
59impl GlyphPosition {
60    #[inline]
61    pub(crate) fn attach_chain(&self) -> i16 {
62        // glyph to which this attaches to, relative to current glyphs;
63        // negative for going back, positive for forward.
64        let v: &[i16; 2] = bytemuck::cast_ref(&self.var);
65        v[0]
66    }
67
68    #[inline]
69    pub(crate) fn set_attach_chain(&mut self, n: i16) {
70        let v: &mut [i16; 2] = bytemuck::cast_mut(&mut self.var);
71        v[0] = n;
72    }
73
74    #[inline]
75    pub(crate) fn attach_type(&self) -> u8 {
76        // attachment type
77        // Note! if attach_chain() is zero, the value of attach_type() is irrelevant.
78        let v: &[u8; 4] = bytemuck::cast_ref(&self.var);
79        v[2]
80    }
81
82    #[inline]
83    pub(crate) fn set_attach_type(&mut self, n: u8) {
84        let v: &mut [u8; 4] = bytemuck::cast_mut(&mut self.var);
85        v[2] = n;
86    }
87}
88
89
90/// A glyph info.
91#[repr(C)]
92#[derive(Clone, Copy, Default, Debug)]
93pub struct GlyphInfo {
94    // NOTE: Stores a Unicode codepoint before shaping and a glyph ID after.
95    //       Just like harfbuzz, we are using the same variable for two purposes.
96    //       Occupies u32 as a codepoint and u16 as a glyph id.
97    /// A selected glyph.
98    ///
99    /// Guarantee to be <= `u16::MAX`.
100    pub glyph_id: u32,
101    pub(crate) mask: Mask,
102    /// An index to the start of the grapheme cluster in the original string.
103    ///
104    /// [Read more on clusters](https://harfbuzz.github.io/clusters.html).
105    pub cluster: u32,
106    pub(crate) var1: u32,
107    pub(crate) var2: u32,
108}
109
110unsafe impl bytemuck::Zeroable for GlyphInfo {}
111unsafe impl bytemuck::Pod for GlyphInfo {}
112
113const IS_LIG_BASE: u8 = 0x10;
114
115impl GlyphInfo {
116    /// Indicates that if input text is broken at the beginning of the cluster this glyph
117    /// is part of, then both sides need to be re-shaped, as the result might be different.
118    ///
119    /// On the flip side, it means that when this flag is not present,
120    /// then it's safe to break the glyph-run at the beginning of this cluster,
121    /// and the two sides represent the exact same result one would get if breaking input text
122    /// at the beginning of this cluster and shaping the two sides separately.
123    /// This can be used to optimize paragraph layout, by avoiding re-shaping of each line
124    /// after line-breaking, or limiting the reshaping to a small piece around
125    /// the breaking point only.
126    pub fn unsafe_to_break(&self) -> bool {
127        self.mask & glyph_flag::UNSAFE_TO_BREAK != 0
128    }
129
130    #[inline]
131    pub(crate) fn as_char(&self) -> char {
132        char::try_from(self.glyph_id).unwrap()
133    }
134
135    #[inline]
136    pub(crate) fn as_glyph(&self) -> GlyphId {
137        debug_assert!(self.glyph_id <= u32::from(u16::MAX));
138        GlyphId(self.glyph_id as u16)
139    }
140
141    // Var allocation: unicode_props
142    // Used during the entire shaping process to store unicode properties
143
144    #[inline]
145    fn unicode_props(&self) -> u16 {
146        let v: &[u16; 2] = bytemuck::cast_ref(&self.var2);
147        v[0]
148    }
149
150    #[inline]
151    fn set_unicode_props(&mut self, n: u16) {
152        let v: &mut [u16; 2] = bytemuck::cast_mut(&mut self.var2);
153        v[0] = n;
154    }
155
156    pub(crate) fn init_unicode_props(&mut self, scratch_flags: &mut BufferScratchFlags) {
157        let u = self.as_char();
158        let gc = u.general_category();
159        let mut props = gc.to_rb() as u16;
160
161        if u as u32 >= 0x80 {
162            *scratch_flags |= BufferScratchFlags::HAS_NON_ASCII;
163
164            if u.is_default_ignorable() {
165                props |= UnicodeProps::IGNORABLE.bits;
166                *scratch_flags |= BufferScratchFlags::HAS_DEFAULT_IGNORABLES;
167
168                match u as u32 {
169                    0x200C => props |= UnicodeProps::CF_ZWNJ.bits,
170                    0x200D => props |= UnicodeProps::CF_ZWJ.bits,
171
172                    // Mongolian Free Variation Selectors need to be remembered
173                    // because although we need to hide them like default-ignorables,
174                    // they need to non-ignorable during shaping.  This is similar to
175                    // what we do for joiners in Indic-like shapers, but since the
176                    // FVSes are GC=Mn, we have use a separate bit to remember them.
177                    // Fixes:
178                    // https://github.com/harfbuzz/harfbuzz/issues/234
179                    0x180B..=0x180D => props |= UnicodeProps::HIDDEN.bits,
180
181                    // TAG characters need similar treatment. Fixes:
182                    // https://github.com/harfbuzz/harfbuzz/issues/463
183                    0xE0020..=0xE007F => props |= UnicodeProps::HIDDEN.bits,
184
185                    // COMBINING GRAPHEME JOINER should not be skipped; at least some times.
186                    // https://github.com/harfbuzz/harfbuzz/issues/554
187                    0x034F => {
188                        props |= UnicodeProps::HIDDEN.bits;
189                        *scratch_flags |= BufferScratchFlags::HAS_CGJ;
190                    }
191
192                    _ => {}
193                }
194            }
195
196            if gc.is_mark() {
197                props |= UnicodeProps::CONTINUATION.bits;
198                props |= (u.modified_combining_class() as u16) << 8;
199            }
200        }
201
202        self.set_unicode_props(props);
203    }
204
205    #[inline]
206    pub(crate) fn general_category(&self) -> GeneralCategory {
207        let n = self.unicode_props() & UnicodeProps::GENERAL_CATEGORY.bits;
208        GeneralCategory::from_rb(n as u32)
209    }
210
211    #[inline]
212    pub(crate) fn set_general_category(&mut self, gc: GeneralCategory) {
213        let gc = gc.to_rb();
214        let n = (gc as u16) | (self.unicode_props() & (0xFF & !UnicodeProps::GENERAL_CATEGORY.bits));
215        self.set_unicode_props(n);
216    }
217
218    #[inline]
219    pub(crate) fn space_fallback(&self) -> Option<Space> {
220        if self.general_category() == GeneralCategory::SpaceSeparator {
221            let n = (self.unicode_props() >> 8) as u8;
222            Some(n)
223        } else {
224            None
225        }
226    }
227
228    #[inline]
229    pub(crate) fn set_space_fallback(&mut self, space: Space) {
230        if self.general_category() == GeneralCategory::SpaceSeparator {
231            let n = ((space as u16) << 8) | (self.unicode_props() & 0xFF);
232            self.set_unicode_props(n);
233        }
234    }
235
236    #[inline]
237    pub(crate) fn is_unicode_mark(&self) -> bool {
238        self.general_category().is_mark()
239    }
240
241    #[inline]
242    pub(crate) fn is_zwnj(&self) -> bool {
243        self.general_category() == GeneralCategory::Format
244            && (self.unicode_props() & UnicodeProps::CF_ZWNJ.bits != 0)
245    }
246
247    #[inline]
248    pub(crate) fn is_zwj(&self) -> bool {
249        self.general_category() == GeneralCategory::Format
250            && (self.unicode_props() & UnicodeProps::CF_ZWJ.bits != 0)
251    }
252
253    #[inline]
254    pub(crate) fn modified_combining_class(&self) -> u8 {
255        if self.is_unicode_mark() {
256            (self.unicode_props() >> 8) as u8
257        } else {
258            0
259        }
260    }
261
262    #[inline]
263    pub(crate) fn set_modified_combining_class(&mut self, mcc: u8) {
264        if self.is_unicode_mark() {
265            let n = ((mcc as u16) << 8) | (self.unicode_props() & 0xFF);
266            self.set_unicode_props(n);
267        }
268    }
269
270    #[inline]
271    pub(crate) fn is_hidden(&self) -> bool {
272        self.unicode_props() & UnicodeProps::HIDDEN.bits != 0
273    }
274
275    #[inline]
276    pub(crate) fn unhide(&mut self) {
277        let mut n = self.unicode_props();
278        n &= !UnicodeProps::HIDDEN.bits;
279        self.set_unicode_props(n);
280    }
281
282    #[inline]
283    pub(crate) fn set_continuation(&mut self) {
284        let mut n = self.unicode_props();
285        n |= UnicodeProps::CONTINUATION.bits;
286        self.set_unicode_props(n);
287    }
288
289    #[inline]
290    pub(crate) fn reset_continuation(&mut self) {
291        let mut n = self.unicode_props();
292        n &= !UnicodeProps::CONTINUATION.bits;
293        self.set_unicode_props(n);
294    }
295
296    #[inline]
297    pub(crate) fn is_continuation(&self) -> bool {
298        self.unicode_props() & UnicodeProps::CONTINUATION.bits != 0
299    }
300
301    #[inline]
302    pub(crate) fn is_default_ignorable(&self) -> bool {
303        let n = self.unicode_props() & UnicodeProps::IGNORABLE.bits;
304        n != 0 && !self.is_ligated()
305    }
306
307    // Var allocation: lig_props (aka lig_id / lig_comp)
308    // Used during the GSUB/GPOS processing to track ligatures
309    //
310    // When a ligature is formed:
311    //
312    //   - The ligature glyph and any marks in between all the same newly allocated
313    //     lig_id,
314    //   - The ligature glyph will get lig_num_comps set to the number of components
315    //   - The marks get lig_comp > 0, reflecting which component of the ligature
316    //     they were applied to.
317    //   - This is used in GPOS to attach marks to the right component of a ligature
318    //     in MarkLigPos,
319    //   - Note that when marks are ligated together, much of the above is skipped
320    //     and the current lig_id reused.
321    //
322    // When a multiple-substitution is done:
323    //
324    //   - All resulting glyphs will have lig_id = 0,
325    //   - The resulting glyphs will have lig_comp = 0, 1, 2, ... respectively.
326    //   - This is used in GPOS to attach marks to the first component of a
327    //     multiple substitution in MarkBasePos.
328    //
329    // The numbers are also used in GPOS to do mark-to-mark positioning only
330    // to marks that belong to the same component of the same ligature.
331
332    #[inline]
333    pub(crate) fn lig_props(&self) -> u8 {
334        let v: &[u8; 4] = bytemuck::cast_ref(&self.var1);
335        v[2]
336    }
337
338    #[inline]
339    pub(crate) fn set_lig_props(&mut self, n: u8) {
340        let v: &mut [u8; 4] = bytemuck::cast_mut(&mut self.var1);
341        v[2] = n;
342    }
343
344    pub(crate) fn set_lig_props_for_ligature(&mut self, lig_id: u8, lig_num_comps: u8) {
345        self.set_lig_props((lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F));
346    }
347
348    pub(crate) fn set_lig_props_for_mark(&mut self, lig_id: u8, lig_comp: u8) {
349        self.set_lig_props((lig_id << 5) | (lig_comp & 0x0F));
350    }
351
352    pub(crate) fn set_lig_props_for_component(&mut self, lig_comp: u8) {
353        self.set_lig_props_for_mark(0, lig_comp)
354    }
355
356    #[inline]
357    pub(crate) fn lig_id(&self) -> u8 {
358        self.lig_props() >> 5
359    }
360
361    #[inline]
362    pub(crate) fn is_ligated_internal(&self) -> bool {
363        self.lig_props() & IS_LIG_BASE != 0
364    }
365
366    #[inline]
367    pub(crate) fn lig_comp(&self) -> u8 {
368        if self.is_ligated_internal() {
369            0
370        } else {
371            self.lig_props() & 0x0F
372        }
373    }
374
375    #[inline]
376    pub(crate) fn lig_num_comps(&self) -> u8 {
377        if self.glyph_props() & GlyphPropsFlags::LIGATURE.bits != 0 && self.is_ligated_internal() {
378            self.lig_props() & 0x0F
379        } else {
380            1
381        }
382    }
383
384    // Var allocation: glyph_props
385    // Used during the GSUB/GPOS processing to store GDEF glyph properties
386
387    #[inline]
388    pub(crate) fn glyph_props(&self) -> u16 {
389        let v: &[u16; 2] = bytemuck::cast_ref(&self.var1);
390        v[0]
391    }
392
393    #[inline]
394    pub(crate) fn set_glyph_props(&mut self, n: u16) {
395        let v: &mut [u16; 2] = bytemuck::cast_mut(&mut self.var1);
396        v[0] = n;
397    }
398
399    #[inline]
400    pub(crate) fn is_base_glyph(&self) -> bool {
401        self.glyph_props() & GlyphPropsFlags::BASE_GLYPH.bits != 0
402    }
403
404    #[inline]
405    pub(crate) fn is_ligature(&self) -> bool {
406        self.glyph_props() & GlyphPropsFlags::LIGATURE.bits != 0
407    }
408
409    #[inline]
410    pub(crate) fn is_mark(&self) -> bool {
411        self.glyph_props() & GlyphPropsFlags::MARK.bits != 0
412    }
413
414    #[inline]
415    pub(crate) fn is_substituted(&self) -> bool {
416        self.glyph_props() & GlyphPropsFlags::SUBSTITUTED.bits != 0
417    }
418
419    #[inline]
420    pub(crate) fn is_ligated(&self) -> bool {
421        self.glyph_props() & GlyphPropsFlags::LIGATED.bits != 0
422    }
423
424    #[inline]
425    pub(crate) fn is_multiplied(&self) -> bool {
426        self.glyph_props() & GlyphPropsFlags::MULTIPLIED.bits != 0
427    }
428
429    #[inline]
430    pub(crate) fn is_ligated_and_didnt_multiply(&self) -> bool {
431        self.is_ligated() && !self.is_multiplied()
432    }
433
434    #[inline]
435    pub(crate) fn clear_ligated_and_multiplied(&mut self) {
436        let mut n = self.glyph_props();
437        n &= !(GlyphPropsFlags::LIGATED | GlyphPropsFlags::MULTIPLIED).bits;
438        self.set_glyph_props(n);
439    }
440
441    #[inline]
442    pub(crate) fn clear_substituted(&mut self) {
443        let mut n = self.glyph_props();
444        n &= !GlyphPropsFlags::SUBSTITUTED.bits;
445        self.set_glyph_props(n);
446    }
447
448    // Var allocation: syllable
449    // Used during the GSUB/GPOS processing to store shaping boundaries
450
451    #[inline]
452    pub(crate) fn syllable(&self) -> u8 {
453        let v: &[u8; 4] = bytemuck::cast_ref(&self.var1);
454        v[3]
455    }
456
457    #[inline]
458    pub(crate) fn set_syllable(&mut self, n: u8) {
459        let v: &mut [u8; 4] = bytemuck::cast_mut(&mut self.var1);
460        v[3] = n;
461    }
462
463    // Var allocation: glyph_index
464    // Used during the normalization process to store glyph indices
465
466    #[inline]
467    pub(crate) fn glyph_index(&mut self) -> u32 {
468        self.var1
469    }
470
471    #[inline]
472    pub(crate) fn set_glyph_index(&mut self, n: u32) {
473        self.var1 = n;
474    }
475}
476
477
478/// A cluster level.
479#[allow(missing_docs)]
480#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
481pub enum BufferClusterLevel {
482    MonotoneGraphemes,
483    MonotoneCharacters,
484    Characters,
485}
486
487impl Default for BufferClusterLevel {
488    #[inline]
489    fn default() -> Self {
490        BufferClusterLevel::MonotoneGraphemes
491    }
492}
493
494
495pub struct Buffer {
496    // Information about how the text in the buffer should be treated.
497    pub flags: BufferFlags,
498    pub cluster_level: BufferClusterLevel,
499    pub invisible: Option<GlyphId>,
500    pub scratch_flags: BufferScratchFlags,
501    // Maximum allowed len.
502    pub max_len: usize,
503    /// Maximum allowed operations.
504    pub max_ops: i32,
505
506    // Buffer contents.
507    pub direction: Direction,
508    pub script: Option<Script>,
509    pub language: Option<Language>,
510
511    /// Allocations successful.
512    pub successful: bool,
513    /// Whether we have an output buffer going on.
514    have_output: bool,
515    pub have_separate_output: bool,
516    /// Whether we have positions
517    pub have_positions: bool,
518
519    pub idx: usize,
520    pub len: usize,
521    pub out_len: usize,
522
523    pub info: Vec<GlyphInfo>,
524    pub pos: Vec<GlyphPosition>,
525
526    serial: u32,
527
528    // Text before / after the main buffer contents.
529    // Always in Unicode, and ordered outward.
530    // Index 0 is for "pre-context", 1 for "post-context".
531    pub context: [[char; CONTEXT_LENGTH]; 2],
532    pub context_len: [usize; 2],
533}
534
535impl Buffer {
536    pub const MAX_LEN_FACTOR: usize = 32;
537    pub const MAX_LEN_MIN: usize = 8192;
538    // Shaping more than a billion chars? Let us know!
539    pub const MAX_LEN_DEFAULT: usize = 0x3FFFFFFF;
540
541    pub const MAX_OPS_FACTOR: i32 = 64;
542    pub const MAX_OPS_MIN: i32 = 1024;
543    // Shaping more than a billion operations? Let us know!
544    pub const MAX_OPS_DEFAULT: i32 = 0x1FFFFFFF;
545
546    /// Creates a new `Buffer`.
547    pub fn new() -> Self {
548        Buffer {
549            flags: BufferFlags::empty(),
550            cluster_level: BufferClusterLevel::default(),
551            invisible: None,
552            scratch_flags: BufferScratchFlags::default(),
553            max_len: Self::MAX_LEN_DEFAULT,
554            max_ops: Self::MAX_OPS_DEFAULT,
555            direction: Direction::Invalid,
556            script: None,
557            language: None,
558            successful: true,
559            have_output: false,
560            have_positions: false,
561            idx: 0,
562            len: 0,
563            out_len: 0,
564            info: Vec::new(),
565            pos: Vec::new(),
566            have_separate_output: false,
567            serial: 0,
568            context: [['\0', '\0', '\0', '\0', '\0'], ['\0', '\0', '\0', '\0', '\0']],
569            context_len: [0, 0],
570        }
571    }
572
573    #[inline]
574    pub fn info_slice(&self) -> &[GlyphInfo] {
575        &self.info[..self.len]
576    }
577
578    #[inline]
579    pub fn info_slice_mut(&mut self) -> &mut [GlyphInfo] {
580        &mut self.info[..self.len]
581    }
582
583    #[inline]
584    pub fn out_info(&self) -> &[GlyphInfo] {
585        if self.have_separate_output {
586            bytemuck::cast_slice(self.pos.as_slice())
587        } else {
588            &self.info
589        }
590    }
591
592    #[inline]
593    pub fn out_info_mut(&mut self) -> &mut [GlyphInfo] {
594        if self.have_separate_output {
595            bytemuck::cast_slice_mut(self.pos.as_mut_slice())
596        } else {
597            &mut self.info
598        }
599    }
600
601    #[inline]
602    fn set_out_info(&mut self, i: usize, info: GlyphInfo) {
603        self.out_info_mut()[i] = info;
604    }
605
606    #[inline]
607    pub fn cur(&self, i: usize) -> &GlyphInfo {
608        &self.info[self.idx + i]
609    }
610
611    #[inline]
612    pub fn cur_mut(&mut self, i: usize) -> &mut GlyphInfo {
613        let idx = self.idx + i;
614        &mut self.info[idx]
615    }
616
617    #[inline]
618    pub fn cur_pos_mut(&mut self) -> &mut GlyphPosition {
619        let i = self.idx;
620        &mut self.pos[i]
621    }
622
623    #[inline]
624    pub fn prev(&self) -> &GlyphInfo {
625        let idx = self.out_len.saturating_sub(1);
626        &self.out_info()[idx]
627    }
628
629    #[inline]
630    pub fn prev_mut(&mut self) -> &mut GlyphInfo {
631        let idx = self.out_len.saturating_sub(1);
632        &mut self.out_info_mut()[idx]
633    }
634
635    fn clear(&mut self) {
636        self.direction = Direction::Invalid;
637        self.script = None;
638        self.language = None;
639        self.scratch_flags = BufferScratchFlags::default();
640
641        self.successful = true;
642        self.have_output = false;
643        self.have_positions = false;
644
645        self.idx = 0;
646        self.info.clear();
647        self.pos.clear();
648        self.len = 0;
649        self.out_len = 0;
650        self.have_separate_output = false;
651
652        self.serial = 0;
653
654        self.context = [['\0', '\0', '\0', '\0', '\0'], ['\0', '\0', '\0', '\0', '\0']];
655        self.context_len = [0, 0];
656    }
657
658    #[inline]
659    pub fn backtrack_len(&self) -> usize {
660        if self.have_output { self.out_len } else { self.idx }
661    }
662
663    #[inline]
664    pub fn lookahead_len(&self) -> usize {
665        self.len - self.idx
666    }
667
668    #[inline]
669    fn next_serial(&mut self) -> u32 {
670        self.serial += 1;
671        self.serial
672    }
673
674    fn add(&mut self, codepoint: u32, cluster: u32) {
675        self.ensure(self.len + 1);
676
677        let i = self.len;
678        self.info[i] = GlyphInfo {
679            glyph_id: codepoint,
680            mask: 0,
681            cluster,
682            var1: 0,
683            var2: 0,
684        };
685
686        self.len += 1;
687    }
688
689    #[inline]
690    pub fn reverse(&mut self) {
691        if self.is_empty() {
692            return;
693        }
694
695        self.reverse_range(0, self.len);
696    }
697
698    pub fn reverse_range(&mut self, start: usize, end: usize) {
699        if end - start < 2 {
700            return;
701        }
702
703        self.info[start..end].reverse();
704        if self.have_positions {
705            self.pos[start..end].reverse();
706        }
707    }
708
709    #[inline]
710    fn reset_clusters(&mut self) {
711        for (i, info) in self.info.iter_mut().enumerate() {
712            info.cluster = i as u32;
713        }
714    }
715
716    pub fn guess_segment_properties(&mut self) {
717        if self.script.is_none() {
718            for info in &self.info {
719                match info.as_char().script() {
720                      crate::script::COMMON
721                    | crate::script::INHERITED
722                    | crate::script::UNKNOWN => {}
723                    s => {
724                        self.script = Some(s);
725                        break;
726                    }
727                }
728            }
729        }
730
731        if self.direction == Direction::Invalid {
732            if let Some(script) = self.script {
733                self.direction = Direction::from_script(script).unwrap_or_default();
734            }
735
736            if self.direction == Direction::Invalid {
737                self.direction = Direction::LeftToRight;
738            }
739        }
740
741        // TODO: language must be set
742    }
743
744    pub fn swap_buffers(&mut self) {
745        if !self.successful {
746            return;
747        }
748
749        assert!(self.have_output);
750        self.have_output = false;
751
752        if self.have_separate_output {
753            // Swap info and pos buffers.
754            let info: Vec<GlyphPosition> = bytemuck::cast_vec(core::mem::take(&mut self.info));
755            let pos: Vec<GlyphInfo> = bytemuck::cast_vec(core::mem::take(&mut self.pos));
756            self.pos = info;
757            self.info = pos;
758        }
759
760        core::mem::swap(&mut self.len, &mut self.out_len);
761
762        self.idx = 0;
763    }
764
765    pub fn remove_output(&mut self) {
766        self.have_output = false;
767        self.have_positions = false;
768
769        self.out_len = 0;
770        self.have_separate_output = false;
771    }
772
773    pub fn clear_output(&mut self) {
774        self.have_output = true;
775        self.have_positions = false;
776
777        self.out_len = 0;
778        self.have_separate_output = false;
779    }
780
781    pub fn clear_positions(&mut self) {
782        self.have_output = false;
783        self.have_positions = true;
784
785        self.out_len = 0;
786        self.have_separate_output = false;
787
788        for pos in &mut self.pos {
789            *pos = GlyphPosition::default();
790        }
791    }
792
793    pub fn replace_glyphs(&mut self, num_in: usize, num_out: usize, glyph_data: &[u32]) {
794        if !self.make_room_for(num_in, num_out) {
795            return;
796        }
797
798        assert!(self.idx + num_in <= self.len);
799
800        self.merge_clusters(self.idx, self.idx + num_in);
801
802        let orig_info = self.info[self.idx];
803        for i in 0..num_out {
804            let ii = self.out_len + i;
805            self.set_out_info(ii, orig_info);
806            self.out_info_mut()[ii].glyph_id = glyph_data[i];
807        }
808
809        self.idx += num_in;
810        self.out_len += num_out;
811    }
812
813    pub fn replace_glyph(&mut self, glyph_index: u32) {
814        if self.have_separate_output || self.out_len != self.idx {
815            if !self.make_room_for(1, 1) {
816                return;
817            }
818
819            self.set_out_info(self.out_len, self.info[self.idx]);
820        }
821
822        let out_len = self.out_len;
823        self.out_info_mut()[out_len].glyph_id = glyph_index;
824
825        self.idx += 1;
826        self.out_len += 1;
827    }
828
829    pub fn output_glyph(&mut self, glyph_index: u32) {
830        if !self.make_room_for(0, 1) {
831            return;
832        }
833
834        if self.idx == self.len && self.out_len == 0 {
835            return;
836        }
837
838        let out_len = self.out_len;
839        if self.idx < self.len {
840            self.set_out_info(out_len, self.info[self.idx]);
841        } else {
842            let info = self.out_info()[out_len - 1];
843            self.set_out_info(out_len, info);
844        }
845
846        self.out_info_mut()[out_len].glyph_id = glyph_index;
847
848        self.out_len += 1;
849    }
850
851    pub fn output_info(&mut self, glyph_info: GlyphInfo) {
852        if !self.make_room_for(0, 1) {
853            return;
854        }
855
856        self.set_out_info(self.out_len, glyph_info);
857        self.out_len += 1;
858    }
859
860    pub fn output_char(&mut self, unichar: u32, glyph: u32) {
861        self.cur_mut(0).set_glyph_index(glyph);
862        // This is very confusing indeed.
863        self.output_glyph(unichar);
864        let mut flags = self.scratch_flags;
865        self.prev_mut().init_unicode_props(&mut flags);
866        self.scratch_flags = flags;
867    }
868
869    /// Copies glyph at idx to output but doesn't advance idx.
870    pub fn copy_glyph(&mut self) {
871        if !self.make_room_for(0, 1) {
872            return;
873        }
874
875        self.set_out_info(self.out_len, self.info[self.idx]);
876        self.out_len += 1;
877    }
878
879    /// Copies glyph at idx to output and advance idx.
880    ///
881    /// If there's no output, just advance idx.
882    pub fn next_glyph(&mut self) {
883        if self.have_output {
884            if self.have_separate_output || self.out_len != self.idx {
885                if !self.make_room_for(1, 1) {
886                    return;
887                }
888
889                self.set_out_info(self.out_len, self.info[self.idx]);
890            }
891
892            self.out_len += 1;
893        }
894
895        self.idx += 1;
896    }
897
898    /// Copies n glyphs at idx to output and advance idx.
899    ///
900    /// If there's no output, just advance idx.
901    pub fn next_glyphs(&mut self, n: usize) {
902        if self.have_output {
903            if self.have_separate_output || self.out_len != self.idx {
904                if !self.make_room_for(n, n) {
905                    return;
906                }
907
908                for i in 0..n {
909                    self.set_out_info(self.out_len + i, self.info[self.idx + i]);
910                }
911            }
912
913            self.out_len += n;
914        }
915
916        self.idx += n;
917    }
918
919    pub fn next_char(&mut self, glyph: u32) {
920        self.cur_mut(0).set_glyph_index(glyph);
921        self.next_glyph();
922    }
923
924    /// Advance idx without copying to output.
925    pub fn skip_glyph(&mut self) {
926        self.idx += 1;
927    }
928
929    pub fn reset_masks(&mut self, mask: Mask) {
930        for info in &mut self.info[..self.len] {
931            info.mask = mask;
932        }
933    }
934
935    pub fn set_masks(
936        &mut self,
937        mut value: Mask,
938        mask: Mask,
939        cluster_start: u32,
940        cluster_end: u32,
941    ) {
942        let not_mask = !mask;
943        value &= mask;
944
945        if mask == 0 {
946            return;
947        }
948
949        if cluster_start == 0 && cluster_end == core::u32::MAX {
950            for info in &mut self.info[..self.len] {
951                info.mask = (info.mask & not_mask) | value;
952            }
953
954            return;
955        }
956
957        for info in &mut self.info[..self.len] {
958            if cluster_start <= info.cluster && info.cluster < cluster_end {
959                info.mask = (info.mask & not_mask) | value;
960            }
961        }
962    }
963
964    pub fn merge_clusters(&mut self, start: usize, end: usize) {
965        if end - start < 2 {
966            return;
967        }
968
969        self.merge_clusters_impl(start, end)
970    }
971
972    fn merge_clusters_impl(&mut self, mut start: usize, mut end: usize) {
973        if self.cluster_level == BufferClusterLevel::Characters {
974            self.unsafe_to_break(start, end);
975            return;
976        }
977
978        let mut cluster = self.info[start].cluster;
979
980        for i in start+1..end {
981            cluster = core::cmp::min(cluster, self.info[i].cluster);
982        }
983
984        // Extend end
985        while end < self.len && self.info[end - 1].cluster == self.info[end].cluster {
986            end += 1;
987        }
988
989        // Extend start
990        while end < start && self.info[start - 1].cluster == self.info[start].cluster {
991            start -= 1;
992        }
993
994        // If we hit the start of buffer, continue in out-buffer.
995        if self.idx == start {
996            let mut i = self.out_len;
997            while i != 0 && self.out_info()[i - 1].cluster == self.info[start].cluster {
998                Self::set_cluster(&mut self.out_info_mut()[i - 1], cluster, 0);
999                i -= 1;
1000            }
1001        }
1002
1003        for i in start..end {
1004            Self::set_cluster(&mut self.info[i], cluster, 0);
1005        }
1006    }
1007
1008    pub fn merge_out_clusters(&mut self, mut start: usize, mut end: usize) {
1009        if self.cluster_level == BufferClusterLevel::Characters {
1010            return;
1011        }
1012
1013        if end - start < 2 {
1014            return;
1015        }
1016
1017        let mut cluster = self.out_info()[start].cluster;
1018
1019        for i in start+1..end {
1020            cluster = core::cmp::min(cluster, self.out_info()[i].cluster);
1021        }
1022
1023        // Extend start
1024        while start != 0 && self.out_info()[start - 1].cluster == self.out_info()[start].cluster {
1025            start -= 1;
1026        }
1027
1028        // Extend end
1029        while end < self.out_len && self.out_info()[end - 1].cluster == self.out_info()[end].cluster {
1030            end += 1;
1031        }
1032
1033        // If we hit the start of buffer, continue in out-buffer.
1034        if end == self.out_len {
1035            let mut i = self.idx;
1036            while i < self.len && self.info[i].cluster == self.out_info()[end - 1].cluster {
1037                Self::set_cluster(&mut self.info[i], cluster, 0);
1038                i += 1;
1039            }
1040        }
1041
1042        for i in start..end {
1043            Self::set_cluster(&mut self.out_info_mut()[i], cluster, 0);
1044        }
1045    }
1046
1047    /// Merge clusters for deleting current glyph, and skip it.
1048    pub fn delete_glyph(&mut self) {
1049        let cluster = self.info[self.idx].cluster;
1050
1051        if self.idx + 1 < self.len && cluster == self.info[self.idx + 1].cluster {
1052            // Cluster survives; do nothing.
1053            self.skip_glyph();
1054            return;
1055        }
1056
1057        if self.out_len != 0 {
1058            // Merge cluster backward.
1059            if cluster < self.out_info()[self.out_len - 1].cluster {
1060                let mask = self.info[self.idx].mask;
1061                let old_cluster = self.out_info()[self.out_len - 1].cluster;
1062
1063                let mut i = self.out_len;
1064                while i != 0 && self.out_info()[i - 1].cluster == old_cluster {
1065                    Self::set_cluster(&mut self.out_info_mut()[i - 1], cluster, mask);
1066                    i -= 1;
1067                }
1068            }
1069
1070            self.skip_glyph();
1071            return;
1072        }
1073
1074        if self.idx + 1 < self.len {
1075            // Merge cluster forward.
1076            self.merge_clusters(self.idx, self.idx + 2);
1077        }
1078
1079        self.skip_glyph();
1080    }
1081
1082    pub fn delete_glyphs_inplace(&mut self, filter: impl Fn(&GlyphInfo) -> bool) {
1083        // Merge clusters and delete filtered glyphs.
1084        // NOTE! We can't use out-buffer as we have positioning data.
1085        let mut j = 0;
1086
1087        for i in 0..self.len {
1088            if filter(&self.info[i]) {
1089                // Merge clusters.
1090                // Same logic as delete_glyph(), but for in-place removal
1091
1092                let cluster = self.info[i].cluster;
1093                if i + 1 < self.len && cluster == self.info[i + 1].cluster {
1094                    // Cluster survives; do nothing.
1095                    continue;
1096                }
1097
1098                if j != 0 {
1099                    // Merge cluster backward.
1100                    if cluster < self.info[j - 1].cluster {
1101                        let mask = self.info[i].mask;
1102                        let old_cluster = self.info[j - 1].cluster;
1103
1104                        let mut k = j;
1105                        while k > 0 && self.info[k - 1].cluster == old_cluster {
1106                            Self::set_cluster(&mut self.info[k - 1], cluster, mask);
1107                            k -= 1;
1108                        }
1109                    }
1110                    continue;
1111                }
1112
1113                if i + 1 < self.len {
1114                    // Merge cluster forward.
1115                    self.merge_clusters(i, i + 2);
1116                }
1117
1118                continue;
1119            }
1120
1121            if j != i {
1122                self.info[j] = self.info[i];
1123                self.pos[j] = self.pos[i];
1124            }
1125
1126            j += 1;
1127        }
1128
1129        self.len = j;
1130    }
1131
1132    pub fn unsafe_to_break(&mut self, start: usize, end: usize) {
1133        if end - start < 2 {
1134            return;
1135        }
1136
1137        self.unsafe_to_break_impl(start, end);
1138    }
1139
1140    fn unsafe_to_break_impl(&mut self, start: usize, end: usize) {
1141        let mut cluster = core::u32::MAX;
1142        cluster = Self::_unsafe_to_break_find_min_cluster(&self.info, start, end, cluster);
1143        let unsafe_to_break = Self::_unsafe_to_break_set_mask(&mut self.info, start, end, cluster);
1144        if unsafe_to_break {
1145            self.scratch_flags |= BufferScratchFlags::HAS_UNSAFE_TO_BREAK;
1146        }
1147    }
1148
1149    pub fn unsafe_to_break_from_outbuffer(&mut self, start: usize, end: usize) {
1150        if !self.have_output {
1151            self.unsafe_to_break_impl(start, end);
1152            return;
1153        }
1154
1155        assert!(start <= self.out_len);
1156        assert!(self.idx <= end);
1157
1158        let mut cluster = core::u32::MAX;
1159        cluster = Self::_unsafe_to_break_find_min_cluster(self.out_info(), start, self.out_len, cluster);
1160        cluster = Self::_unsafe_to_break_find_min_cluster(&self.info, self.idx, end, cluster);
1161        let idx = self.idx;
1162        let out_len = self.out_len;
1163        let unsafe_to_break1 = Self::_unsafe_to_break_set_mask(self.out_info_mut(), start, out_len, cluster);
1164        let unsafe_to_break2 = Self::_unsafe_to_break_set_mask(&mut self.info, idx, end, cluster);
1165
1166        if unsafe_to_break1 || unsafe_to_break2 {
1167            self.scratch_flags |= BufferScratchFlags::HAS_UNSAFE_TO_BREAK;
1168        }
1169    }
1170
1171    pub fn move_to(&mut self, i: usize) -> bool {
1172        if !self.have_output {
1173            assert!(i <= self.len);
1174            self.idx = i;
1175            return true;
1176        }
1177
1178        if !self.successful {
1179            return false;
1180        }
1181
1182        assert!(i <= self.out_len + (self.len - self.idx));
1183
1184        if self.out_len < i {
1185            let count = i - self.out_len;
1186            if !self.make_room_for(count, count) {
1187                return false;
1188            }
1189
1190            for j in 0..count {
1191                self.set_out_info(self.out_len + j, self.info[self.idx + j]);
1192            }
1193
1194            self.idx += count;
1195            self.out_len += count;
1196        } else if self.out_len > i {
1197            // Tricky part: rewinding...
1198            let count = self.out_len - i;
1199
1200            // This will blow in our face if memory allocation fails later
1201            // in this same lookup...
1202            //
1203            // We used to shift with extra 32 items, instead of the 0 below.
1204            // But that would leave empty slots in the buffer in case of allocation
1205            // failures.  Setting to zero for now to avoid other problems (see
1206            // comments in shift_forward().  This can cause O(N^2) behavior more
1207            // severely than adding 32 empty slots can...
1208            if self.idx < count {
1209                self.shift_forward(count);
1210            }
1211
1212            assert!(self.idx >= count);
1213
1214            self.idx -= count;
1215            self.out_len -= count;
1216
1217            for j in 0..count {
1218                self.info[self.idx + j] = self.out_info()[self.out_len + j];
1219            }
1220        }
1221
1222        true
1223    }
1224
1225    pub fn ensure(&mut self, size: usize) -> bool {
1226        if size < self.len {
1227            return true;
1228        }
1229
1230        if size > self.max_len {
1231            self.successful = false;
1232            return false;
1233        }
1234
1235        self.info.resize(size, GlyphInfo::default());
1236        self.pos.resize(size, GlyphPosition::default());
1237        true
1238    }
1239
1240    pub fn set_len(&mut self, len: usize) {
1241        self.ensure(len);
1242        self.len = len;
1243    }
1244
1245    fn make_room_for(&mut self, num_in: usize, num_out: usize) -> bool {
1246        if !self.ensure(self.out_len + num_out) {
1247            return false;
1248        }
1249
1250        if !self.have_separate_output && self.out_len + num_out > self.idx + num_in {
1251            assert!(self.have_output);
1252
1253            self.have_separate_output = true;
1254            for i in 0..self.out_len {
1255                self.set_out_info(i, self.info[i]);
1256            }
1257        }
1258
1259        true
1260    }
1261
1262    fn shift_forward(&mut self, count: usize) {
1263        assert!(self.have_output);
1264        self.ensure(self.len + count);
1265
1266        for i in 0..(self.len - self.idx) {
1267            self.info[self.idx + count + i] = self.info[self.idx + i];
1268        }
1269
1270        if self.idx + count > self.len {
1271            for info in &mut self.info[self.len..self.idx+count] {
1272                *info = GlyphInfo::default();
1273            }
1274        }
1275
1276        self.len += count;
1277        self.idx += count;
1278    }
1279
1280    pub fn sort(&mut self, start: usize, end: usize, cmp: impl Fn(&GlyphInfo, &GlyphInfo) -> bool) {
1281        assert!(!self.have_positions);
1282
1283        for i in start+1..end {
1284            let mut j = i;
1285            while j > start && cmp(&self.info[j - 1], &self.info[i]) {
1286                j -= 1;
1287            }
1288
1289            if i == j {
1290                continue;
1291            }
1292
1293            // Move item i to occupy place for item j, shift what's in between.
1294            self.merge_clusters(j, i + 1);
1295
1296            {
1297                let t = self.info[i];
1298                for idx in (0..i-j).rev() {
1299                    self.info[idx + j + 1] = self.info[idx + j];
1300                }
1301
1302                self.info[j] = t;
1303            }
1304        }
1305    }
1306
1307    pub fn set_cluster(info: &mut GlyphInfo, cluster: u32, mask: Mask) {
1308        if info.cluster != cluster {
1309            if mask & glyph_flag::UNSAFE_TO_BREAK != 0 {
1310                info.mask |= glyph_flag::UNSAFE_TO_BREAK;
1311            } else {
1312                info.mask &= !glyph_flag::UNSAFE_TO_BREAK;
1313            }
1314        }
1315
1316        info.cluster = cluster;
1317    }
1318
1319    fn _unsafe_to_break_find_min_cluster(info: &[GlyphInfo], start: usize, end: usize, mut cluster: u32) -> u32 {
1320        for glyph_info in &info[start..end] {
1321            cluster = core::cmp::min(cluster, glyph_info.cluster);
1322        }
1323
1324        cluster
1325    }
1326
1327    fn _unsafe_to_break_set_mask(info: &mut [GlyphInfo], start: usize, end: usize, cluster: u32) -> bool {
1328        let mut unsafe_to_break = false;
1329        for glyph_info in &mut info[start..end] {
1330            if glyph_info.cluster != cluster {
1331                unsafe_to_break = true;
1332                glyph_info.mask |= glyph_flag::UNSAFE_TO_BREAK;
1333            }
1334        }
1335
1336        unsafe_to_break
1337    }
1338
1339    /// Checks that buffer contains no elements.
1340    pub fn is_empty(&self) -> bool {
1341        self.len == 0
1342    }
1343
1344    fn push_str(&mut self, text: &str) {
1345        self.ensure(self.len + text.chars().count());
1346
1347        for (i, c) in text.char_indices() {
1348            self.add(c as u32, i as u32);
1349        }
1350    }
1351
1352    pub fn next_cluster(&self, mut start: usize) -> usize {
1353        if start >= self.len {
1354            return start;
1355        }
1356
1357        let cluster = self.info[start].cluster;
1358        start += 1;
1359        while start < self.len && cluster == self.info[start].cluster {
1360            start += 1;
1361        }
1362
1363        start
1364    }
1365
1366    pub fn next_syllable(&self, mut start: usize) -> usize {
1367        if start >= self.len {
1368            return start;
1369        }
1370
1371        let syllable = self.info[start].syllable();
1372        start += 1;
1373        while start < self.len && syllable == self.info[start].syllable() {
1374            start += 1;
1375        }
1376
1377        start
1378    }
1379
1380    pub fn next_grapheme(&self, mut start: usize) -> usize {
1381        if start >= self.len {
1382            return start;
1383        }
1384
1385        start += 1;
1386        while start < self.len && self.info[start].is_continuation() {
1387            start += 1;
1388        }
1389
1390        start
1391    }
1392
1393    #[inline]
1394    pub fn allocate_lig_id(&mut self) -> u8 {
1395        let mut lig_id = self.next_serial() & 0x07;
1396        if lig_id == 0 {
1397            // In case of overflow.
1398            lig_id = self.next_serial() & 0x07;
1399        }
1400        lig_id as u8
1401    }
1402}
1403
1404// TODO: to iter if possible
1405
1406macro_rules! foreach_cluster {
1407    ($buffer:expr, $start:ident, $end:ident, $($body:tt)*) => {{
1408        let mut $start = 0;
1409        let mut $end = $buffer.next_cluster(0);
1410        while $start < $buffer.len {
1411            $($body)*;
1412            $start = $end;
1413            $end = $buffer.next_cluster($start);
1414        }
1415    }};
1416}
1417
1418macro_rules! foreach_syllable {
1419    ($buffer:expr, $start:ident, $end:ident, $($body:tt)*) => {{
1420        let mut $start = 0;
1421        let mut $end = $buffer.next_syllable(0);
1422        while $start < $buffer.len {
1423            $($body)*;
1424            $start = $end;
1425            $end = $buffer.next_syllable($start);
1426        }
1427    }};
1428}
1429
1430macro_rules! foreach_grapheme {
1431    ($buffer:expr, $start:ident, $end:ident, $($body:tt)*) => {{
1432        let mut $start = 0;
1433        let mut $end = $buffer.next_grapheme(0);
1434        while $start < $buffer.len {
1435            $($body)*;
1436            $start = $end;
1437            $end = $buffer.next_grapheme($start);
1438        }
1439    }};
1440}
1441
1442
1443bitflags::bitflags! {
1444    #[derive(Default)]
1445    pub struct UnicodeProps: u16 {
1446        const GENERAL_CATEGORY  = 0x001F;
1447        const IGNORABLE         = 0x0020;
1448        // MONGOLIAN FREE VARIATION SELECTOR 1..3, or TAG characters
1449        const HIDDEN            = 0x0040;
1450        const CONTINUATION      = 0x0080;
1451
1452        // If GEN_CAT=FORMAT, top byte masks:
1453        const CF_ZWJ            = 0x0100;
1454        const CF_ZWNJ           = 0x0200;
1455    }
1456}
1457
1458
1459bitflags::bitflags! {
1460    #[derive(Default)]
1461    pub struct GlyphPropsFlags: u16 {
1462        // The following three match LookupFlags::Ignore* numbers.
1463        const BASE_GLYPH    = 0x02;
1464        const LIGATURE      = 0x04;
1465        const MARK          = 0x08;
1466        const CLASS_MASK    = Self::BASE_GLYPH.bits | Self::LIGATURE.bits | Self::MARK.bits;
1467
1468        // The following are used internally; not derived from GDEF.
1469        const SUBSTITUTED   = 0x10;
1470        const LIGATED       = 0x20;
1471        const MULTIPLIED    = 0x40;
1472
1473        const PRESERVE      = Self::SUBSTITUTED.bits | Self::LIGATED.bits | Self::MULTIPLIED.bits;
1474    }
1475}
1476
1477
1478bitflags::bitflags! {
1479    #[derive(Default)]
1480    pub struct BufferFlags: u32 {
1481        const BEGINNING_OF_TEXT             = 1 << 1;
1482        const END_OF_TEXT                   = 1 << 2;
1483        const PRESERVE_DEFAULT_IGNORABLES   = 1 << 3;
1484        const REMOVE_DEFAULT_IGNORABLES     = 1 << 4;
1485        const DO_NOT_INSERT_DOTTED_CIRCLE   = 1 << 5;
1486    }
1487}
1488
1489
1490bitflags::bitflags! {
1491    #[derive(Default)]
1492    pub struct BufferScratchFlags: u32 {
1493        const HAS_NON_ASCII             = 0x00000001;
1494        const HAS_DEFAULT_IGNORABLES    = 0x00000002;
1495        const HAS_SPACE_FALLBACK        = 0x00000004;
1496        const HAS_GPOS_ATTACHMENT       = 0x00000008;
1497        const HAS_UNSAFE_TO_BREAK       = 0x00000010;
1498        const HAS_CGJ                   = 0x00000020;
1499
1500        // Reserved for complex shapers' internal use.
1501        const COMPLEX0                  = 0x01000000;
1502        const COMPLEX1                  = 0x02000000;
1503        const COMPLEX2                  = 0x04000000;
1504        const COMPLEX3                  = 0x08000000;
1505    }
1506}
1507
1508
1509bitflags::bitflags! {
1510    /// Flags used for serialization with a `BufferSerializer`.
1511    #[derive(Default)]
1512    pub struct SerializeFlags: u8 {
1513        /// Do not serialize glyph cluster.
1514        const NO_CLUSTERS       = 0b00000001;
1515        /// Do not serialize glyph position information.
1516        const NO_POSITIONS      = 0b00000010;
1517        /// Do no serialize glyph name.
1518        const NO_GLYPH_NAMES    = 0b00000100;
1519        /// Serialize glyph extents.
1520        const GLYPH_EXTENTS     = 0b00001000;
1521        /// Serialize glyph flags.
1522        const GLYPH_FLAGS       = 0b00010000;
1523        /// Do not serialize glyph advances, glyph offsets will reflect absolute
1524        /// glyph positions.
1525        const NO_ADVANCES       = 0b00100000;
1526    }
1527}
1528
1529
1530/// A buffer that contains an input string ready for shaping.
1531pub struct UnicodeBuffer(pub(crate) Buffer);
1532
1533impl UnicodeBuffer {
1534    /// Create a new `UnicodeBuffer`.
1535    #[inline]
1536    pub fn new() -> UnicodeBuffer {
1537        UnicodeBuffer(Buffer::new())
1538    }
1539
1540    /// Returns the length of the data of the buffer.
1541    ///
1542    /// This corresponds to the number of unicode codepoints contained in the
1543    /// buffer.
1544    #[inline]
1545    pub fn len(&self) -> usize {
1546        self.0.len
1547    }
1548
1549    /// Returns `true` if the buffer contains no elements.
1550    #[inline]
1551    pub fn is_empty(&self) -> bool {
1552        self.0.is_empty()
1553    }
1554
1555    /// Pushes a string to a buffer.
1556    #[inline]
1557    pub fn push_str(&mut self, str: &str) {
1558        self.0.push_str(str);
1559    }
1560
1561    /// Appends a character to a buffer with the given cluster value.
1562    #[inline]
1563    pub fn add(&mut self, codepoint: char, cluster: u32) {
1564        self.0.add(codepoint as u32, cluster);
1565        self.0.context_len[1] = 0;
1566    }
1567
1568    /// Set the text direction of the `Buffer`'s contents.
1569    #[inline]
1570    pub fn set_direction(&mut self, direction: Direction) {
1571        self.0.direction = direction;
1572    }
1573
1574    /// Returns the `Buffer`'s text direction.
1575    #[inline]
1576    pub fn direction(&self) -> Direction {
1577        self.0.direction
1578    }
1579
1580    /// Set the script from an ISO15924 tag.
1581    #[inline]
1582    pub fn set_script(&mut self, script: Script) {
1583        self.0.script = Some(script);
1584    }
1585
1586    /// Get the ISO15924 script tag.
1587    pub fn script(&self) -> Script {
1588        self.0.script.unwrap_or(script::UNKNOWN)
1589    }
1590
1591    /// Set the buffer language.
1592    #[inline]
1593    pub fn set_language(&mut self, lang: Language) {
1594        self.0.language = Some(lang);
1595    }
1596
1597    /// Get the buffer language.
1598    #[inline]
1599    pub fn language(&self) -> Option<Language> {
1600        self.0.language.clone()
1601    }
1602
1603    /// Guess the segment properties (direction, language, script) for the
1604    /// current buffer.
1605    #[inline]
1606    pub fn guess_segment_properties(&mut self) {
1607        self.0.guess_segment_properties()
1608    }
1609
1610    /// Set the cluster level of the buffer.
1611    #[inline]
1612    pub fn set_cluster_level(&mut self, cluster_level: BufferClusterLevel) {
1613        self.0.cluster_level = cluster_level
1614    }
1615
1616    /// Retrieve the cluster level of the buffer.
1617    #[inline]
1618    pub fn cluster_level(&self) -> BufferClusterLevel {
1619        self.0.cluster_level
1620    }
1621
1622    /// Resets clusters.
1623    #[inline]
1624    pub fn reset_clusters(&mut self) {
1625        self.0.reset_clusters();
1626    }
1627
1628    /// Clear the contents of the buffer.
1629    #[inline]
1630    pub fn clear(&mut self) {
1631        self.0.clear()
1632    }
1633}
1634
1635impl core::fmt::Debug for UnicodeBuffer {
1636    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1637        fmt.debug_struct("UnicodeBuffer")
1638            .field("direction", &self.direction())
1639            .field("language", &self.language())
1640            .field("script", &self.script())
1641            .field("cluster_level", &self.cluster_level())
1642            .finish()
1643    }
1644}
1645
1646impl Default for UnicodeBuffer {
1647    fn default() -> UnicodeBuffer {
1648        UnicodeBuffer::new()
1649    }
1650}
1651
1652
1653/// A buffer that contains the results of the shaping process.
1654pub struct GlyphBuffer(pub(crate) Buffer);
1655
1656impl GlyphBuffer {
1657    /// Returns the length of the data of the buffer.
1658    ///
1659    /// When called before shaping this is the number of unicode codepoints
1660    /// contained in the buffer. When called after shaping it returns the number
1661    /// of glyphs stored.
1662    #[inline]
1663    pub fn len(&self) -> usize {
1664        self.0.len
1665    }
1666
1667    /// Returns `true` if the buffer contains no elements.
1668    #[inline]
1669    pub fn is_empty(&self) -> bool {
1670        self.0.is_empty()
1671    }
1672
1673    /// Get the glyph infos.
1674    #[inline]
1675    pub fn glyph_infos(&self) -> &[GlyphInfo] {
1676        &self.0.info[0..self.0.len]
1677    }
1678
1679    /// Get the glyph positions.
1680    #[inline]
1681    pub fn glyph_positions(&self) -> &[GlyphPosition] {
1682        &self.0.pos[0..self.0.len]
1683    }
1684
1685    /// Clears the content of the glyph buffer and returns an empty
1686    /// `UnicodeBuffer` reusing the existing allocation.
1687    #[inline]
1688    pub fn clear(mut self) -> UnicodeBuffer {
1689        self.0.clear();
1690        UnicodeBuffer(self.0)
1691    }
1692
1693    /// Converts the glyph buffer content into a string.
1694    pub fn serialize(&self, face: &Face, flags: SerializeFlags) -> String {
1695        self.serialize_impl(face, flags).unwrap_or_default()
1696    }
1697
1698    fn serialize_impl(&self, face: &Face, flags: SerializeFlags) -> Result<String, core::fmt::Error> {
1699        use core::fmt::Write;
1700
1701        let mut s = String::with_capacity(64);
1702
1703        let info = self.glyph_infos();
1704        let pos = self.glyph_positions();
1705        let mut x = 0;
1706        let mut y = 0;
1707        for (info, pos) in info.iter().zip(pos) {
1708            if !flags.contains(SerializeFlags::NO_GLYPH_NAMES) {
1709                match face.glyph_name(info.as_glyph()) {
1710                    Some(name) => s.push_str(name),
1711                    None => write!(&mut s, "gid{}", info.glyph_id)?,
1712                }
1713            } else {
1714                write!(&mut s, "{}", info.glyph_id)?;
1715            }
1716
1717            if !flags.contains(SerializeFlags::NO_CLUSTERS) {
1718                write!(&mut s, "={}", info.cluster)?;
1719            }
1720
1721            if !flags.contains(SerializeFlags::NO_POSITIONS) {
1722                if x + pos.x_offset != 0 || y + pos.y_offset != 0 {
1723                    write!(&mut s, "@{},{}", x + pos.x_offset, y + pos.y_offset)?;
1724                }
1725
1726                if !flags.contains(SerializeFlags::NO_ADVANCES) {
1727                    write!(&mut s, "+{}", pos.x_advance)?;
1728                    if pos.y_advance != 0 {
1729                        write!(&mut s, ",{}", pos.y_advance)?;
1730                    }
1731                }
1732            }
1733
1734            if flags.contains(SerializeFlags::GLYPH_FLAGS) {
1735                if info.mask & glyph_flag::DEFINED != 0 {
1736                    write!(&mut s, "#{:X}", info.mask & glyph_flag::DEFINED)?;
1737                }
1738            }
1739
1740            if flags.contains(SerializeFlags::GLYPH_EXTENTS) {
1741                let extents = face.glyph_extents(info.as_glyph()).unwrap_or_default();
1742                write!(&mut s, "<{},{},{},{}>", extents.x_bearing, extents.y_bearing, extents.width, extents.height)?;
1743            }
1744
1745            if flags.contains(SerializeFlags::NO_ADVANCES) {
1746                x += pos.x_advance;
1747                y += pos.y_advance;
1748            }
1749
1750            s.push('|');
1751        }
1752
1753        // Remove last `|`.
1754        if !s.is_empty() {
1755            s.pop();
1756        }
1757
1758        Ok(s)
1759    }
1760}
1761
1762impl core::fmt::Debug for GlyphBuffer {
1763    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1764        fmt.debug_struct("GlyphBuffer")
1765            .field("glyph_positions", &self.glyph_positions())
1766            .field("glyph_infos", &self.glyph_infos())
1767            .finish()
1768    }
1769}