Skip to main content

harfrust/hb/
buffer.rs

1use super::hb_mask_t;
2use super::unicode::CharExt;
3use crate::hb::face::BasicFontMetrics;
4use crate::hb::glyph_metrics::GlyphMetrics;
5use crate::hb::glyph_names::GlyphNames;
6use crate::hb::set_digest::hb_set_digest_t;
7use crate::hb::tables::TableRanges;
8use crate::hb::unicode::Codepoint;
9use crate::U32Set;
10use crate::{script, BufferClusterLevel, BufferFlags, Direction, Language, Script, SerializeFlags};
11use alloc::{string::String, vec::Vec};
12use core::cmp::min;
13use core::convert::TryFrom;
14use read_fonts::types::{F2Dot14, GlyphId, GlyphId16};
15
16const CONTEXT_LENGTH: usize = 5;
17
18/// Holds the positions of the glyph in both horizontal and vertical directions.
19///
20/// All positions are relative to the current point.
21#[repr(C)]
22#[derive(Clone, Copy, Default, Debug, bytemuck::Pod, bytemuck::Zeroable)]
23pub struct GlyphPosition {
24    /// How much the line advances after drawing this glyph when setting text in
25    /// horizontal direction.
26    pub x_advance: i32,
27    /// How much the line advances after drawing this glyph when setting text in
28    /// vertical direction.
29    pub y_advance: i32,
30    /// How much the glyph moves on the X-axis before drawing it, this should
31    /// not affect how much the line advances.
32    pub x_offset: i32,
33    /// How much the glyph moves on the Y-axis before drawing it, this should
34    /// not affect how much the line advances.
35    pub y_offset: i32,
36    pub(crate) var: u32,
37}
38
39impl GlyphPosition {
40    #[inline]
41    pub(crate) fn attach_chain(&self) -> i16 {
42        // glyph to which this attaches to, relative to current glyphs;
43        // negative for going back, positive for forward.
44        let v: &[i16; 2] = bytemuck::cast_ref(&self.var);
45        v[0]
46    }
47
48    #[inline]
49    pub(crate) fn set_attach_chain(&mut self, n: i16) {
50        let v: &mut [i16; 2] = bytemuck::cast_mut(&mut self.var);
51        v[0] = n;
52    }
53
54    #[inline]
55    pub(crate) fn attach_type(&self) -> u8 {
56        // attachment type
57        // Note! if attach_chain() is zero, the value of attach_type() is irrelevant.
58        let v: &[u8; 4] = bytemuck::cast_ref(&self.var);
59        v[2]
60    }
61
62    #[inline]
63    pub(crate) fn set_attach_type(&mut self, n: u8) {
64        let v: &mut [u8; 4] = bytemuck::cast_mut(&mut self.var);
65        v[2] = n;
66    }
67}
68
69/// A glyph info.
70///
71/// Structure that holds information about the glyphs and their relation to
72/// input text.
73///
74/// HarfBuzz calls this `hb_glyph_info_t`. See the [documentation](https://harfbuzz.github.io/harfbuzz-hb-buffer.html#hb-glyph-info-t)
75/// and [source](https://github.com/harfbuzz/harfbuzz/blob/368598b5bd9c37a15cb0fd5438b8e617e254609b/src/hb-buffer.h#L62).
76#[repr(C)]
77#[derive(Clone, Copy, Default, Debug, bytemuck::Pod, bytemuck::Zeroable)]
78pub struct GlyphInfo {
79    // NOTE: Stores a Unicode codepoint before shaping and a glyph ID after.
80    //       Just like harfbuzz, we are using the same variable for two purposes.
81    //       Occupies u32 as a codepoint and u16 as a glyph id.
82    /// A selected glyph.
83    ///
84    /// Guarantee to be <= `u16::MAX`.
85    pub glyph_id: u32,
86    pub(crate) mask: hb_mask_t,
87    /// An index to the start of the grapheme cluster in the original string.
88    ///
89    /// [Read more on clusters](https://harfbuzz.github.io/clusters.html).
90    pub cluster: u32,
91    pub(crate) vars: [u32; 2],
92}
93
94#[allow(dead_code)]
95pub(crate) struct buffer_var_shape {
96    pub(crate) width: u8,
97    pub(crate) var_index: u8,
98    pub(crate) index: u8,
99}
100
101impl buffer_var_shape {
102    #[inline]
103    pub fn start(&self) -> u8 {
104        (self.var_index - 1) * 4 + self.index * self.width
105    }
106
107    #[inline]
108    pub fn count(&self) -> u8 {
109        self.width
110    }
111
112    #[inline]
113    pub fn bits(&self) -> u8 {
114        let start = self.start();
115        let end = start + self.count();
116        debug_assert!(end <= 8);
117        ((1u16 << end) - (1u16 << start)) as u8
118    }
119}
120
121macro_rules! declare_buffer_var {
122    ($ty:ty, $var_index:expr, $index:expr, $var_name:ident, $getter:ident, $setter:ident) => {
123        #[allow(dead_code)]
124        pub(crate) const $var_name: buffer_var_shape = buffer_var_shape {
125            width: core::mem::size_of::<$ty>() as u8,
126            var_index: $var_index,
127            index: $index,
128        };
129
130        #[inline]
131        #[allow(dead_code)]
132        pub(crate) fn $getter(&self) -> $ty {
133            const LEN: usize = core::mem::size_of::<u32>() / core::mem::size_of::<$ty>();
134            let v: &[$ty; LEN] = bytemuck::cast_ref(&self.vars[$var_index - 1usize]);
135            v[$index]
136        }
137
138        #[inline]
139        #[allow(dead_code)]
140        pub(crate) fn $setter(&mut self, value: $ty) {
141            const LEN: usize = core::mem::size_of::<u32>() / core::mem::size_of::<$ty>();
142            let v: &mut [$ty; LEN] = bytemuck::cast_mut(&mut self.vars[$var_index - 1usize]);
143            v[$index] = value;
144        }
145    };
146}
147
148macro_rules! declare_buffer_var_alias {
149    ($alias_var:ident, $ty:ty, $var_name:ident, $getter:ident, $setter:ident) => {
150        #[allow(dead_code)]
151        pub(crate) const $var_name: buffer_var_shape = GlyphInfo::$alias_var;
152
153        #[inline]
154        pub(crate) fn $getter(&self) -> $ty {
155            const { assert!(GlyphInfo::$alias_var.width == core::mem::size_of::<$ty>() as u8) };
156            const LEN: usize = core::mem::size_of::<u32>() / core::mem::size_of::<$ty>();
157            let v: &[$ty; LEN] =
158                bytemuck::cast_ref(&self.vars[GlyphInfo::$alias_var.var_index as usize - 1usize]);
159            v[GlyphInfo::$alias_var.index as usize]
160        }
161
162        #[inline]
163        pub(crate) fn $setter(&mut self, value: $ty) {
164            const { assert!(GlyphInfo::$alias_var.width == core::mem::size_of::<$ty>() as u8) };
165            const LEN: usize = core::mem::size_of::<u32>() / core::mem::size_of::<$ty>();
166            let v: &mut [$ty; LEN] = bytemuck::cast_mut(
167                &mut self.vars[GlyphInfo::$alias_var.var_index as usize - 1usize],
168            );
169            v[GlyphInfo::$alias_var.index as usize] = value;
170        }
171    };
172}
173
174/// Flags that describe the properties of a glyph.
175#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
176pub struct GlyphFlags(pub(crate) u32);
177
178impl GlyphFlags {
179    /// Indicates that if input text is broken at the beginning of the cluster this glyph
180    /// is part of, then both sides need to be re-shaped, as the result might be different.
181    ///
182    /// On the flip side, it means that when this flag is not present,
183    /// then it's safe to break the glyph-run at the beginning of this cluster,
184    /// and the two sides represent the exact same result one would get if breaking input text
185    /// at the beginning of this cluster and shaping the two sides separately.
186    /// This can be used to optimize paragraph layout, by avoiding re-shaping of each line
187    /// after line-breaking, or limiting the reshaping to a small piece around
188    /// the breaking point only.
189    pub const UNSAFE_TO_BREAK: Self = Self(0x0000_0001);
190
191    /// Indicates that if input text is changed on one side of the beginning of the cluster
192    /// this glyph is part of, then the shaping results for the other side might change.
193    /// Note that the absence of this flag will NOT by itself mean that it IS safe to concat
194    /// text. Only two pieces of text both of which clear of this flag can be concatenated
195    /// safely.
196    ///
197    /// This can be used to optimize paragraph layout, by avoiding re-shaping of each line after
198    /// line-breaking, by limiting the reshaping to a small piece around the breaking position
199    /// only, even if the breaking position carries the unsafe-to-break flag or when hyphenation
200    /// or other text transformation happens at line-break position, in the following way:
201    /// 1. Iterate back from the line-break position until the first cluster start position
202    ///    that is NOT unsafe-to-concat.
203    /// 2. Shape the segment from there till the end of line.
204    /// 3. Check whether the resulting glyph-run also is clear of the unsafe-to-concat at its
205    ///    start-of-text position; if it is, just splice it into place and the line is shaped;
206    ///    If not, move on to a position further back that is clear of unsafe-to-concat and retry
207    ///    from there, and repeat.
208    ///
209    /// At the start of next line a similar algorithm can be implemented. That is:
210    /// 1. Iterate forward from the line-break position until the first cluster start position that is
211    ///    NOT unsafe-to-concat.
212    /// 2. Shape the segment from beginning of the line to that position.
213    /// 3. Check whether the resulting glyph-run also is clear of the unsafe-to-concat at its end-of-text
214    ///    position; if it is, just splice it into place and the beginning is shaped; If not, move on to a
215    ///    position further forward that is clear of unsafe-to-concat and retry up to there, and repeat. A
216    ///    slight complication will arise in the implementation of the algorithm above, because while our
217    ///    buffer API has a way to return flags for position corresponding to start-of-text, there is currently
218    ///    no position corresponding to end-of-text. This limitation can be alleviated by shaping more text
219    ///    than needed and looking for unsafe-to-concat flag within text clusters. The unsafe-to-break flag will
220    ///    always imply this flag. To use this flag, you must enable the buffer flag [`BufferFlags::PRODUCE_UNSAFE_TO_CONCAT`]
221    ///    during shaping, otherwise the buffer flag will not be reliably produced.
222    pub const UNSAFE_TO_CONCAT: Self = Self(0x0000_0002);
223
224    /// In scripts that use elongation (Arabic, Mongolian, Syriac, etc.), this flag signifies that it is
225    /// safe to insert a U+0640 TATWEEL character before this cluster for elongation. This flag does not
226    /// determine the script-specific elongation places, but only when it is safe to do the elongation
227    /// without interrupting text shaping.
228    pub const SAFE_TO_INSERT_TATWEEL: Self = Self(0x0000_0004);
229
230    /// All the currently defined flags.
231    pub const ALL: Self = Self(Self::DEFINED_BITS);
232
233    pub(crate) const DEFINED_BITS: u32 = 0x0000_0007; // OR of all defined flags
234
235    /// Creates a `GlyphFlags` from the given bits, ignoring any bits that are not defined.
236    pub const fn from_bits_truncate(bits: u32) -> Self {
237        Self(bits & Self::DEFINED_BITS)
238    }
239
240    /// Returns the underlying flag bits.
241    #[inline(always)]
242    pub const fn to_bits(self) -> u32 {
243        self.0
244    }
245
246    /// Indicates that if input text is broken at the beginning of the cluster this glyph
247    /// is part of, then both sides need to be re-shaped, as the result might be different.
248    ///
249    /// See [Self::UNSAFE_TO_BREAK] for more details.
250    #[inline(always)]
251    pub const fn is_unsafe_to_break(self) -> bool {
252        self.intersects(Self::UNSAFE_TO_BREAK)
253    }
254
255    /// Indicates that if input text is changed on one side of the beginning of the cluster
256    /// this glyph is part of, then the shaping results for the other side might change.
257    ///
258    /// See [Self::UNSAFE_TO_CONCAT] for more details.
259    #[inline(always)]
260    pub const fn is_unsafe_to_concat(self) -> bool {
261        self.intersects(Self::UNSAFE_TO_CONCAT)
262    }
263
264    /// In scripts that use elongation (Arabic, Mongolian, Syriac, etc.), this flag signifies that it is
265    /// safe to insert a U+0640 TATWEEL character before this cluster for elongation.
266    ///
267    /// See [Self::SAFE_TO_INSERT_TATWEEL] for more details.
268    #[inline(always)]
269    pub const fn is_safe_to_insert_tatweel(self) -> bool {
270        self.intersects(Self::SAFE_TO_INSERT_TATWEEL)
271    }
272
273    /// Returns `true` if all of the flags in `other` are contained within `self`.
274    #[inline(always)]
275    pub const fn contains(self, other: Self) -> bool {
276        (self.0 & other.0) == other.0
277    }
278
279    /// Returns `true` if any of the flags in `other` are contained within `self`.
280    #[inline(always)]
281    pub const fn intersects(self, other: Self) -> bool {
282        (self.0 & other.0) != 0
283    }
284}
285
286impl core::ops::BitOr for GlyphFlags {
287    type Output = Self;
288
289    #[inline(always)]
290    fn bitor(self, rhs: Self) -> Self::Output {
291        Self(self.0 | rhs.0)
292    }
293}
294
295impl core::ops::BitOrAssign for GlyphFlags {
296    #[inline(always)]
297    fn bitor_assign(&mut self, rhs: Self) {
298        self.0 |= rhs.0;
299    }
300}
301
302impl core::ops::BitAnd for GlyphFlags {
303    type Output = Self;
304
305    #[inline(always)]
306    fn bitand(self, rhs: Self) -> Self::Output {
307        Self(self.0 & rhs.0)
308    }
309}
310
311impl core::ops::BitAndAssign for GlyphFlags {
312    #[inline(always)]
313    fn bitand_assign(&mut self, rhs: Self) {
314        self.0 &= rhs.0;
315    }
316}
317
318impl core::ops::Not for GlyphFlags {
319    type Output = Self;
320
321    #[inline(always)]
322    fn not(self) -> Self::Output {
323        Self(!self.0 & Self::DEFINED_BITS)
324    }
325}
326
327impl GlyphInfo {
328    /// Returns the flags for this glyph.
329    #[inline(always)]
330    pub const fn flags(&self) -> GlyphFlags {
331        GlyphFlags(self.mask)
332    }
333
334    /// Indicates that if input text is broken at the beginning of the cluster this glyph
335    /// is part of, then both sides need to be re-shaped, as the result might be different.
336    ///
337    /// On the flip side, it means that when this flag is not present,
338    /// then it's safe to break the glyph-run at the beginning of this cluster,
339    /// and the two sides represent the exact same result one would get if breaking input text
340    /// at the beginning of this cluster and shaping the two sides separately.
341    /// This can be used to optimize paragraph layout, by avoiding re-shaping of each line
342    /// after line-breaking, or limiting the reshaping to a small piece around
343    /// the breaking point only.
344    #[inline(always)]
345    pub fn unsafe_to_break(&self) -> bool {
346        self.flags().is_unsafe_to_break()
347    }
348
349    /// Indicates that if input text is changed on one side of the beginning of the cluster
350    /// this glyph is part of, then the shaping results for the other side might change.
351    /// Note that the absence of this flag will NOT by itself mean that it IS safe to concat
352    /// text. Only two pieces of text both of which clear of this flag can be concatenated
353    /// safely.
354    ///
355    /// This can be used to optimize paragraph layout, by avoiding re-shaping of each line after
356    /// line-breaking, by limiting the reshaping to a small piece around the breaking position
357    /// only, even if the breaking position carries the unsafe-to-break flag or when hyphenation
358    /// or other text transformation happens at line-break position, in the following way:
359    /// 1. Iterate back from the line-break position until the first cluster start position
360    ///    that is NOT unsafe-to-concat.
361    /// 2. Shape the segment from there till the end of line.
362    /// 3. Check whether the resulting glyph-run also is clear of the unsafe-to-concat at its
363    ///    start-of-text position; if it is, just splice it into place and the line is shaped;
364    ///    If not, move on to a position further back that is clear of unsafe-to-concat and retry
365    ///    from there, and repeat.
366    ///
367    /// At the start of next line a similar algorithm can be implemented. That is:
368    /// 1. Iterate forward from the line-break position until the first cluster start position that is
369    ///    NOT unsafe-to-concat.
370    /// 2. Shape the segment from beginning of the line to that position.
371    /// 3. Check whether the resulting glyph-run also is clear of the unsafe-to-concat at its end-of-text
372    ///    position; if it is, just splice it into place and the beginning is shaped; If not, move on to a
373    ///    position further forward that is clear of unsafe-to-concat and retry up to there, and repeat. A
374    ///    slight complication will arise in the implementation of the algorithm above, because while our
375    ///    buffer API has a way to return flags for position corresponding to start-of-text, there is currently
376    ///    no position corresponding to end-of-text. This limitation can be alleviated by shaping more text
377    ///    than needed and looking for unsafe-to-concat flag within text clusters. The unsafe-to-break flag will
378    ///    always imply this flag. To use this flag, you must enable the buffer flag [`BufferFlags::PRODUCE_UNSAFE_TO_CONCAT`]
379    ///    during shaping, otherwise the buffer flag will not be reliably produced.
380    #[inline(always)]
381    pub fn unsafe_to_concat(&self) -> bool {
382        self.flags().is_unsafe_to_concat()
383    }
384
385    /// In scripts that use elongation (Arabic, Mongolian, Syriac, etc.), this flag signifies that it is
386    /// safe to insert a U+0640 TATWEEL character before this cluster for elongation. This flag does not
387    /// determine the script-specific elongation places, but only when it is safe to do the elongation
388    /// without interrupting text shaping.
389    #[inline(always)]
390    pub fn safe_to_insert_tatweel(&self) -> bool {
391        self.flags().is_safe_to_insert_tatweel()
392    }
393
394    pub(crate) fn as_codepoint(&self) -> Codepoint {
395        self.glyph_id
396    }
397
398    #[inline]
399    pub(crate) fn as_glyph(&self) -> GlyphId {
400        GlyphId::new(self.glyph_id)
401    }
402
403    #[inline]
404    pub(crate) fn as_gid16(&self) -> Option<GlyphId16> {
405        let gid: u16 = self.glyph_id.try_into().ok()?;
406        Some(gid.into())
407    }
408
409    pub(crate) fn init_unicode_props(&mut self, scratch_flags: &mut hb_buffer_scratch_flags_t) {
410        let u = self.as_codepoint();
411        let gc = u.general_category();
412        let mut props = gc.0 as u16;
413
414        if u >= 0x80 {
415            if u.is_default_ignorable() {
416                props |= UnicodeProps::IGNORABLE.bits();
417                *scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
418
419                match u {
420                    0x200C => props |= UnicodeProps::CF_ZWNJ.bits(),
421                    0x200D => props |= UnicodeProps::CF_ZWJ.bits(),
422
423                    // Mongolian Free Variation Selectors need to be remembered
424                    // because although we need to hide them like default-ignorables,
425                    // they need to non-ignorable during shaping.  This is similar to
426                    // what we do for joiners in Indic-like shapers, but since the
427                    // FVSes are GC=Mn, we have use a separate bit to remember them.
428                    // Fixes:
429                    // https://github.com/harfbuzz/harfbuzz/issues/234
430                    0x180B..=0x180D | 0x180F => props |= UnicodeProps::HIDDEN.bits(),
431
432                    // TAG characters need similar treatment. Fixes:
433                    // https://github.com/harfbuzz/harfbuzz/issues/463
434                    0xE0020..=0xE007F => props |= UnicodeProps::HIDDEN.bits(),
435
436                    // COMBINING GRAPHEME JOINER should not be skipped during GSUB either.
437                    // https://github.com/harfbuzz/harfbuzz/issues/554
438                    0x034F => {
439                        props |= UnicodeProps::HIDDEN.bits();
440                        *scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CGJ;
441                    }
442
443                    _ => {}
444                }
445            }
446
447            if gc.is_mark() {
448                *scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CONTINUATIONS;
449                props |= UnicodeProps::CONTINUATION.bits();
450                props |= (u.modified_combining_class() as u16) << 8;
451            }
452        }
453
454        self.set_unicode_props(props);
455    }
456
457    #[inline]
458    pub(crate) fn unhide(&mut self) {
459        let mut n = self.unicode_props();
460        n &= !UnicodeProps::HIDDEN.bits();
461        self.set_unicode_props(n);
462    }
463}
464
465pub type hb_buffer_cluster_level_t = u32;
466pub const HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES: u32 = 0;
467pub const HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS: u32 = 1;
468pub const HB_BUFFER_CLUSTER_LEVEL_CHARACTERS: u32 = 2;
469pub const HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES: u32 = 3;
470pub const HB_BUFFER_CLUSTER_LEVEL_DEFAULT: u32 = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES;
471
472pub struct hb_buffer_t {
473    // Information about how the text in the buffer should be treated.
474    pub flags: BufferFlags,
475    pub cluster_level: hb_buffer_cluster_level_t,
476    pub invisible: Option<GlyphId>,
477    pub not_found_variation_selector: Option<u32>,
478
479    // Buffer contents.
480    pub direction: Direction,
481    pub script: Option<Script>,
482    pub language: Option<Language>,
483
484    /// Allocations successful.
485    pub successful: bool,
486    /// Whether we have an output buffer going on.
487    pub(crate) have_output: bool,
488    pub have_separate_output: bool,
489    /// Whether we have positions
490    pub have_positions: bool,
491
492    pub idx: usize,
493    pub len: usize,
494    pub out_len: usize,
495
496    pub info: Vec<GlyphInfo>,
497    pub pos: Vec<GlyphPosition>,
498
499    // Text before / after the main buffer contents.
500    // Always in Unicode, and ordered outward.
501    // Index 0 is for "pre-context", 1 for "post-context".
502    pub context: [[Codepoint; CONTEXT_LENGTH]; 2],
503    pub context_len: [usize; 2],
504
505    pub(crate) digest: hb_set_digest_t,
506    pub(crate) glyph_set: U32Set,
507
508    // Managed by enter / leave
509    pub allocated_var_bits: u8,
510    pub serial: u8,
511    pub scratch_flags: hb_buffer_scratch_flags_t,
512    /// Maximum allowed len.
513    pub max_len: usize,
514    /// Maximum allowed operations.
515    pub max_ops: i32,
516}
517
518impl hb_buffer_t {
519    pub const MAX_LEN_FACTOR: usize = 256;
520    pub const MAX_LEN_MIN: usize = 65536;
521    // Shaping more than a billion chars? Let us know!
522    pub const MAX_LEN_DEFAULT: usize = 0x3FFF_FFFF;
523
524    pub const MAX_OPS_FACTOR: i32 = 4096;
525    pub const MAX_OPS_MIN: i32 = 65536;
526    // Shaping more than a billion operations? Let us know!
527    pub const MAX_OPS_DEFAULT: i32 = 0x1FFF_FFFF;
528
529    /// Creates a new `Buffer`.
530    pub fn new() -> Self {
531        hb_buffer_t {
532            flags: BufferFlags::empty(),
533            cluster_level: HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
534            invisible: None,
535            scratch_flags: HB_BUFFER_SCRATCH_FLAG_DEFAULT,
536            not_found_variation_selector: None,
537            max_len: Self::MAX_LEN_DEFAULT,
538            max_ops: Self::MAX_OPS_DEFAULT,
539            direction: Direction::Invalid,
540            script: None,
541            language: None,
542            successful: true,
543            have_output: false,
544            have_positions: false,
545            idx: 0,
546            len: 0,
547            out_len: 0,
548            info: Vec::new(),
549            pos: Vec::new(),
550            have_separate_output: false,
551            allocated_var_bits: 0,
552            serial: 0,
553            context: Default::default(),
554            context_len: [0, 0],
555            digest: hb_set_digest_t::new(),
556            glyph_set: U32Set::default(),
557        }
558    }
559
560    #[inline]
561    pub fn allocate_var(&mut self, shape: buffer_var_shape) {
562        let bits = shape.bits();
563        debug_assert_eq!(
564            self.allocated_var_bits & bits,
565            0,
566            "Variable already allocated"
567        );
568        self.allocated_var_bits |= bits;
569    }
570
571    #[inline]
572    pub fn try_allocate_var(&mut self, shape: buffer_var_shape) -> bool {
573        let bits = shape.bits();
574        if self.allocated_var_bits & bits != 0 {
575            return false;
576        }
577        self.allocated_var_bits |= bits;
578        true
579    }
580
581    #[inline]
582    pub fn deallocate_var(&mut self, shape: buffer_var_shape) {
583        let bits = shape.bits();
584        debug_assert_eq!(
585            self.allocated_var_bits & bits,
586            bits,
587            "Deallocating unallocated var"
588        );
589        self.allocated_var_bits &= !bits;
590    }
591
592    #[inline]
593    pub fn assert_var(&self, shape: buffer_var_shape) {
594        let bits = shape.bits();
595        debug_assert_eq!(
596            self.allocated_var_bits & bits,
597            bits,
598            "Variable not allocated"
599        );
600    }
601
602    #[inline]
603    pub fn info_slice_mut(&mut self) -> &mut [GlyphInfo] {
604        &mut self.info[..self.len]
605    }
606
607    #[inline]
608    pub fn out_info(&self) -> &[GlyphInfo] {
609        if self.have_separate_output {
610            bytemuck::cast_slice(self.pos.as_slice())
611        } else {
612            &self.info
613        }
614    }
615
616    #[inline]
617    pub fn out_info_mut(&mut self) -> &mut [GlyphInfo] {
618        if self.have_separate_output {
619            bytemuck::cast_slice_mut(self.pos.as_mut_slice())
620        } else {
621            &mut self.info
622        }
623    }
624
625    #[inline]
626    fn set_out_info(&mut self, i: usize, info: GlyphInfo) {
627        self.out_info_mut()[i] = info;
628    }
629
630    #[inline]
631    pub fn cur(&self, i: usize) -> &GlyphInfo {
632        &self.info[self.idx + i]
633    }
634
635    #[inline]
636    pub fn cur_mut(&mut self, i: usize) -> &mut GlyphInfo {
637        let idx = self.idx + i;
638        &mut self.info[idx]
639    }
640
641    #[inline]
642    pub fn cur_pos_mut(&mut self) -> &mut GlyphPosition {
643        let i = self.idx;
644        &mut self.pos[i]
645    }
646
647    #[inline]
648    pub fn prev(&self) -> &GlyphInfo {
649        let idx = self.out_len.saturating_sub(1);
650        &self.out_info()[idx]
651    }
652
653    #[inline]
654    pub fn prev_mut(&mut self) -> &mut GlyphInfo {
655        let idx = self.out_len.saturating_sub(1);
656        &mut self.out_info_mut()[idx]
657    }
658
659    pub fn update_digest(&mut self) {
660        self.digest = hb_set_digest_t::new();
661        self.digest.add_array(self.info.iter().map(|i| i.glyph_id));
662    }
663    pub fn update_glyph_set(&mut self) {
664        self.glyph_set.clear();
665        self.glyph_set
666            .extend_unsorted(self.info.iter().map(|i| i.glyph_id));
667    }
668
669    fn clear(&mut self) {
670        self.direction = Direction::Invalid;
671        self.script = None;
672        self.language = None;
673
674        self.successful = true;
675        self.have_output = false;
676        self.have_positions = false;
677
678        self.idx = 0;
679        self.info.clear();
680        self.pos.clear();
681        self.len = 0;
682        self.out_len = 0;
683        self.have_separate_output = false;
684
685        self.context = Default::default();
686        self.context_len = [0, 0];
687
688        self.serial = 0;
689        self.scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
690        self.cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT;
691        self.not_found_variation_selector = None;
692    }
693
694    #[inline]
695    pub fn backtrack_len(&self) -> usize {
696        if self.have_output {
697            self.out_len
698        } else {
699            self.idx
700        }
701    }
702
703    #[inline]
704    pub fn lookahead_len(&self) -> usize {
705        self.len - self.idx
706    }
707
708    #[inline]
709    fn next_serial(&mut self) -> u8 {
710        // A `serial` overflow/wrap-around here is perfectly fine.
711        self.serial = self.serial.wrapping_add(1);
712
713        if self.serial == 0 {
714            self.serial += 1;
715        }
716
717        self.serial
718    }
719
720    fn add(&mut self, codepoint: u32, cluster: u32) {
721        if !self.ensure(self.len + 1) {
722            return;
723        }
724        self.info[self.len] = GlyphInfo {
725            glyph_id: codepoint,
726            cluster,
727            ..GlyphInfo::default()
728        };
729        self.len += 1;
730    }
731
732    #[inline]
733    pub fn reverse(&mut self) {
734        if self.is_empty() {
735            return;
736        }
737
738        self.reverse_range(0, self.len);
739    }
740
741    pub fn reverse_range(&mut self, start: usize, end: usize) {
742        if end - start < 2 {
743            return;
744        }
745
746        self.info[start..end].reverse();
747        if self.have_positions {
748            self.pos[start..end].reverse();
749        }
750    }
751
752    pub fn reverse_groups<F>(&mut self, group: F, merge_clusters: bool)
753    where
754        F: Fn(&GlyphInfo, &GlyphInfo) -> bool,
755    {
756        if self.is_empty() {
757            return;
758        }
759
760        let mut start = 0;
761        let mut i = 1;
762
763        while i < self.len {
764            if !group(&self.info[i - 1], &self.info[i]) {
765                if merge_clusters {
766                    self.merge_clusters(start, i);
767                }
768
769                self.reverse_range(start, i);
770                start = i;
771            }
772
773            i += 1;
774        }
775
776        if merge_clusters {
777            self.merge_clusters(start, i);
778        }
779
780        self.reverse_range(start, i);
781
782        self.reverse();
783    }
784
785    pub fn group_end<F>(&self, mut start: usize, group: F) -> usize
786    where
787        F: Fn(&GlyphInfo, &GlyphInfo) -> bool,
788    {
789        start += 1;
790
791        while start < self.len && group(&self.info[start - 1], &self.info[start]) {
792            start += 1;
793        }
794
795        start
796    }
797
798    #[inline]
799    fn reset_clusters(&mut self) {
800        for (i, info) in self.info.iter_mut().enumerate() {
801            info.cluster = i as u32;
802        }
803    }
804
805    pub fn guess_segment_properties(&mut self) {
806        if self.script.is_none() {
807            for info in &self.info {
808                match info.as_codepoint().script() {
809                    script::COMMON | script::INHERITED | script::UNKNOWN => {}
810                    s => {
811                        self.script = Some(s);
812                        break;
813                    }
814                }
815            }
816        }
817
818        if self.direction == Direction::Invalid {
819            if let Some(script) = self.script {
820                self.direction = Direction::from_script(script).unwrap_or_default();
821            }
822
823            if self.direction == Direction::Invalid {
824                self.direction = Direction::LeftToRight;
825            }
826        }
827
828        // TODO: language must be set
829    }
830
831    pub fn sync(&mut self) -> bool {
832        debug_assert!(self.have_output);
833        debug_assert!(self.idx <= self.len);
834
835        if !self.successful {
836            self.have_output = false;
837            self.out_len = 0;
838            self.idx = 0;
839            return false;
840        }
841
842        self.next_glyphs(self.len - self.idx);
843
844        if self.have_separate_output {
845            // Swap info and pos buffers.
846            let info: Vec<GlyphPosition> = bytemuck::cast_vec(core::mem::take(&mut self.info));
847            let pos: Vec<GlyphInfo> = bytemuck::cast_vec(core::mem::take(&mut self.pos));
848            self.pos = info;
849            self.info = pos;
850            self.have_separate_output = false;
851        }
852
853        self.len = self.out_len;
854
855        self.have_output = false;
856        self.out_len = 0;
857        self.idx = 0;
858        true
859    }
860
861    pub fn clear_output(&mut self) {
862        self.have_output = true;
863        self.have_positions = false;
864
865        self.idx = 0;
866        self.out_len = 0;
867        self.have_separate_output = false;
868    }
869
870    pub fn clear_positions(&mut self) {
871        self.have_output = false;
872        self.have_positions = true;
873
874        self.out_len = 0;
875        self.have_separate_output = false;
876
877        for pos in &mut self.pos {
878            *pos = GlyphPosition::default();
879        }
880    }
881
882    pub fn replace_glyphs(&mut self, num_in: usize, num_out: usize, glyph_data: &[u32]) {
883        if !self.make_room_for(num_in, num_out) {
884            return;
885        }
886
887        debug_assert!(self.idx + num_in <= self.len);
888
889        self.merge_clusters(self.idx, self.idx + num_in);
890
891        let orig_info = self.info[self.idx];
892        for i in 0..num_out {
893            let ii = self.out_len + i;
894            self.set_out_info(ii, orig_info);
895            self.out_info_mut()[ii].glyph_id = glyph_data[i];
896        }
897
898        self.idx += num_in;
899        self.out_len += num_out;
900    }
901
902    pub fn replace_glyph(&mut self, glyph_index: u32) {
903        if self.have_separate_output || self.out_len != self.idx {
904            if !self.make_room_for(1, 1) {
905                return;
906            }
907
908            self.set_out_info(self.out_len, self.info[self.idx]);
909        }
910
911        let out_len = self.out_len;
912        self.out_info_mut()[out_len].glyph_id = glyph_index;
913
914        self.idx += 1;
915        self.out_len += 1;
916    }
917
918    pub fn output_glyph(&mut self, glyph_index: u32) {
919        if !self.make_room_for(0, 1) {
920            return;
921        }
922
923        if self.idx == self.len && self.out_len == 0 {
924            return;
925        }
926
927        let out_len = self.out_len;
928        if self.idx < self.len {
929            self.set_out_info(out_len, self.info[self.idx]);
930        } else {
931            let info = self.out_info()[out_len - 1];
932            self.set_out_info(out_len, info);
933        }
934
935        self.out_info_mut()[out_len].glyph_id = glyph_index;
936
937        self.out_len += 1;
938    }
939
940    pub fn output_info(&mut self, glyph_info: GlyphInfo) {
941        if !self.make_room_for(0, 1) {
942            return;
943        }
944
945        self.set_out_info(self.out_len, glyph_info);
946        self.out_len += 1;
947    }
948
949    /// Copies glyph at idx to output but doesn't advance idx.
950    pub fn copy_glyph(&mut self) {
951        if !self.make_room_for(0, 1) {
952            return;
953        }
954
955        self.set_out_info(self.out_len, self.info[self.idx]);
956        self.out_len += 1;
957    }
958
959    /// Copies glyph at idx to output and advance idx.
960    ///
961    /// If there's no output, just advance idx.
962    #[inline(always)]
963    pub fn next_glyph(&mut self) {
964        if self.have_output {
965            if self.have_separate_output || self.out_len != self.idx {
966                if !self.ensure(self.out_len + 1) {
967                    return;
968                }
969
970                let i = self.out_len;
971                self.out_info_mut()[i] = self.info[self.idx];
972            }
973
974            self.out_len += 1;
975        }
976
977        self.idx += 1;
978    }
979
980    /// Copies n glyphs at idx to output and advance idx.
981    ///
982    /// If there's no output, just advance idx.
983    pub fn next_glyphs(&mut self, n: usize) {
984        if self.have_output {
985            if self.have_separate_output || self.out_len != self.idx {
986                if !self.ensure(self.out_len + n) {
987                    return;
988                }
989
990                for i in 0..n {
991                    self.set_out_info(self.out_len + i, self.info[self.idx + i]);
992                }
993            }
994
995            self.out_len += n;
996        }
997
998        self.idx += n;
999    }
1000
1001    /// Advance idx without copying to output.
1002    pub fn skip_glyph(&mut self) {
1003        self.idx += 1;
1004    }
1005
1006    pub fn reset_masks(&mut self, mask: hb_mask_t) {
1007        for info in &mut self.info[..self.len] {
1008            info.mask = mask;
1009        }
1010    }
1011
1012    pub fn set_masks(
1013        &mut self,
1014        mut value: hb_mask_t,
1015        mask: hb_mask_t,
1016        cluster_start: u32,
1017        cluster_end: u32,
1018    ) {
1019        if mask == 0 {
1020            return;
1021        }
1022
1023        let not_mask = !mask;
1024        value &= mask;
1025
1026        self.max_ops -= self.len as i32;
1027        if self.max_ops < 0 {
1028            self.successful = false;
1029        }
1030
1031        if cluster_start == 0 && cluster_end == u32::MAX {
1032            for info in &mut self.info[..self.len] {
1033                info.mask = (info.mask & not_mask) | value;
1034            }
1035
1036            return;
1037        }
1038
1039        for info in &mut self.info[..self.len] {
1040            if cluster_start <= info.cluster && info.cluster < cluster_end {
1041                info.mask = (info.mask & not_mask) | value;
1042            }
1043        }
1044    }
1045
1046    #[inline(always)]
1047    pub fn merge_clusters(&mut self, start: usize, end: usize) {
1048        if end - start < 2 {
1049            return;
1050        }
1051
1052        if !BufferClusterLevel::new(self.cluster_level).is_monotone() {
1053            self.unsafe_to_break(Some(start), Some(end));
1054            return;
1055        }
1056
1057        self.merge_clusters_impl(start, end);
1058    }
1059
1060    fn merge_clusters_impl(&mut self, mut start: usize, mut end: usize) {
1061        self.max_ops -= (end - start) as i32;
1062        if self.max_ops < 0 {
1063            self.successful = false;
1064        }
1065
1066        let cluster = self.info[start..end]
1067            .iter()
1068            .map(|info| info.cluster)
1069            .min()
1070            .unwrap();
1071
1072        // Extend end
1073        if cluster != self.info[end - 1].cluster {
1074            while end < self.len && self.info[end - 1].cluster == self.info[end].cluster {
1075                end += 1;
1076            }
1077        }
1078
1079        // Extend start
1080        if cluster != self.info[start].cluster {
1081            while self.idx < start && self.info[start - 1].cluster == self.info[start].cluster {
1082                start -= 1;
1083            }
1084        }
1085
1086        // If we hit the start of buffer, continue in out-buffer.
1087        if self.idx == start && self.info[start].cluster != cluster {
1088            let mut i = self.out_len;
1089            while i != 0 && self.out_info()[i - 1].cluster == self.info[start].cluster {
1090                Self::set_cluster(&mut self.out_info_mut()[i - 1], cluster, 0);
1091                i -= 1;
1092            }
1093        }
1094
1095        for info in &mut self.info[start..end] {
1096            Self::set_cluster(info, cluster, 0);
1097        }
1098    }
1099
1100    pub fn merge_grapheme_clusters(&mut self, start: usize, end: usize) {
1101        if end - start < 2 {
1102            return;
1103        }
1104
1105        if !BufferClusterLevel::new(self.cluster_level).is_graphemes() {
1106            self.unsafe_to_break(Some(start), Some(end));
1107            return;
1108        }
1109
1110        self.merge_clusters_impl(start, end);
1111    }
1112
1113    pub fn merge_out_clusters(&mut self, start: usize, end: usize) {
1114        if end - start < 2 {
1115            return;
1116        }
1117
1118        if !BufferClusterLevel::new(self.cluster_level).is_monotone() {
1119            return;
1120        }
1121
1122        self.merge_out_clusters_impl(start, end);
1123    }
1124
1125    pub fn merge_out_grapheme_clusters(&mut self, start: usize, end: usize) {
1126        if end - start < 2 {
1127            return;
1128        }
1129
1130        if !BufferClusterLevel::new(self.cluster_level).is_graphemes() {
1131            return;
1132        }
1133
1134        self.merge_out_clusters_impl(start, end);
1135    }
1136
1137    fn merge_out_clusters_impl(&mut self, mut start: usize, mut end: usize) {
1138        self.max_ops -= (end - start) as i32;
1139        if self.max_ops < 0 {
1140            self.successful = false;
1141        }
1142
1143        let cluster = self.out_info()[start..end]
1144            .iter()
1145            .map(|info| info.cluster)
1146            .min()
1147            .unwrap();
1148
1149        // Extend start
1150        while start != 0 && self.out_info()[start - 1].cluster == self.out_info()[start].cluster {
1151            start -= 1;
1152        }
1153
1154        // Extend end
1155        while end < self.out_len && self.out_info()[end - 1].cluster == self.out_info()[end].cluster
1156        {
1157            end += 1;
1158        }
1159
1160        // If we hit the start of buffer, continue in out-buffer.
1161        if end == self.out_len {
1162            let mut i = self.idx;
1163            while i < self.len && self.info[i].cluster == self.out_info()[end - 1].cluster {
1164                Self::set_cluster(&mut self.info[i], cluster, 0);
1165                i += 1;
1166            }
1167        }
1168
1169        for info in &mut self.out_info_mut()[start..end] {
1170            Self::set_cluster(info, cluster, 0);
1171        }
1172    }
1173
1174    /// Merge clusters for deleting current glyph, and skip it.
1175    pub fn delete_glyph(&mut self) {
1176        let cluster = self.info[self.idx].cluster;
1177
1178        if (self.idx + 1 < self.len && cluster == self.info[self.idx + 1].cluster)
1179            || (self.out_len != 0 && cluster == self.out_info()[self.out_len - 1].cluster)
1180        {
1181            // Cluster survives; do nothing.
1182            self.skip_glyph();
1183            return;
1184        }
1185
1186        if self.out_len != 0 {
1187            // Merge cluster backward.
1188            if cluster < self.out_info()[self.out_len - 1].cluster {
1189                let mask = self.info[self.idx].mask;
1190                let old_cluster = self.out_info()[self.out_len - 1].cluster;
1191
1192                let mut i = self.out_len;
1193                while i != 0 && self.out_info()[i - 1].cluster == old_cluster {
1194                    Self::set_cluster(&mut self.out_info_mut()[i - 1], cluster, mask);
1195                    i -= 1;
1196                }
1197            }
1198
1199            self.skip_glyph();
1200            return;
1201        }
1202
1203        if self.idx + 1 < self.len {
1204            // Merge cluster forward.
1205            self.merge_clusters(self.idx, self.idx + 2);
1206        }
1207
1208        self.skip_glyph();
1209    }
1210
1211    pub fn delete_glyphs_inplace(&mut self, filter: impl Fn(&GlyphInfo) -> bool) {
1212        // Merge clusters and delete filtered glyphs.
1213        // NOTE! We can't use out-buffer as we have positioning data.
1214        let mut j = 0;
1215
1216        for i in 0..self.len {
1217            if filter(&self.info[i]) {
1218                // Merge clusters.
1219                // Same logic as delete_glyph(), but for in-place removal
1220
1221                let cluster = self.info[i].cluster;
1222                if i + 1 < self.len && cluster == self.info[i + 1].cluster {
1223                    // Cluster survives; do nothing.
1224                    continue;
1225                }
1226
1227                if j != 0 {
1228                    // Merge cluster backward.
1229                    if cluster < self.info[j - 1].cluster {
1230                        let mask = self.info[i].mask;
1231                        let old_cluster = self.info[j - 1].cluster;
1232
1233                        let mut k = j;
1234                        while k > 0 && self.info[k - 1].cluster == old_cluster {
1235                            Self::set_cluster(&mut self.info[k - 1], cluster, mask);
1236                            k -= 1;
1237                        }
1238                    }
1239                    continue;
1240                }
1241
1242                if i + 1 < self.len {
1243                    // Merge cluster forward.
1244                    self.merge_clusters(i, i + 2);
1245                }
1246
1247                continue;
1248            }
1249
1250            if j != i {
1251                self.info[j] = self.info[i];
1252                self.pos[j] = self.pos[i];
1253            }
1254
1255            j += 1;
1256        }
1257
1258        self.len = j;
1259    }
1260
1261    pub fn unsafe_to_break(&mut self, start: Option<usize>, end: Option<usize>) {
1262        self.set_glyph_flags(
1263            GlyphFlags::UNSAFE_TO_BREAK | GlyphFlags::UNSAFE_TO_CONCAT,
1264            start,
1265            end,
1266            Some(true),
1267            None,
1268        );
1269    }
1270
1271    pub fn safe_to_insert_tatweel(&mut self, start: Option<usize>, end: Option<usize>) {
1272        if !self
1273            .flags
1274            .contains(BufferFlags::PRODUCE_SAFE_TO_INSERT_TATWEEL)
1275        {
1276            self.unsafe_to_break(start, end);
1277            return;
1278        }
1279
1280        self.set_glyph_flags(
1281            GlyphFlags::SAFE_TO_INSERT_TATWEEL,
1282            start,
1283            end,
1284            Some(true),
1285            None,
1286        );
1287    }
1288
1289    fn _set_glyph_flags_impl(
1290        &mut self,
1291        mask: hb_mask_t,
1292        start: usize,
1293        end: usize,
1294        interior: bool,
1295        from_out_buffer: bool,
1296    ) {
1297        if !from_out_buffer || !self.have_output {
1298            if !interior {
1299                for info in &mut self.info[start..end] {
1300                    info.mask |= mask;
1301                }
1302            } else {
1303                let cluster = self._infos_find_min_cluster(&self.info, start, end, None);
1304                self._infos_set_glyph_flags(false, start, end, cluster, mask);
1305            }
1306        } else {
1307            debug_assert!(start <= self.out_len);
1308            debug_assert!(self.idx <= end);
1309
1310            if !interior {
1311                let range_end = self.out_len;
1312                for info in &mut self.out_info_mut()[start..range_end] {
1313                    info.mask |= mask;
1314                }
1315
1316                for info in &mut self.info[self.idx..end] {
1317                    info.mask |= mask;
1318                }
1319            } else {
1320                let mut cluster = self._infos_find_min_cluster(&self.info, self.idx, end, None);
1321                cluster = self._infos_find_min_cluster(
1322                    self.out_info(),
1323                    start,
1324                    self.out_len,
1325                    Some(cluster),
1326                );
1327
1328                let out_len = self.out_len;
1329                self._infos_set_glyph_flags(true, start, out_len, cluster, mask);
1330                self._infos_set_glyph_flags(false, self.idx, end, cluster, mask);
1331            }
1332        }
1333    }
1334
1335    /// Adds glyph flags in mask to infos with clusters between start and end.
1336    /// The start index will be from out-buffer if from_out_buffer is true.
1337    /// If interior is true, then the cluster having the minimum value is skipped. */
1338    fn set_glyph_flags(
1339        &mut self,
1340        flags: GlyphFlags,
1341        start: Option<usize>,
1342        end: Option<usize>,
1343        interior: Option<bool>,
1344        from_out_buffer: Option<bool>,
1345    ) {
1346        // If the range is not specified, ie. whole buffer, allow it.
1347        // But if range *is* specified, reject if range is too large.
1348        if let (Some(start), Some(end)) = (start, end) {
1349            if end.wrapping_sub(start) > 255 {
1350                return;
1351            }
1352        }
1353
1354        let start = start.unwrap_or(0);
1355        let end = min(end.unwrap_or(self.len), self.len);
1356        let interior = interior.unwrap_or(false);
1357        let from_out_buffer = from_out_buffer.unwrap_or(false);
1358
1359        if interior && !from_out_buffer && end - start < 2 {
1360            return;
1361        }
1362
1363        self._set_glyph_flags_impl(flags.0, start, end, interior, from_out_buffer);
1364    }
1365
1366    pub fn unsafe_to_concat(&mut self, start: Option<usize>, end: Option<usize>) {
1367        if !self.flags.contains(BufferFlags::PRODUCE_UNSAFE_TO_CONCAT) {
1368            return;
1369        }
1370
1371        self.set_glyph_flags(GlyphFlags::UNSAFE_TO_CONCAT, start, end, Some(false), None);
1372    }
1373
1374    pub fn unsafe_to_break_from_outbuffer(&mut self, start: Option<usize>, end: Option<usize>) {
1375        self.set_glyph_flags(
1376            GlyphFlags::UNSAFE_TO_BREAK | GlyphFlags::UNSAFE_TO_CONCAT,
1377            start,
1378            end,
1379            Some(true),
1380            Some(true),
1381        );
1382    }
1383
1384    pub fn unsafe_to_concat_from_outbuffer(&mut self, start: Option<usize>, end: Option<usize>) {
1385        if !self.flags.contains(BufferFlags::PRODUCE_UNSAFE_TO_CONCAT) {
1386            return;
1387        }
1388
1389        self.set_glyph_flags(
1390            GlyphFlags::UNSAFE_TO_CONCAT,
1391            start,
1392            end,
1393            Some(false),
1394            Some(true),
1395        );
1396    }
1397
1398    pub fn move_to(&mut self, i: usize) -> bool {
1399        if !self.have_output {
1400            debug_assert!(i <= self.len);
1401            self.idx = i;
1402            return true;
1403        }
1404
1405        if !self.successful {
1406            return false;
1407        }
1408
1409        debug_assert!(i <= self.out_len + (self.len - self.idx));
1410
1411        if self.out_len < i {
1412            let count = i - self.out_len;
1413            if !self.make_room_for(count, count) {
1414                return false;
1415            }
1416
1417            for j in 0..count {
1418                self.set_out_info(self.out_len + j, self.info[self.idx + j]);
1419            }
1420
1421            self.idx += count;
1422            self.out_len += count;
1423        } else if self.out_len > i {
1424            // Tricky part: rewinding...
1425            let count = self.out_len - i;
1426
1427            // This will blow in our face if memory allocation fails later
1428            // in this same lookup...
1429            //
1430            // We used to shift with extra 32 items.
1431            // But that would leave empty slots in the buffer in case of allocation
1432            // failures.  See comments in shift_forward().  This can cause O(N^2)
1433            // behavior more severely than adding 32 empty slots can...
1434            if self.idx < count && !self.shift_forward(count - self.idx) {
1435                return false;
1436            }
1437
1438            debug_assert!(self.idx >= count);
1439
1440            self.idx -= count;
1441            self.out_len -= count;
1442
1443            for j in 0..count {
1444                self.info[self.idx + j] = self.out_info()[self.out_len + j];
1445            }
1446        }
1447
1448        true
1449    }
1450
1451    #[must_use]
1452    #[inline(always)]
1453    pub fn ensure(&mut self, size: usize) -> bool {
1454        if size <= self.info.len() {
1455            true
1456        } else {
1457            self.enlarge(size)
1458        }
1459    }
1460
1461    #[must_use]
1462    fn enlarge(&mut self, size: usize) -> bool {
1463        if size > self.max_len {
1464            self.successful = false;
1465            return false;
1466        }
1467
1468        self.info.resize(size, GlyphInfo::default());
1469        self.pos.resize(size, GlyphPosition::default());
1470        true
1471    }
1472
1473    #[must_use]
1474    fn make_room_for(&mut self, num_in: usize, num_out: usize) -> bool {
1475        if !self.ensure(self.out_len + num_out) {
1476            return false;
1477        }
1478
1479        if !self.have_separate_output && self.out_len + num_out > self.idx + num_in {
1480            debug_assert!(self.have_output);
1481
1482            self.have_separate_output = true;
1483            for i in 0..self.out_len {
1484                self.set_out_info(i, self.info[i]);
1485            }
1486        }
1487
1488        true
1489    }
1490
1491    fn shift_forward(&mut self, count: usize) -> bool {
1492        debug_assert!(self.have_output);
1493        if !self.ensure(self.len + count) {
1494            return false;
1495        }
1496
1497        self.max_ops -= (self.len - self.idx) as i32;
1498        if self.max_ops < 0 {
1499            self.successful = false;
1500            return false;
1501        }
1502
1503        for i in (0..(self.len - self.idx)).rev() {
1504            self.info[self.idx + count + i] = self.info[self.idx + i];
1505        }
1506
1507        if self.idx + count > self.len {
1508            for info in &mut self.info[self.len..self.idx + count] {
1509                *info = GlyphInfo::default();
1510            }
1511        }
1512
1513        self.len += count;
1514        self.idx += count;
1515
1516        true
1517    }
1518
1519    fn clear_context(&mut self, side: usize) {
1520        self.context_len[side] = 0;
1521    }
1522
1523    pub fn sort(&mut self, start: usize, end: usize, cmp: impl Fn(&GlyphInfo, &GlyphInfo) -> bool) {
1524        debug_assert!(!self.have_positions);
1525
1526        for i in start + 1..end {
1527            let mut j = i;
1528            while j > start && cmp(&self.info[j - 1], &self.info[i]) {
1529                j -= 1;
1530            }
1531
1532            if i == j {
1533                continue;
1534            }
1535
1536            // Move item i to occupy place for item j, shift what's in between.
1537            self.merge_clusters(j, i + 1);
1538
1539            {
1540                let t = self.info[i];
1541                for idx in (0..i - j).rev() {
1542                    self.info[idx + j + 1] = self.info[idx + j];
1543                }
1544
1545                self.info[j] = t;
1546            }
1547        }
1548    }
1549
1550    pub fn set_cluster(info: &mut GlyphInfo, cluster: u32, mask: hb_mask_t) {
1551        if info.cluster != cluster {
1552            info.mask = (info.mask & !GlyphFlags::DEFINED_BITS) | (mask & GlyphFlags::DEFINED_BITS);
1553        }
1554
1555        info.cluster = cluster;
1556    }
1557
1558    // Called around shape()
1559    pub(crate) fn enter(&mut self) {
1560        self.serial = 0;
1561        self.scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
1562
1563        if let Some(len) = self.len.checked_mul(hb_buffer_t::MAX_LEN_FACTOR) {
1564            self.max_len = len.max(hb_buffer_t::MAX_LEN_MIN);
1565        }
1566
1567        if let Ok(len) = i32::try_from(self.len) {
1568            if let Some(ops) = len.checked_mul(hb_buffer_t::MAX_OPS_FACTOR) {
1569                self.max_ops = ops.max(hb_buffer_t::MAX_OPS_MIN);
1570            }
1571        }
1572    }
1573
1574    // Called around shape()
1575    pub(crate) fn leave(&mut self) {
1576        self.max_len = hb_buffer_t::MAX_LEN_DEFAULT;
1577        self.max_ops = hb_buffer_t::MAX_OPS_DEFAULT;
1578        self.serial = 0;
1579    }
1580
1581    fn _infos_find_min_cluster(
1582        &self,
1583        info: &[GlyphInfo],
1584        start: usize,
1585        end: usize,
1586        cluster: Option<u32>,
1587    ) -> u32 {
1588        let mut cluster = cluster.unwrap_or(u32::MAX);
1589
1590        if start == end {
1591            return cluster;
1592        }
1593
1594        if self.cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS {
1595            for glyph_info in &info[start..end] {
1596                cluster = min(cluster, glyph_info.cluster);
1597            }
1598        }
1599
1600        cluster.min(info[start].cluster.min(info[end - 1].cluster))
1601    }
1602
1603    #[inline(always)]
1604    fn _infos_set_glyph_flags(
1605        &mut self,
1606        out_info: bool,
1607        start: usize,
1608        end: usize,
1609        cluster: u32,
1610        mask: hb_mask_t,
1611    ) {
1612        if start == end {
1613            return;
1614        }
1615
1616        let cluster_level = self.cluster_level;
1617
1618        let infos = if out_info {
1619            self.out_info_mut()
1620        } else {
1621            self.info.as_mut_slice()
1622        };
1623
1624        let cluster_first = infos[start].cluster;
1625        let cluster_last = infos[end - 1].cluster;
1626
1627        if cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS
1628            || (cluster != cluster_first && cluster != cluster_last)
1629        {
1630            for info in &mut infos[start..end] {
1631                if info.cluster != cluster {
1632                    info.mask |= mask;
1633                }
1634            }
1635
1636            return;
1637        }
1638
1639        // Monotone clusters
1640        if cluster == cluster_first {
1641            let mut i = end;
1642            while start < i && infos[i - 1].cluster != cluster_first {
1643                if cluster != infos[i - 1].cluster {
1644                    infos[i - 1].mask |= mask;
1645                }
1646
1647                i -= 1;
1648            }
1649        } else {
1650            let mut i = start;
1651            while i < end && infos[i].cluster != cluster_last {
1652                if cluster != infos[i].cluster {
1653                    infos[i].mask |= mask;
1654                }
1655
1656                i += 1;
1657            }
1658        }
1659    }
1660
1661    /// Checks that buffer contains no elements.
1662    pub fn is_empty(&self) -> bool {
1663        self.len == 0
1664    }
1665
1666    fn push_str(&mut self, text: &str) {
1667        if !self.ensure(self.len + text.chars().count()) {
1668            return;
1669        }
1670
1671        for (i, c) in text.char_indices() {
1672            self.info[self.len] = GlyphInfo {
1673                glyph_id: c as u32,
1674                cluster: i as u32,
1675                ..GlyphInfo::default()
1676            };
1677            self.len += 1;
1678        }
1679    }
1680
1681    fn set_pre_context(&mut self, text: &str) {
1682        self.clear_context(0);
1683        for (i, c) in text.chars().rev().enumerate().take(CONTEXT_LENGTH) {
1684            self.context[0][i] = c as Codepoint;
1685            self.context_len[0] += 1;
1686        }
1687    }
1688
1689    fn set_pre_context_codepoints(&mut self, codepoints: &[u32]) {
1690        self.clear_context(0);
1691        for (i, &c) in codepoints.iter().take(CONTEXT_LENGTH).enumerate() {
1692            self.context[0][i] = c;
1693            self.context_len[0] += 1;
1694        }
1695    }
1696
1697    fn set_post_context(&mut self, text: &str) {
1698        self.clear_context(1);
1699        for (i, c) in text.chars().enumerate().take(CONTEXT_LENGTH) {
1700            self.context[1][i] = c as Codepoint;
1701            self.context_len[1] += 1;
1702        }
1703    }
1704
1705    fn set_post_context_codepoints(&mut self, codepoints: &[u32]) {
1706        self.clear_context(1);
1707        for (i, &c) in codepoints.iter().take(CONTEXT_LENGTH).enumerate() {
1708            self.context[1][i] = c;
1709            self.context_len[1] += 1;
1710        }
1711    }
1712
1713    pub fn next_syllable(&self, mut start: usize) -> usize {
1714        if start >= self.len {
1715            return start;
1716        }
1717
1718        let syllable = self.info[start].syllable();
1719        start += 1;
1720        while start < self.len && syllable == self.info[start].syllable() {
1721            start += 1;
1722        }
1723
1724        start
1725    }
1726
1727    #[inline]
1728    pub fn allocate_lig_id(&mut self) -> u8 {
1729        let mut lig_id = self.next_serial() & 0x07;
1730
1731        if lig_id == 0 {
1732            lig_id = self.allocate_lig_id();
1733        }
1734
1735        lig_id
1736    }
1737}
1738
1739pub(crate) fn _cluster_group_func(a: &GlyphInfo, b: &GlyphInfo) -> bool {
1740    a.cluster == b.cluster
1741}
1742
1743// TODO: to iter if possible
1744
1745macro_rules! foreach_cluster {
1746    ($buffer:expr, $start:ident, $end:ident, $($body:tt)*) => {
1747        foreach_group!($buffer, $start, $end, $crate::hb::buffer::_cluster_group_func, $($body)*)
1748    };
1749}
1750
1751macro_rules! foreach_group {
1752    ($buffer:expr, $start:ident, $end:ident, $group_func:expr, $($body:tt)*) => {{
1753        let count = $buffer.len;
1754        let mut $start = 0;
1755        let mut $end = if count > 0 { $buffer.group_end(0, $group_func) } else { 0 };
1756
1757        while $start < count {
1758            $($body)*;
1759            $start = $end;
1760            $end = $buffer.group_end($start, $group_func);
1761        }
1762    }};
1763}
1764
1765macro_rules! foreach_syllable {
1766    ($buffer:expr, $start:ident, $end:ident, $($body:tt)*) => {{
1767        let mut $start = 0;
1768        let mut $end = $buffer.next_syllable(0);
1769        while $start < $buffer.len {
1770            $($body)*;
1771            $start = $end;
1772            $end = $buffer.next_syllable($start);
1773        }
1774    }};
1775}
1776
1777macro_rules! foreach_grapheme {
1778    ($buffer:expr, $start:ident, $end:ident, $($body:tt)*) => {
1779        foreach_group!($buffer, $start, $end, $crate::hb::ot_layout::_hb_grapheme_group_func, $($body)*)
1780    };
1781}
1782
1783bitflags::bitflags! {
1784    #[derive(Default, Debug, Clone, Copy)]
1785    pub struct UnicodeProps: u16 {
1786        const GENERAL_CATEGORY  = 0x001F;
1787        const IGNORABLE         = 0x0020;
1788        // MONGOLIAN FREE VARIATION SELECTOR 1..4, or TAG characters, or CGJ sometimes
1789        const HIDDEN            = 0x0040;
1790        const CONTINUATION      = 0x0080;
1791
1792        // If GEN_CAT=FORMAT, top byte masks:
1793        const CF_ZWJ            = 0x0100;
1794        const CF_ZWNJ           = 0x0200;
1795        const CF_VS             = 0x0400;
1796        const CF_AAT_DELETED    = 0x0800;
1797    }
1798}
1799
1800bitflags::bitflags! {
1801    #[derive(Default, Debug, Clone, Copy)]
1802    pub struct GlyphPropsFlags: u16 {
1803        // The following three match LookupFlags::Ignore* numbers.
1804        const BASE_GLYPH    = 0x02;
1805        const LIGATURE      = 0x04;
1806        const MARK          = 0x08;
1807        const CLASS_MASK    = Self::BASE_GLYPH.bits() | Self::LIGATURE.bits() | Self::MARK.bits();
1808
1809        // The following are used internally; not derived from GDEF.
1810        const SUBSTITUTED   = 0x10;
1811        const LIGATED       = 0x20;
1812        const MULTIPLIED    = 0x40;
1813
1814        const PRESERVE      = Self::SUBSTITUTED.bits() | Self::LIGATED.bits() | Self::MULTIPLIED.bits();
1815    }
1816}
1817
1818pub type hb_buffer_scratch_flags_t = u32;
1819pub const HB_BUFFER_SCRATCH_FLAG_DEFAULT: u32 = 0x0000_0000;
1820pub const HB_BUFFER_SCRATCH_FLAG_HAS_FRACTION_SLASH: u32 = 0x0000_0001;
1821pub const HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES: u32 = 0x0000_0002;
1822pub const HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK: u32 = 0x0000_0004;
1823pub const HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT: u32 = 0x0000_0008;
1824pub const HB_BUFFER_SCRATCH_FLAG_HAS_CGJ: u32 = 0x0000_0010;
1825pub const HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE: u32 = 0x0000_0020;
1826pub const HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK: u32 = 0x0000_0040;
1827pub const HB_BUFFER_SCRATCH_FLAG_HAS_CONTINUATIONS: u32 = 0x0000_0080;
1828
1829/* Reserved for shapers' internal use. */
1830pub const HB_BUFFER_SCRATCH_FLAG_SHAPER0: u32 = 0x0100_0000;
1831// pub const HB_BUFFER_SCRATCH_FLAG_SHAPER1: u32 = 0x02000000;
1832// pub const HB_BUFFER_SCRATCH_FLAG_SHAPER2: u32 = 0x04000000;
1833// pub const HB_BUFFER_SCRATCH_FLAG_SHAPER3: u32 = 0x08000000;
1834
1835/// A buffer that contains an input string ready for shaping.
1836pub struct UnicodeBuffer(pub(crate) hb_buffer_t);
1837
1838impl UnicodeBuffer {
1839    /// Create a new `UnicodeBuffer`.
1840    #[inline]
1841    pub fn new() -> UnicodeBuffer {
1842        UnicodeBuffer(hb_buffer_t::new())
1843    }
1844
1845    /// Returns the length of the data of the buffer.
1846    ///
1847    /// This corresponds to the number of unicode codepoints contained in the
1848    /// buffer.
1849    #[inline]
1850    pub fn len(&self) -> usize {
1851        self.0.len
1852    }
1853
1854    /// Ensures that the buffer can hold at least `size` codepoints.
1855    pub fn reserve(&mut self, size: usize) -> bool {
1856        self.0.ensure(size)
1857    }
1858
1859    /// Returns `true` if the buffer contains no elements.
1860    #[inline]
1861    pub fn is_empty(&self) -> bool {
1862        self.0.is_empty()
1863    }
1864
1865    /// Pushes a string to a buffer.
1866    #[inline]
1867    pub fn push_str(&mut self, str: &str) {
1868        self.0.push_str(str);
1869    }
1870
1871    /// Sets the pre-context for this buffer.
1872    #[inline]
1873    pub fn set_pre_context(&mut self, str: &str) {
1874        self.0.set_pre_context(str);
1875    }
1876
1877    /// Sets the pre-context for this buffer from codepoints.
1878    ///
1879    /// The input is expected to be the Unicode codepoints in reverse order.
1880    /// This matches HarfBuzz's internal storage of pre-context, and serves
1881    /// as a low-overhead method to pass pre-context from HarfBuzz-HarfRust.
1882    #[inline]
1883    pub fn set_pre_context_codepoints(&mut self, codepoints: &[u32]) {
1884        self.0.set_pre_context_codepoints(codepoints);
1885    }
1886
1887    /// Sets the post-context for this buffer.
1888    #[inline]
1889    pub fn set_post_context(&mut self, str: &str) {
1890        self.0.set_post_context(str);
1891    }
1892
1893    /// Sets the post-context for this buffer from codepoints.
1894    #[inline]
1895    pub fn set_post_context_codepoints(&mut self, codepoints: &[u32]) {
1896        self.0.set_post_context_codepoints(codepoints);
1897    }
1898
1899    /// Appends glyph infos to a buffer.
1900    #[inline]
1901    pub fn push_glyph_infos(&mut self, infos: &[GlyphInfo]) -> bool {
1902        let len = infos.len();
1903        if !self.0.ensure(self.0.len + len) {
1904            return false;
1905        }
1906
1907        self.0.info[self.0.len..self.0.len + len].copy_from_slice(infos);
1908        self.0.len += len;
1909        true
1910    }
1911
1912    /// Appends a character to a buffer with the given cluster value.
1913    #[inline]
1914    pub fn add(&mut self, codepoint: char, cluster: u32) {
1915        self.0.add(codepoint as u32, cluster);
1916        self.0.context_len[1] = 0;
1917    }
1918
1919    /// Set the text direction of the `Buffer`'s contents.
1920    #[inline]
1921    pub fn set_direction(&mut self, direction: Direction) {
1922        self.0.direction = direction;
1923    }
1924
1925    /// Returns the `Buffer`'s text direction.
1926    #[inline]
1927    pub fn direction(&self) -> Direction {
1928        self.0.direction
1929    }
1930
1931    /// Set the script from an ISO15924 tag.
1932    #[inline]
1933    pub fn set_script(&mut self, script: Script) {
1934        self.0.script = Some(script);
1935    }
1936
1937    /// Get the ISO15924 script tag.
1938    pub fn script(&self) -> Script {
1939        self.0.script.unwrap_or(script::UNKNOWN)
1940    }
1941
1942    /// Set the buffer language.
1943    #[inline]
1944    pub fn set_language(&mut self, lang: Language) {
1945        self.0.language = Some(lang);
1946    }
1947
1948    /// Set the glyph value to replace not-found variation-selector characters with.
1949    #[inline]
1950    pub fn set_not_found_variation_selector_glyph(&mut self, glyph: u32) {
1951        self.0.not_found_variation_selector = Some(glyph);
1952    }
1953
1954    /// Get the buffer language.
1955    #[inline]
1956    pub fn language(&self) -> Option<Language> {
1957        self.0.language.clone()
1958    }
1959
1960    /// Guess the segment properties (direction, language, script) for the
1961    /// current buffer.
1962    #[inline]
1963    pub fn guess_segment_properties(&mut self) {
1964        self.0.guess_segment_properties();
1965    }
1966
1967    /// Set the flags for this buffer.
1968    #[inline]
1969    pub fn set_flags(&mut self, flags: BufferFlags) {
1970        self.0.flags = flags;
1971    }
1972
1973    /// Get the flags for this buffer.
1974    #[inline]
1975    pub fn flags(&self) -> BufferFlags {
1976        self.0.flags
1977    }
1978
1979    /// Set the cluster level of the buffer.
1980    #[inline]
1981    pub fn set_cluster_level(&mut self, cluster_level: BufferClusterLevel) {
1982        self.0.cluster_level = match cluster_level {
1983            BufferClusterLevel::MonotoneGraphemes => HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES,
1984            BufferClusterLevel::MonotoneCharacters => HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS,
1985            BufferClusterLevel::Characters => HB_BUFFER_CLUSTER_LEVEL_CHARACTERS,
1986            BufferClusterLevel::Graphemes => HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES,
1987        }
1988    }
1989
1990    /// Retrieve the cluster level of the buffer.
1991    #[inline]
1992    pub fn cluster_level(&self) -> BufferClusterLevel {
1993        match self.0.cluster_level {
1994            HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES => BufferClusterLevel::MonotoneGraphemes,
1995            HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS => BufferClusterLevel::MonotoneCharacters,
1996            HB_BUFFER_CLUSTER_LEVEL_CHARACTERS => BufferClusterLevel::Characters,
1997            HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES => BufferClusterLevel::Graphemes,
1998            _ => BufferClusterLevel::MonotoneGraphemes,
1999        }
2000    }
2001
2002    /// Resets clusters.
2003    #[inline]
2004    pub fn reset_clusters(&mut self) {
2005        self.0.reset_clusters();
2006    }
2007
2008    /// Clear the contents of the buffer.
2009    #[inline]
2010    pub fn clear(&mut self) {
2011        self.0.clear();
2012    }
2013}
2014
2015impl core::fmt::Debug for UnicodeBuffer {
2016    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2017        fmt.debug_struct("UnicodeBuffer")
2018            .field("direction", &self.direction())
2019            .field("language", &self.language())
2020            .field("script", &self.script())
2021            .field("cluster_level", &self.cluster_level())
2022            .finish()
2023    }
2024}
2025
2026impl Default for UnicodeBuffer {
2027    fn default() -> UnicodeBuffer {
2028        UnicodeBuffer::new()
2029    }
2030}
2031
2032/// A buffer that contains the results of the shaping process.
2033pub struct GlyphBuffer(pub(crate) hb_buffer_t);
2034
2035impl GlyphBuffer {
2036    /// Returns the length of the data of the buffer.
2037    ///
2038    /// When called before shaping this is the number of unicode codepoints
2039    /// contained in the buffer. When called after shaping it returns the number
2040    /// of glyphs stored.
2041    #[inline]
2042    pub fn len(&self) -> usize {
2043        self.0.len
2044    }
2045
2046    /// Returns `true` if the buffer contains no elements.
2047    #[inline]
2048    pub fn is_empty(&self) -> bool {
2049        self.0.is_empty()
2050    }
2051
2052    /// Get the glyph infos.
2053    #[inline]
2054    pub fn glyph_infos(&self) -> &[GlyphInfo] {
2055        &self.0.info[0..self.0.len]
2056    }
2057
2058    /// Get the glyph positions.
2059    #[inline]
2060    pub fn glyph_positions(&self) -> &[GlyphPosition] {
2061        &self.0.pos[0..self.0.len]
2062    }
2063
2064    /// Clears the content of the glyph buffer and returns an empty
2065    /// `UnicodeBuffer` reusing the existing allocation.
2066    #[inline]
2067    pub fn clear(mut self) -> UnicodeBuffer {
2068        self.0.clear();
2069        UnicodeBuffer(self.0)
2070    }
2071
2072    /// Converts the glyph buffer content into a string.
2073    pub fn serialize(&self, font: &impl SerializerFont, flags: SerializeFlags) -> String {
2074        self.serialize_impl(font, flags).unwrap_or_default()
2075    }
2076
2077    pub(crate) fn serialize_impl(
2078        &self,
2079        font: &impl SerializerFont,
2080        flags: SerializeFlags,
2081    ) -> Result<String, core::fmt::Error> {
2082        use core::fmt::Write;
2083
2084        let mut s = String::with_capacity(64);
2085
2086        let info = self.glyph_infos();
2087        let pos = self.glyph_positions();
2088        let mut x = 0;
2089        let mut y = 0;
2090        let names = font.glyph_names();
2091        let glyph_metrics = if flags.contains(SerializeFlags::GLYPH_EXTENTS) {
2092            Some(font.glyph_metrics())
2093        } else {
2094            None
2095        };
2096        for (info, pos) in info.iter().zip(pos) {
2097            s.push(if s.is_empty() { '[' } else { '|' });
2098
2099            if !flags.contains(SerializeFlags::NO_GLYPH_NAMES) {
2100                match names.get(info.as_glyph().to_u32()) {
2101                    Some(name) => s.push_str(name),
2102                    None => write!(&mut s, "gid{}", info.glyph_id)?,
2103                }
2104            } else {
2105                write!(&mut s, "{}", info.glyph_id)?;
2106            }
2107
2108            if !flags.contains(SerializeFlags::NO_CLUSTERS) {
2109                write!(&mut s, "={}", info.cluster)?;
2110            }
2111
2112            if !flags.contains(SerializeFlags::NO_POSITIONS) {
2113                if x + pos.x_offset != 0 || y + pos.y_offset != 0 {
2114                    write!(&mut s, "@{},{}", x + pos.x_offset, y + pos.y_offset)?;
2115                }
2116
2117                if !flags.contains(SerializeFlags::NO_ADVANCES) {
2118                    write!(&mut s, "+{}", pos.x_advance)?;
2119                    if pos.y_advance != 0 {
2120                        write!(&mut s, ",{}", pos.y_advance)?;
2121                    }
2122                }
2123            }
2124
2125            if flags.contains(SerializeFlags::GLYPH_FLAGS) {
2126                if info.mask & GlyphFlags::DEFINED_BITS != 0 {
2127                    write!(&mut s, "#{:X}", info.mask & GlyphFlags::DEFINED_BITS)?;
2128                }
2129            }
2130
2131            if flags.contains(SerializeFlags::GLYPH_EXTENTS) {
2132                let extents = glyph_metrics
2133                    .as_ref()
2134                    .unwrap()
2135                    .extents(info.as_glyph(), font.coords())
2136                    .unwrap_or_default();
2137                write!(
2138                    &mut s,
2139                    "<{},{},{},{}>",
2140                    extents.x_bearing, extents.y_bearing, extents.width, extents.height
2141                )?;
2142            }
2143
2144            if flags.contains(SerializeFlags::NO_ADVANCES) {
2145                x += pos.x_advance;
2146                y += pos.y_advance;
2147            }
2148        }
2149
2150        if !s.is_empty() {
2151            s.push(']');
2152        }
2153
2154        Ok(s)
2155    }
2156}
2157
2158pub trait SerializerFont {
2159    fn coords(&self) -> &[F2Dot14];
2160    fn glyph_names(&self) -> GlyphNames<'_>;
2161    fn glyph_metrics(&self) -> GlyphMetrics<'_>;
2162}
2163
2164impl SerializerFont for crate::Shaper<'_> {
2165    fn coords(&self) -> &[F2Dot14] {
2166        self.coords()
2167    }
2168
2169    fn glyph_names(&self) -> GlyphNames<'_> {
2170        crate::Shaper::glyph_names(self)
2171    }
2172
2173    fn glyph_metrics(&self) -> GlyphMetrics<'_> {
2174        crate::Shaper::glyph_metrics(self)
2175    }
2176}
2177
2178impl SerializerFont for crate::font::FontInstance {
2179    fn coords(&self) -> &[F2Dot14] {
2180        self.normalized_coords()
2181    }
2182
2183    fn glyph_names(&self) -> GlyphNames<'_> {
2184        GlyphNames::from_tables(&self.tables())
2185    }
2186
2187    fn glyph_metrics(&self) -> GlyphMetrics<'_> {
2188        let table_ranges = TableRanges::from_tables(&self.tables());
2189        let metrics = BasicFontMetrics {
2190            num_glyphs: table_ranges.num_glyphs,
2191            units_per_em: table_ranges.units_per_em,
2192            ascent: table_ranges.ascent,
2193            descent: table_ranges.descent,
2194        };
2195        GlyphMetrics::from_tables(&self.tables(), &metrics)
2196    }
2197}
2198
2199impl core::fmt::Debug for GlyphBuffer {
2200    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2201        fmt.debug_struct("GlyphBuffer")
2202            .field("glyph_positions", &self.glyph_positions())
2203            .field("glyph_infos", &self.glyph_infos())
2204            .finish()
2205    }
2206}