rustybuzz/hb/
buffer.rs

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