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            *scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII;
343
344            if u.is_default_ignorable() {
345                props |= UnicodeProps::IGNORABLE.bits();
346                *scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
347
348                match u {
349                    0x200C => props |= UnicodeProps::CF_ZWNJ.bits(),
350                    0x200D => props |= UnicodeProps::CF_ZWJ.bits(),
351
352                    // Mongolian Free Variation Selectors need to be remembered
353                    // because although we need to hide them like default-ignorables,
354                    // they need to non-ignorable during shaping.  This is similar to
355                    // what we do for joiners in Indic-like shapers, but since the
356                    // FVSes are GC=Mn, we have use a separate bit to remember them.
357                    // Fixes:
358                    // https://github.com/harfbuzz/harfbuzz/issues/234
359                    0x180B..=0x180D | 0x180F => props |= UnicodeProps::HIDDEN.bits(),
360
361                    // TAG characters need similar treatment. Fixes:
362                    // https://github.com/harfbuzz/harfbuzz/issues/463
363                    0xE0020..=0xE007F => props |= UnicodeProps::HIDDEN.bits(),
364
365                    // COMBINING GRAPHEME JOINER should not be skipped during GSUB either.
366                    // https://github.com/harfbuzz/harfbuzz/issues/554
367                    0x034F => {
368                        props |= UnicodeProps::HIDDEN.bits();
369                        *scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CGJ;
370                    }
371
372                    _ => {}
373                }
374            }
375
376            if gc.is_mark() {
377                props |= UnicodeProps::CONTINUATION.bits();
378                props |= (u.modified_combining_class() as u16) << 8;
379            }
380        }
381
382        self.set_unicode_props(props);
383    }
384
385    #[inline]
386    pub(crate) fn unhide(&mut self) {
387        let mut n = self.unicode_props();
388        n &= !UnicodeProps::HIDDEN.bits();
389        self.set_unicode_props(n);
390    }
391}
392
393pub type hb_buffer_cluster_level_t = u32;
394pub const HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES: u32 = 0;
395pub const HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS: u32 = 1;
396pub const HB_BUFFER_CLUSTER_LEVEL_CHARACTERS: u32 = 2;
397pub const HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES: u32 = 3;
398pub const HB_BUFFER_CLUSTER_LEVEL_DEFAULT: u32 = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES;
399
400pub struct hb_buffer_t {
401    // Information about how the text in the buffer should be treated.
402    pub flags: BufferFlags,
403    pub cluster_level: hb_buffer_cluster_level_t,
404    pub invisible: Option<GlyphId>,
405    pub not_found_variation_selector: Option<u32>,
406
407    // Buffer contents.
408    pub direction: Direction,
409    pub script: Option<Script>,
410    pub language: Option<Language>,
411
412    /// Allocations successful.
413    pub successful: bool,
414    /// Whether we have an output buffer going on.
415    pub(crate) have_output: bool,
416    pub have_separate_output: bool,
417    /// Whether we have positions
418    pub have_positions: bool,
419
420    pub idx: usize,
421    pub len: usize,
422    pub out_len: usize,
423
424    pub info: Vec<GlyphInfo>,
425    pub pos: Vec<GlyphPosition>,
426
427    // Text before / after the main buffer contents.
428    // Always in Unicode, and ordered outward.
429    // Index 0 is for "pre-context", 1 for "post-context".
430    pub context: [[Codepoint; CONTEXT_LENGTH]; 2],
431    pub context_len: [usize; 2],
432
433    // Managed by enter / leave
434    pub allocated_var_bits: u8,
435    pub serial: u8,
436    pub scratch_flags: hb_buffer_scratch_flags_t,
437    /// Maximum allowed len.
438    pub max_len: usize,
439    /// Maximum allowed operations.
440    pub max_ops: i32,
441
442    pub(crate) glyph_set: U32Set,
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            glyph_set: U32Set::default(),
483        }
484    }
485
486    #[inline]
487    pub fn allocate_var(&mut self, shape: buffer_var_shape) {
488        let bits = shape.bits();
489        debug_assert_eq!(
490            self.allocated_var_bits & bits,
491            0,
492            "Variable already allocated"
493        );
494        self.allocated_var_bits |= bits;
495    }
496
497    #[inline]
498    pub fn try_allocate_var(&mut self, shape: buffer_var_shape) -> bool {
499        let bits = shape.bits();
500        if self.allocated_var_bits & bits != 0 {
501            return false;
502        }
503        self.allocated_var_bits |= bits;
504        true
505    }
506
507    #[inline]
508    pub fn deallocate_var(&mut self, shape: buffer_var_shape) {
509        let bits = shape.bits();
510        debug_assert_eq!(
511            self.allocated_var_bits & bits,
512            bits,
513            "Deallocating unallocated var"
514        );
515        self.allocated_var_bits &= !bits;
516    }
517
518    #[inline]
519    pub fn assert_var(&self, shape: buffer_var_shape) {
520        let bits = shape.bits();
521        debug_assert_eq!(
522            self.allocated_var_bits & bits,
523            bits,
524            "Variable not allocated"
525        );
526    }
527
528    #[inline]
529    pub fn info_slice_mut(&mut self) -> &mut [GlyphInfo] {
530        &mut self.info[..self.len]
531    }
532
533    #[inline]
534    pub fn out_info(&self) -> &[GlyphInfo] {
535        if self.have_separate_output {
536            bytemuck::cast_slice(self.pos.as_slice())
537        } else {
538            &self.info
539        }
540    }
541
542    #[inline]
543    pub fn out_info_mut(&mut self) -> &mut [GlyphInfo] {
544        if self.have_separate_output {
545            bytemuck::cast_slice_mut(self.pos.as_mut_slice())
546        } else {
547            &mut self.info
548        }
549    }
550
551    #[inline]
552    fn set_out_info(&mut self, i: usize, info: GlyphInfo) {
553        self.out_info_mut()[i] = info;
554    }
555
556    #[inline]
557    pub fn cur(&self, i: usize) -> &GlyphInfo {
558        &self.info[self.idx + i]
559    }
560
561    #[inline]
562    pub fn cur_mut(&mut self, i: usize) -> &mut GlyphInfo {
563        let idx = self.idx + i;
564        &mut self.info[idx]
565    }
566
567    #[inline]
568    pub fn cur_pos_mut(&mut self) -> &mut GlyphPosition {
569        let i = self.idx;
570        &mut self.pos[i]
571    }
572
573    #[inline]
574    pub fn prev(&self) -> &GlyphInfo {
575        let idx = self.out_len.saturating_sub(1);
576        &self.out_info()[idx]
577    }
578
579    #[inline]
580    pub fn prev_mut(&mut self) -> &mut GlyphInfo {
581        let idx = self.out_len.saturating_sub(1);
582        &mut self.out_info_mut()[idx]
583    }
584
585    pub fn digest(&self) -> hb_set_digest_t {
586        let mut digest = hb_set_digest_t::new();
587        digest.add_array(self.info.iter().map(|i| i.glyph_id));
588        digest
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.make_room_for(n, 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        self.merge_clusters_impl(start, end);
980    }
981
982    fn merge_clusters_impl(&mut self, mut start: usize, mut end: usize) {
983        if !BufferClusterLevel::new(self.cluster_level).is_monotone() {
984            self.unsafe_to_break(Some(start), Some(end));
985            return;
986        }
987
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 end < 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_out_clusters(&mut self, mut start: usize, mut end: usize) {
1028        if !BufferClusterLevel::new(self.cluster_level).is_monotone() {
1029            return;
1030        }
1031
1032        if end - start < 2 {
1033            return;
1034        }
1035
1036        self.max_ops -= (end - start) as i32;
1037        if self.max_ops < 0 {
1038            self.successful = false;
1039        }
1040
1041        let cluster = self.out_info()[start..end]
1042            .iter()
1043            .map(|info| info.cluster)
1044            .min()
1045            .unwrap();
1046
1047        // Extend start
1048        while start != 0 && self.out_info()[start - 1].cluster == self.out_info()[start].cluster {
1049            start -= 1;
1050        }
1051
1052        // Extend end
1053        while end < self.out_len && self.out_info()[end - 1].cluster == self.out_info()[end].cluster
1054        {
1055            end += 1;
1056        }
1057
1058        // If we hit the start of buffer, continue in out-buffer.
1059        if end == self.out_len {
1060            let mut i = self.idx;
1061            while i < self.len && self.info[i].cluster == self.out_info()[end - 1].cluster {
1062                Self::set_cluster(&mut self.info[i], cluster, 0);
1063                i += 1;
1064            }
1065        }
1066
1067        for info in &mut self.out_info_mut()[start..end] {
1068            Self::set_cluster(info, cluster, 0);
1069        }
1070    }
1071
1072    /// Merge clusters for deleting current glyph, and skip it.
1073    pub fn delete_glyph(&mut self) {
1074        let cluster = self.info[self.idx].cluster;
1075
1076        if (self.idx + 1 < self.len && cluster == self.info[self.idx + 1].cluster)
1077            || (self.out_len != 0 && cluster == self.out_info()[self.out_len - 1].cluster)
1078        {
1079            // Cluster survives; do nothing.
1080            self.skip_glyph();
1081            return;
1082        }
1083
1084        if self.out_len != 0 {
1085            // Merge cluster backward.
1086            if cluster < self.out_info()[self.out_len - 1].cluster {
1087                let mask = self.info[self.idx].mask;
1088                let old_cluster = self.out_info()[self.out_len - 1].cluster;
1089
1090                let mut i = self.out_len;
1091                while i != 0 && self.out_info()[i - 1].cluster == old_cluster {
1092                    Self::set_cluster(&mut self.out_info_mut()[i - 1], cluster, mask);
1093                    i -= 1;
1094                }
1095            }
1096
1097            self.skip_glyph();
1098            return;
1099        }
1100
1101        if self.idx + 1 < self.len {
1102            // Merge cluster forward.
1103            self.merge_clusters(self.idx, self.idx + 2);
1104        }
1105
1106        self.skip_glyph();
1107    }
1108
1109    pub fn delete_glyphs_inplace(&mut self, filter: impl Fn(&GlyphInfo) -> bool) {
1110        // Merge clusters and delete filtered glyphs.
1111        // NOTE! We can't use out-buffer as we have positioning data.
1112        let mut j = 0;
1113
1114        for i in 0..self.len {
1115            if filter(&self.info[i]) {
1116                // Merge clusters.
1117                // Same logic as delete_glyph(), but for in-place removal
1118
1119                let cluster = self.info[i].cluster;
1120                if i + 1 < self.len && cluster == self.info[i + 1].cluster {
1121                    // Cluster survives; do nothing.
1122                    continue;
1123                }
1124
1125                if j != 0 {
1126                    // Merge cluster backward.
1127                    if cluster < self.info[j - 1].cluster {
1128                        let mask = self.info[i].mask;
1129                        let old_cluster = self.info[j - 1].cluster;
1130
1131                        let mut k = j;
1132                        while k > 0 && self.info[k - 1].cluster == old_cluster {
1133                            Self::set_cluster(&mut self.info[k - 1], cluster, mask);
1134                            k -= 1;
1135                        }
1136                    }
1137                    continue;
1138                }
1139
1140                if i + 1 < self.len {
1141                    // Merge cluster forward.
1142                    self.merge_clusters(i, i + 2);
1143                }
1144
1145                continue;
1146            }
1147
1148            if j != i {
1149                self.info[j] = self.info[i];
1150                self.pos[j] = self.pos[i];
1151            }
1152
1153            j += 1;
1154        }
1155
1156        self.len = j;
1157    }
1158
1159    pub fn unsafe_to_break(&mut self, start: Option<usize>, end: Option<usize>) {
1160        self._set_glyph_flags(
1161            UNSAFE_TO_BREAK | UNSAFE_TO_CONCAT,
1162            start,
1163            end,
1164            Some(true),
1165            None,
1166        );
1167    }
1168
1169    pub fn safe_to_insert_tatweel(&mut self, start: Option<usize>, end: Option<usize>) {
1170        if !self
1171            .flags
1172            .contains(BufferFlags::PRODUCE_SAFE_TO_INSERT_TATWEEL)
1173        {
1174            self.unsafe_to_break(start, end);
1175            return;
1176        }
1177
1178        self._set_glyph_flags(SAFE_TO_INSERT_TATWEEL, start, end, Some(true), None);
1179    }
1180
1181    fn _set_glyph_flags_impl(
1182        &mut self,
1183        mask: hb_mask_t,
1184        start: usize,
1185        end: usize,
1186        interior: bool,
1187        from_out_buffer: bool,
1188    ) {
1189        self.scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
1190
1191        if !from_out_buffer || !self.have_output {
1192            if !interior {
1193                for info in &mut self.info[start..end] {
1194                    info.mask |= mask;
1195                }
1196            } else {
1197                let cluster = self._infos_find_min_cluster(&self.info, start, end, None);
1198                self._infos_set_glyph_flags(false, start, end, cluster, mask);
1199            }
1200        } else {
1201            debug_assert!(start <= self.out_len);
1202            debug_assert!(self.idx <= end);
1203
1204            if !interior {
1205                let range_end = self.out_len;
1206                for info in &mut self.out_info_mut()[start..range_end] {
1207                    info.mask |= mask;
1208                }
1209
1210                for info in &mut self.info[self.idx..end] {
1211                    info.mask |= mask;
1212                }
1213            } else {
1214                let mut cluster = self._infos_find_min_cluster(&self.info, self.idx, end, None);
1215                cluster = self._infos_find_min_cluster(
1216                    self.out_info(),
1217                    start,
1218                    self.out_len,
1219                    Some(cluster),
1220                );
1221
1222                let out_len = self.out_len;
1223                self._infos_set_glyph_flags(true, start, out_len, cluster, mask);
1224                self._infos_set_glyph_flags(false, self.idx, end, cluster, mask);
1225            }
1226        }
1227    }
1228
1229    /// Adds glyph flags in mask to infos with clusters between start and end.
1230    /// The start index will be from out-buffer if from_out_buffer is true.
1231    /// If interior is true, then the cluster having the minimum value is skipped. */
1232    fn _set_glyph_flags(
1233        &mut self,
1234        mask: hb_mask_t,
1235        start: Option<usize>,
1236        end: Option<usize>,
1237        interior: Option<bool>,
1238        from_out_buffer: Option<bool>,
1239    ) {
1240        // If the range is not specified, ie. whole buffer, allow it.
1241        // But if range *is* specified, reject if range is too large.
1242        if let (Some(start), Some(end)) = (start, end) {
1243            if end.wrapping_sub(start) > 255 {
1244                return;
1245            }
1246        }
1247
1248        let start = start.unwrap_or(0);
1249        let end = min(end.unwrap_or(self.len), self.len);
1250        let interior = interior.unwrap_or(false);
1251        let from_out_buffer = from_out_buffer.unwrap_or(false);
1252
1253        if interior && !from_out_buffer && end - start < 2 {
1254            return;
1255        }
1256
1257        self._set_glyph_flags_impl(mask, start, end, interior, from_out_buffer);
1258    }
1259
1260    pub fn unsafe_to_concat(&mut self, start: Option<usize>, end: Option<usize>) {
1261        if !self.flags.contains(BufferFlags::PRODUCE_UNSAFE_TO_CONCAT) {
1262            return;
1263        }
1264
1265        self._set_glyph_flags(UNSAFE_TO_CONCAT, start, end, Some(false), None);
1266    }
1267
1268    pub fn unsafe_to_break_from_outbuffer(&mut self, start: Option<usize>, end: Option<usize>) {
1269        self._set_glyph_flags(
1270            UNSAFE_TO_BREAK | UNSAFE_TO_CONCAT,
1271            start,
1272            end,
1273            Some(true),
1274            Some(true),
1275        );
1276    }
1277
1278    pub fn unsafe_to_concat_from_outbuffer(&mut self, start: Option<usize>, end: Option<usize>) {
1279        if !self.flags.contains(BufferFlags::PRODUCE_UNSAFE_TO_CONCAT) {
1280            return;
1281        }
1282
1283        self._set_glyph_flags(UNSAFE_TO_CONCAT, start, end, Some(false), Some(true));
1284    }
1285
1286    pub fn move_to(&mut self, i: usize) -> bool {
1287        if !self.have_output {
1288            debug_assert!(i <= self.len);
1289            self.idx = i;
1290            return true;
1291        }
1292
1293        if !self.successful {
1294            return false;
1295        }
1296
1297        debug_assert!(i <= self.out_len + (self.len - self.idx));
1298
1299        if self.out_len < i {
1300            let count = i - self.out_len;
1301            if !self.make_room_for(count, count) {
1302                return false;
1303            }
1304
1305            for j in 0..count {
1306                self.set_out_info(self.out_len + j, self.info[self.idx + j]);
1307            }
1308
1309            self.idx += count;
1310            self.out_len += count;
1311        } else if self.out_len > i {
1312            // Tricky part: rewinding...
1313            let count = self.out_len - i;
1314
1315            // This will blow in our face if memory allocation fails later
1316            // in this same lookup...
1317            //
1318            // We used to shift with extra 32 items.
1319            // But that would leave empty slots in the buffer in case of allocation
1320            // failures.  See comments in shift_forward().  This can cause O(N^2)
1321            // behavior more severely than adding 32 empty slots can...
1322            if self.idx < count && !self.shift_forward(count - self.idx) {
1323                return false;
1324            }
1325
1326            debug_assert!(self.idx >= count);
1327
1328            self.idx -= count;
1329            self.out_len -= count;
1330
1331            for j in 0..count {
1332                self.info[self.idx + j] = self.out_info()[self.out_len + j];
1333            }
1334        }
1335
1336        true
1337    }
1338
1339    #[must_use]
1340    #[inline(always)]
1341    pub fn ensure(&mut self, size: usize) -> bool {
1342        if size <= self.info.len() {
1343            true
1344        } else {
1345            self.enlarge(size)
1346        }
1347    }
1348
1349    #[must_use]
1350    fn enlarge(&mut self, size: usize) -> bool {
1351        if size > self.max_len {
1352            self.successful = false;
1353            return false;
1354        }
1355
1356        self.info.resize(size, GlyphInfo::default());
1357        self.pos.resize(size, GlyphPosition::default());
1358        true
1359    }
1360
1361    #[must_use]
1362    fn make_room_for(&mut self, num_in: usize, num_out: usize) -> bool {
1363        if !self.ensure(self.out_len + num_out) {
1364            return false;
1365        }
1366
1367        if !self.have_separate_output && self.out_len + num_out > self.idx + num_in {
1368            debug_assert!(self.have_output);
1369
1370            self.have_separate_output = true;
1371            for i in 0..self.out_len {
1372                self.set_out_info(i, self.info[i]);
1373            }
1374        }
1375
1376        true
1377    }
1378
1379    fn shift_forward(&mut self, count: usize) -> bool {
1380        debug_assert!(self.have_output);
1381        if !self.ensure(self.len + count) {
1382            return false;
1383        }
1384
1385        self.max_ops -= (self.len - self.idx) as i32;
1386        if self.max_ops < 0 {
1387            self.successful = false;
1388            return false;
1389        }
1390
1391        for i in (0..(self.len - self.idx)).rev() {
1392            self.info[self.idx + count + i] = self.info[self.idx + i];
1393        }
1394
1395        if self.idx + count > self.len {
1396            for info in &mut self.info[self.len..self.idx + count] {
1397                *info = GlyphInfo::default();
1398            }
1399        }
1400
1401        self.len += count;
1402        self.idx += count;
1403
1404        true
1405    }
1406
1407    fn clear_context(&mut self, side: usize) {
1408        self.context_len[side] = 0;
1409    }
1410
1411    pub fn sort(&mut self, start: usize, end: usize, cmp: impl Fn(&GlyphInfo, &GlyphInfo) -> bool) {
1412        debug_assert!(!self.have_positions);
1413
1414        for i in start + 1..end {
1415            let mut j = i;
1416            while j > start && cmp(&self.info[j - 1], &self.info[i]) {
1417                j -= 1;
1418            }
1419
1420            if i == j {
1421                continue;
1422            }
1423
1424            // Move item i to occupy place for item j, shift what's in between.
1425            self.merge_clusters(j, i + 1);
1426
1427            {
1428                let t = self.info[i];
1429                for idx in (0..i - j).rev() {
1430                    self.info[idx + j + 1] = self.info[idx + j];
1431                }
1432
1433                self.info[j] = t;
1434            }
1435        }
1436    }
1437
1438    pub fn set_cluster(info: &mut GlyphInfo, cluster: u32, mask: hb_mask_t) {
1439        if info.cluster != cluster {
1440            info.mask = (info.mask & !glyph_flag::DEFINED) | (mask & glyph_flag::DEFINED);
1441        }
1442
1443        info.cluster = cluster;
1444    }
1445
1446    // Called around shape()
1447    pub(crate) fn enter(&mut self) {
1448        self.serial = 0;
1449        self.scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
1450
1451        if let Some(len) = self.len.checked_mul(hb_buffer_t::MAX_LEN_FACTOR) {
1452            self.max_len = len.max(hb_buffer_t::MAX_LEN_MIN);
1453        }
1454
1455        if let Ok(len) = i32::try_from(self.len) {
1456            if let Some(ops) = len.checked_mul(hb_buffer_t::MAX_OPS_FACTOR) {
1457                self.max_ops = ops.max(hb_buffer_t::MAX_OPS_MIN);
1458            }
1459        }
1460    }
1461
1462    // Called around shape()
1463    pub(crate) fn leave(&mut self) {
1464        self.max_len = hb_buffer_t::MAX_LEN_DEFAULT;
1465        self.max_ops = hb_buffer_t::MAX_OPS_DEFAULT;
1466        self.serial = 0;
1467    }
1468
1469    fn _infos_find_min_cluster(
1470        &self,
1471        info: &[GlyphInfo],
1472        start: usize,
1473        end: usize,
1474        cluster: Option<u32>,
1475    ) -> u32 {
1476        let mut cluster = cluster.unwrap_or(u32::MAX);
1477
1478        if start == end {
1479            return cluster;
1480        }
1481
1482        if self.cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS {
1483            for glyph_info in &info[start..end] {
1484                cluster = min(cluster, glyph_info.cluster);
1485            }
1486        }
1487
1488        cluster.min(info[start].cluster.min(info[end - 1].cluster))
1489    }
1490
1491    #[inline(always)]
1492    fn _infos_set_glyph_flags(
1493        &mut self,
1494        out_info: bool,
1495        start: usize,
1496        end: usize,
1497        cluster: u32,
1498        mask: hb_mask_t,
1499    ) {
1500        let mut apply_scratch_flags = false;
1501
1502        if start == end {
1503            return;
1504        }
1505
1506        let cluster_level = self.cluster_level;
1507
1508        let infos = if out_info {
1509            self.out_info_mut()
1510        } else {
1511            self.info.as_mut_slice()
1512        };
1513
1514        let cluster_first = infos[start].cluster;
1515        let cluster_last = infos[end - 1].cluster;
1516
1517        if cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS
1518            || (cluster != cluster_first && cluster != cluster_last)
1519        {
1520            for info in &mut infos[start..end] {
1521                if info.cluster != cluster {
1522                    apply_scratch_flags = true;
1523                    info.mask |= mask;
1524                }
1525            }
1526
1527            if apply_scratch_flags {
1528                self.scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
1529            }
1530
1531            return;
1532        }
1533
1534        // Monotone clusters
1535        if cluster == cluster_first {
1536            let mut i = end;
1537            while start < i && infos[i - 1].cluster != cluster_first {
1538                if cluster != infos[i - 1].cluster {
1539                    apply_scratch_flags = true;
1540                    infos[i - 1].mask |= mask;
1541                }
1542
1543                i -= 1;
1544            }
1545        } else {
1546            let mut i = start;
1547            while i < end && infos[i].cluster != cluster_last {
1548                if cluster != infos[i].cluster {
1549                    apply_scratch_flags = true;
1550                    infos[i].mask |= mask;
1551                }
1552
1553                i += 1;
1554            }
1555        }
1556
1557        if apply_scratch_flags {
1558            self.scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
1559        }
1560    }
1561
1562    /// Checks that buffer contains no elements.
1563    pub fn is_empty(&self) -> bool {
1564        self.len == 0
1565    }
1566
1567    fn push_str(&mut self, text: &str) {
1568        if !self.ensure(self.len + text.chars().count()) {
1569            return;
1570        }
1571
1572        for (i, c) in text.char_indices() {
1573            self.info[self.len] = GlyphInfo {
1574                glyph_id: c as u32,
1575                cluster: i as u32,
1576                ..GlyphInfo::default()
1577            };
1578            self.len += 1;
1579        }
1580    }
1581
1582    fn set_pre_context(&mut self, text: &str) {
1583        self.clear_context(0);
1584        for (i, c) in text.chars().rev().enumerate().take(CONTEXT_LENGTH) {
1585            self.context[0][i] = c as Codepoint;
1586            self.context_len[0] += 1;
1587        }
1588    }
1589
1590    fn set_post_context(&mut self, text: &str) {
1591        self.clear_context(1);
1592        for (i, c) in text.chars().enumerate().take(CONTEXT_LENGTH) {
1593            self.context[1][i] = c as Codepoint;
1594            self.context_len[1] += 1;
1595        }
1596    }
1597
1598    pub fn next_syllable(&self, mut start: usize) -> usize {
1599        if start >= self.len {
1600            return start;
1601        }
1602
1603        let syllable = self.info[start].syllable();
1604        start += 1;
1605        while start < self.len && syllable == self.info[start].syllable() {
1606            start += 1;
1607        }
1608
1609        start
1610    }
1611
1612    #[inline]
1613    pub fn allocate_lig_id(&mut self) -> u8 {
1614        let mut lig_id = self.next_serial() & 0x07;
1615
1616        if lig_id == 0 {
1617            lig_id = self.allocate_lig_id();
1618        }
1619
1620        lig_id
1621    }
1622}
1623
1624pub(crate) fn _cluster_group_func(a: &GlyphInfo, b: &GlyphInfo) -> bool {
1625    a.cluster == b.cluster
1626}
1627
1628// TODO: to iter if possible
1629
1630macro_rules! foreach_cluster {
1631    ($buffer:expr, $start:ident, $end:ident, $($body:tt)*) => {
1632        foreach_group!($buffer, $start, $end, $crate::hb::buffer::_cluster_group_func, $($body)*)
1633    };
1634}
1635
1636macro_rules! foreach_group {
1637    ($buffer:expr, $start:ident, $end:ident, $group_func:expr, $($body:tt)*) => {{
1638        let count = $buffer.len;
1639        let mut $start = 0;
1640        let mut $end = if count > 0 { $buffer.group_end(0, $group_func) } else { 0 };
1641
1642        while $start < count {
1643            $($body)*;
1644            $start = $end;
1645            $end = $buffer.group_end($start, $group_func);
1646        }
1647    }};
1648}
1649
1650macro_rules! foreach_syllable {
1651    ($buffer:expr, $start:ident, $end:ident, $($body:tt)*) => {{
1652        let mut $start = 0;
1653        let mut $end = $buffer.next_syllable(0);
1654        while $start < $buffer.len {
1655            $($body)*;
1656            $start = $end;
1657            $end = $buffer.next_syllable($start);
1658        }
1659    }};
1660}
1661
1662macro_rules! foreach_grapheme {
1663    ($buffer:expr, $start:ident, $end:ident, $($body:tt)*) => {
1664        foreach_group!($buffer, $start, $end, $crate::hb::ot_layout::_hb_grapheme_group_func, $($body)*)
1665    };
1666}
1667
1668bitflags::bitflags! {
1669    #[derive(Default, Debug, Clone, Copy)]
1670    pub struct UnicodeProps: u16 {
1671        const GENERAL_CATEGORY  = 0x001F;
1672        const IGNORABLE         = 0x0020;
1673        // MONGOLIAN FREE VARIATION SELECTOR 1..4, or TAG characters, or CGJ sometimes
1674        const HIDDEN            = 0x0040;
1675        const CONTINUATION      = 0x0080;
1676
1677        // If GEN_CAT=FORMAT, top byte masks:
1678        const CF_ZWJ            = 0x0100;
1679        const CF_ZWNJ           = 0x0200;
1680        const CF_VS             = 0x0400;
1681        const CF_AAT_DELETED    = 0x0800;
1682    }
1683}
1684
1685bitflags::bitflags! {
1686    #[derive(Default, Debug, Clone, Copy)]
1687    pub struct GlyphPropsFlags: u16 {
1688        // The following three match LookupFlags::Ignore* numbers.
1689        const BASE_GLYPH    = 0x02;
1690        const LIGATURE      = 0x04;
1691        const MARK          = 0x08;
1692        const CLASS_MASK    = Self::BASE_GLYPH.bits() | Self::LIGATURE.bits() | Self::MARK.bits();
1693
1694        // The following are used internally; not derived from GDEF.
1695        const MATCHES       = 0x10;
1696        const SUBSTITUTED   = 0x20;
1697        const LIGATED       = 0x40;
1698        const MULTIPLIED    = 0x80;
1699
1700        const PRESERVE      = Self::SUBSTITUTED.bits() | Self::LIGATED.bits() | Self::MULTIPLIED.bits();
1701    }
1702}
1703
1704pub type hb_buffer_scratch_flags_t = u32;
1705pub const HB_BUFFER_SCRATCH_FLAG_DEFAULT: u32 = 0x0000_0000;
1706pub const HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII: u32 = 0x0000_0001;
1707pub const HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES: u32 = 0x0000_0002;
1708pub const HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK: u32 = 0x0000_0004;
1709pub const HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT: u32 = 0x0000_0008;
1710pub const HB_BUFFER_SCRATCH_FLAG_HAS_CGJ: u32 = 0x0000_0010;
1711pub const HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS: u32 = 0x0000_0020;
1712pub const HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE: u32 = 0x0000_0040;
1713pub const HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK: u32 = 0x0000_0080;
1714
1715/* Reserved for shapers' internal use. */
1716pub const HB_BUFFER_SCRATCH_FLAG_SHAPER0: u32 = 0x0100_0000;
1717// pub const HB_BUFFER_SCRATCH_FLAG_SHAPER1: u32 = 0x02000000;
1718// pub const HB_BUFFER_SCRATCH_FLAG_SHAPER2: u32 = 0x04000000;
1719// pub const HB_BUFFER_SCRATCH_FLAG_SHAPER3: u32 = 0x08000000;
1720
1721/// A buffer that contains an input string ready for shaping.
1722pub struct UnicodeBuffer(pub(crate) hb_buffer_t);
1723
1724impl UnicodeBuffer {
1725    /// Create a new `UnicodeBuffer`.
1726    #[inline]
1727    pub fn new() -> UnicodeBuffer {
1728        UnicodeBuffer(hb_buffer_t::new())
1729    }
1730
1731    /// Returns the length of the data of the buffer.
1732    ///
1733    /// This corresponds to the number of unicode codepoints contained in the
1734    /// buffer.
1735    #[inline]
1736    pub fn len(&self) -> usize {
1737        self.0.len
1738    }
1739
1740    /// Ensures that the buffer can hold at least `size` codepoints.
1741    pub fn reserve(&mut self, size: usize) -> bool {
1742        self.0.ensure(size)
1743    }
1744
1745    /// Returns `true` if the buffer contains no elements.
1746    #[inline]
1747    pub fn is_empty(&self) -> bool {
1748        self.0.is_empty()
1749    }
1750
1751    /// Pushes a string to a buffer.
1752    #[inline]
1753    pub fn push_str(&mut self, str: &str) {
1754        self.0.push_str(str);
1755    }
1756
1757    /// Sets the pre-context for this buffer.
1758    #[inline]
1759    pub fn set_pre_context(&mut self, str: &str) {
1760        self.0.set_pre_context(str);
1761    }
1762
1763    /// Sets the post-context for this buffer.
1764    #[inline]
1765    pub fn set_post_context(&mut self, str: &str) {
1766        self.0.set_post_context(str);
1767    }
1768
1769    /// Appends a character to a buffer with the given cluster value.
1770    #[inline]
1771    pub fn add(&mut self, codepoint: char, cluster: u32) {
1772        self.0.add(codepoint as u32, cluster);
1773        self.0.context_len[1] = 0;
1774    }
1775
1776    /// Set the text direction of the `Buffer`'s contents.
1777    #[inline]
1778    pub fn set_direction(&mut self, direction: Direction) {
1779        self.0.direction = direction;
1780    }
1781
1782    /// Returns the `Buffer`'s text direction.
1783    #[inline]
1784    pub fn direction(&self) -> Direction {
1785        self.0.direction
1786    }
1787
1788    /// Set the script from an ISO15924 tag.
1789    #[inline]
1790    pub fn set_script(&mut self, script: Script) {
1791        self.0.script = Some(script);
1792    }
1793
1794    /// Get the ISO15924 script tag.
1795    pub fn script(&self) -> Script {
1796        self.0.script.unwrap_or(script::UNKNOWN)
1797    }
1798
1799    /// Set the buffer language.
1800    #[inline]
1801    pub fn set_language(&mut self, lang: Language) {
1802        self.0.language = Some(lang);
1803    }
1804
1805    /// Set the glyph value to replace not-found variation-selector characters with.
1806    #[inline]
1807    pub fn set_not_found_variation_selector_glyph(&mut self, glyph: u32) {
1808        self.0.not_found_variation_selector = Some(glyph);
1809    }
1810
1811    /// Get the buffer language.
1812    #[inline]
1813    pub fn language(&self) -> Option<Language> {
1814        self.0.language.clone()
1815    }
1816
1817    /// Guess the segment properties (direction, language, script) for the
1818    /// current buffer.
1819    #[inline]
1820    pub fn guess_segment_properties(&mut self) {
1821        self.0.guess_segment_properties();
1822    }
1823
1824    /// Set the flags for this buffer.
1825    #[inline]
1826    pub fn set_flags(&mut self, flags: BufferFlags) {
1827        self.0.flags = flags;
1828    }
1829
1830    /// Get the flags for this buffer.
1831    #[inline]
1832    pub fn flags(&self) -> BufferFlags {
1833        self.0.flags
1834    }
1835
1836    /// Set the cluster level of the buffer.
1837    #[inline]
1838    pub fn set_cluster_level(&mut self, cluster_level: BufferClusterLevel) {
1839        self.0.cluster_level = match cluster_level {
1840            BufferClusterLevel::MonotoneGraphemes => HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES,
1841            BufferClusterLevel::MonotoneCharacters => HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS,
1842            BufferClusterLevel::Characters => HB_BUFFER_CLUSTER_LEVEL_CHARACTERS,
1843            BufferClusterLevel::Graphemes => HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES,
1844        }
1845    }
1846
1847    /// Retrieve the cluster level of the buffer.
1848    #[inline]
1849    pub fn cluster_level(&self) -> BufferClusterLevel {
1850        match self.0.cluster_level {
1851            HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES => BufferClusterLevel::MonotoneGraphemes,
1852            HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS => BufferClusterLevel::MonotoneCharacters,
1853            HB_BUFFER_CLUSTER_LEVEL_CHARACTERS => BufferClusterLevel::Characters,
1854            HB_BUFFER_CLUSTER_LEVEL_GRAPHEMES => BufferClusterLevel::Graphemes,
1855            _ => BufferClusterLevel::MonotoneGraphemes,
1856        }
1857    }
1858
1859    /// Resets clusters.
1860    #[inline]
1861    pub fn reset_clusters(&mut self) {
1862        self.0.reset_clusters();
1863    }
1864
1865    /// Clear the contents of the buffer.
1866    #[inline]
1867    pub fn clear(&mut self) {
1868        self.0.clear();
1869    }
1870}
1871
1872impl core::fmt::Debug for UnicodeBuffer {
1873    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1874        fmt.debug_struct("UnicodeBuffer")
1875            .field("direction", &self.direction())
1876            .field("language", &self.language())
1877            .field("script", &self.script())
1878            .field("cluster_level", &self.cluster_level())
1879            .finish()
1880    }
1881}
1882
1883impl Default for UnicodeBuffer {
1884    fn default() -> UnicodeBuffer {
1885        UnicodeBuffer::new()
1886    }
1887}
1888
1889/// A buffer that contains the results of the shaping process.
1890pub struct GlyphBuffer(pub(crate) hb_buffer_t);
1891
1892impl GlyphBuffer {
1893    /// Returns the length of the data of the buffer.
1894    ///
1895    /// When called before shaping this is the number of unicode codepoints
1896    /// contained in the buffer. When called after shaping it returns the number
1897    /// of glyphs stored.
1898    #[inline]
1899    pub fn len(&self) -> usize {
1900        self.0.len
1901    }
1902
1903    /// Returns `true` if the buffer contains no elements.
1904    #[inline]
1905    pub fn is_empty(&self) -> bool {
1906        self.0.is_empty()
1907    }
1908
1909    /// Get the glyph infos.
1910    #[inline]
1911    pub fn glyph_infos(&self) -> &[GlyphInfo] {
1912        &self.0.info[0..self.0.len]
1913    }
1914
1915    /// Get the glyph positions.
1916    #[inline]
1917    pub fn glyph_positions(&self) -> &[GlyphPosition] {
1918        &self.0.pos[0..self.0.len]
1919    }
1920
1921    /// Clears the content of the glyph buffer and returns an empty
1922    /// `UnicodeBuffer` reusing the existing allocation.
1923    #[inline]
1924    pub fn clear(mut self) -> UnicodeBuffer {
1925        self.0.clear();
1926        UnicodeBuffer(self.0)
1927    }
1928
1929    /// Converts the glyph buffer content into a string.
1930    pub fn serialize(&self, face: &crate::Shaper, flags: SerializeFlags) -> String {
1931        self.serialize_impl(face, flags).unwrap_or_default()
1932    }
1933
1934    fn serialize_impl(
1935        &self,
1936        face: &hb_font_t,
1937        flags: SerializeFlags,
1938    ) -> Result<String, core::fmt::Error> {
1939        use core::fmt::Write;
1940
1941        let mut s = String::with_capacity(64);
1942
1943        let info = self.glyph_infos();
1944        let pos = self.glyph_positions();
1945        let mut x = 0;
1946        let mut y = 0;
1947        let names = face.glyph_names();
1948        for (info, pos) in info.iter().zip(pos) {
1949            s.push(if s.is_empty() { '[' } else { '|' });
1950
1951            if !flags.contains(SerializeFlags::NO_GLYPH_NAMES) {
1952                match names.get(info.as_glyph().to_u32()) {
1953                    Some(name) => s.push_str(name),
1954                    None => write!(&mut s, "gid{}", info.glyph_id)?,
1955                }
1956            } else {
1957                write!(&mut s, "{}", info.glyph_id)?;
1958            }
1959
1960            if !flags.contains(SerializeFlags::NO_CLUSTERS) {
1961                write!(&mut s, "={}", info.cluster)?;
1962            }
1963
1964            if !flags.contains(SerializeFlags::NO_POSITIONS) {
1965                if x + pos.x_offset != 0 || y + pos.y_offset != 0 {
1966                    write!(&mut s, "@{},{}", x + pos.x_offset, y + pos.y_offset)?;
1967                }
1968
1969                if !flags.contains(SerializeFlags::NO_ADVANCES) {
1970                    write!(&mut s, "+{}", pos.x_advance)?;
1971                    if pos.y_advance != 0 {
1972                        write!(&mut s, ",{}", pos.y_advance)?;
1973                    }
1974                }
1975            }
1976
1977            if flags.contains(SerializeFlags::GLYPH_FLAGS) {
1978                if info.mask & glyph_flag::DEFINED != 0 {
1979                    write!(&mut s, "#{:X}", info.mask & glyph_flag::DEFINED)?;
1980                }
1981            }
1982
1983            if flags.contains(SerializeFlags::GLYPH_EXTENTS) {
1984                let mut extents = hb_glyph_extents_t::default();
1985                face.glyph_extents(info.as_glyph(), &mut extents);
1986                write!(
1987                    &mut s,
1988                    "<{},{},{},{}>",
1989                    extents.x_bearing, extents.y_bearing, extents.width, extents.height
1990                )?;
1991            }
1992
1993            if flags.contains(SerializeFlags::NO_ADVANCES) {
1994                x += pos.x_advance;
1995                y += pos.y_advance;
1996            }
1997        }
1998
1999        if !s.is_empty() {
2000            s.push(']');
2001        }
2002
2003        Ok(s)
2004    }
2005}
2006
2007impl core::fmt::Debug for GlyphBuffer {
2008    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2009        fmt.debug_struct("GlyphBuffer")
2010            .field("glyph_positions", &self.glyph_positions())
2011            .field("glyph_infos", &self.glyph_infos())
2012            .finish()
2013    }
2014}