harfrust/hb/
buffer.rs

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