xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-buffer.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker  * Copyright © 1998-2004  David Turner and Werner Lemberg
3*2d1272b8SAndroid Build Coastguard Worker  * Copyright © 2004,2007,2009,2010  Red Hat, Inc.
4*2d1272b8SAndroid Build Coastguard Worker  * Copyright © 2011,2012  Google, Inc.
5*2d1272b8SAndroid Build Coastguard Worker  *
6*2d1272b8SAndroid Build Coastguard Worker  *  This is part of HarfBuzz, a text shaping library.
7*2d1272b8SAndroid Build Coastguard Worker  *
8*2d1272b8SAndroid Build Coastguard Worker  * Permission is hereby granted, without written agreement and without
9*2d1272b8SAndroid Build Coastguard Worker  * license or royalty fees, to use, copy, modify, and distribute this
10*2d1272b8SAndroid Build Coastguard Worker  * software and its documentation for any purpose, provided that the
11*2d1272b8SAndroid Build Coastguard Worker  * above copyright notice and the following two paragraphs appear in
12*2d1272b8SAndroid Build Coastguard Worker  * all copies of this software.
13*2d1272b8SAndroid Build Coastguard Worker  *
14*2d1272b8SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
15*2d1272b8SAndroid Build Coastguard Worker  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16*2d1272b8SAndroid Build Coastguard Worker  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
17*2d1272b8SAndroid Build Coastguard Worker  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18*2d1272b8SAndroid Build Coastguard Worker  * DAMAGE.
19*2d1272b8SAndroid Build Coastguard Worker  *
20*2d1272b8SAndroid Build Coastguard Worker  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
21*2d1272b8SAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22*2d1272b8SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
23*2d1272b8SAndroid Build Coastguard Worker  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
24*2d1272b8SAndroid Build Coastguard Worker  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25*2d1272b8SAndroid Build Coastguard Worker  *
26*2d1272b8SAndroid Build Coastguard Worker  * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
27*2d1272b8SAndroid Build Coastguard Worker  * Google Author(s): Behdad Esfahbod
28*2d1272b8SAndroid Build Coastguard Worker  */
29*2d1272b8SAndroid Build Coastguard Worker 
30*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_BUFFER_HH
31*2d1272b8SAndroid Build Coastguard Worker #define HB_BUFFER_HH
32*2d1272b8SAndroid Build Coastguard Worker 
33*2d1272b8SAndroid Build Coastguard Worker #include "hb.hh"
34*2d1272b8SAndroid Build Coastguard Worker #include "hb-unicode.hh"
35*2d1272b8SAndroid Build Coastguard Worker #include "hb-set-digest.hh"
36*2d1272b8SAndroid Build Coastguard Worker 
37*2d1272b8SAndroid Build Coastguard Worker 
38*2d1272b8SAndroid Build Coastguard Worker static_assert ((sizeof (hb_glyph_info_t) == 20), "");
39*2d1272b8SAndroid Build Coastguard Worker static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
40*2d1272b8SAndroid Build Coastguard Worker 
41*2d1272b8SAndroid Build Coastguard Worker HB_MARK_AS_FLAG_T (hb_glyph_flags_t);
42*2d1272b8SAndroid Build Coastguard Worker HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
43*2d1272b8SAndroid Build Coastguard Worker HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
44*2d1272b8SAndroid Build Coastguard Worker HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
45*2d1272b8SAndroid Build Coastguard Worker 
46*2d1272b8SAndroid Build Coastguard Worker enum hb_buffer_scratch_flags_t {
47*2d1272b8SAndroid Build Coastguard Worker   HB_BUFFER_SCRATCH_FLAG_DEFAULT			= 0x00000000u,
48*2d1272b8SAndroid Build Coastguard Worker   HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII			= 0x00000001u,
49*2d1272b8SAndroid Build Coastguard Worker   HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES		= 0x00000002u,
50*2d1272b8SAndroid Build Coastguard Worker   HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK		= 0x00000004u,
51*2d1272b8SAndroid Build Coastguard Worker   HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT		= 0x00000008u,
52*2d1272b8SAndroid Build Coastguard Worker   HB_BUFFER_SCRATCH_FLAG_HAS_CGJ			= 0x00000010u,
53*2d1272b8SAndroid Build Coastguard Worker   HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS		= 0x00000020u,
54*2d1272b8SAndroid Build Coastguard Worker   HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE		= 0x00000040u,
55*2d1272b8SAndroid Build Coastguard Worker   HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK= 0x00000080u,
56*2d1272b8SAndroid Build Coastguard Worker 
57*2d1272b8SAndroid Build Coastguard Worker   /* Reserved for shapers' internal use. */
58*2d1272b8SAndroid Build Coastguard Worker   HB_BUFFER_SCRATCH_FLAG_SHAPER0			= 0x01000000u,
59*2d1272b8SAndroid Build Coastguard Worker   HB_BUFFER_SCRATCH_FLAG_SHAPER1			= 0x02000000u,
60*2d1272b8SAndroid Build Coastguard Worker   HB_BUFFER_SCRATCH_FLAG_SHAPER2			= 0x04000000u,
61*2d1272b8SAndroid Build Coastguard Worker   HB_BUFFER_SCRATCH_FLAG_SHAPER3			= 0x08000000u,
62*2d1272b8SAndroid Build Coastguard Worker };
63*2d1272b8SAndroid Build Coastguard Worker HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
64*2d1272b8SAndroid Build Coastguard Worker 
65*2d1272b8SAndroid Build Coastguard Worker 
66*2d1272b8SAndroid Build Coastguard Worker /*
67*2d1272b8SAndroid Build Coastguard Worker  * hb_buffer_t
68*2d1272b8SAndroid Build Coastguard Worker  */
69*2d1272b8SAndroid Build Coastguard Worker 
70*2d1272b8SAndroid Build Coastguard Worker struct hb_buffer_t
71*2d1272b8SAndroid Build Coastguard Worker {
72*2d1272b8SAndroid Build Coastguard Worker   hb_object_header_t header;
73*2d1272b8SAndroid Build Coastguard Worker 
74*2d1272b8SAndroid Build Coastguard Worker   /*
75*2d1272b8SAndroid Build Coastguard Worker    * Information about how the text in the buffer should be treated.
76*2d1272b8SAndroid Build Coastguard Worker    */
77*2d1272b8SAndroid Build Coastguard Worker 
78*2d1272b8SAndroid Build Coastguard Worker   hb_unicode_funcs_t *unicode; /* Unicode functions */
79*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_flags_t flags; /* BOT / EOT / etc. */
80*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_cluster_level_t cluster_level;
81*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t replacement; /* U+FFFD or something else. */
82*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t invisible; /* 0 or something else. */
83*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t not_found; /* 0 or something else. */
84*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t not_found_variation_selector; /* HB_CODEPOINT_INVALID or something else. */
85*2d1272b8SAndroid Build Coastguard Worker 
86*2d1272b8SAndroid Build Coastguard Worker   /*
87*2d1272b8SAndroid Build Coastguard Worker    * Buffer contents
88*2d1272b8SAndroid Build Coastguard Worker    */
89*2d1272b8SAndroid Build Coastguard Worker 
90*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_content_type_t content_type;
91*2d1272b8SAndroid Build Coastguard Worker   hb_segment_properties_t props; /* Script, language, direction */
92*2d1272b8SAndroid Build Coastguard Worker 
93*2d1272b8SAndroid Build Coastguard Worker   bool successful; /* Allocations successful */
94*2d1272b8SAndroid Build Coastguard Worker   bool shaping_failed; /* Shaping failure */
95*2d1272b8SAndroid Build Coastguard Worker   bool have_output; /* Whether we have an output buffer going on */
96*2d1272b8SAndroid Build Coastguard Worker   bool have_positions; /* Whether we have positions */
97*2d1272b8SAndroid Build Coastguard Worker 
98*2d1272b8SAndroid Build Coastguard Worker   unsigned int idx; /* Cursor into ->info and ->pos arrays */
99*2d1272b8SAndroid Build Coastguard Worker   unsigned int len; /* Length of ->info and ->pos arrays */
100*2d1272b8SAndroid Build Coastguard Worker   unsigned int out_len; /* Length of ->out_info array if have_output */
101*2d1272b8SAndroid Build Coastguard Worker 
102*2d1272b8SAndroid Build Coastguard Worker   unsigned int allocated; /* Length of allocated arrays */
103*2d1272b8SAndroid Build Coastguard Worker   hb_glyph_info_t     *info;
104*2d1272b8SAndroid Build Coastguard Worker   hb_glyph_info_t     *out_info;
105*2d1272b8SAndroid Build Coastguard Worker   hb_glyph_position_t *pos;
106*2d1272b8SAndroid Build Coastguard Worker 
107*2d1272b8SAndroid Build Coastguard Worker   /* Text before / after the main buffer contents.
108*2d1272b8SAndroid Build Coastguard Worker    * Always in Unicode, and ordered outward.
109*2d1272b8SAndroid Build Coastguard Worker    * Index 0 is for "pre-context", 1 for "post-context". */
110*2d1272b8SAndroid Build Coastguard Worker   static constexpr unsigned CONTEXT_LENGTH = 5u;
111*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t context[2][CONTEXT_LENGTH];
112*2d1272b8SAndroid Build Coastguard Worker   unsigned int context_len[2];
113*2d1272b8SAndroid Build Coastguard Worker 
114*2d1272b8SAndroid Build Coastguard Worker 
115*2d1272b8SAndroid Build Coastguard Worker   /*
116*2d1272b8SAndroid Build Coastguard Worker    * Managed by enter / leave
117*2d1272b8SAndroid Build Coastguard Worker    */
118*2d1272b8SAndroid Build Coastguard Worker 
119*2d1272b8SAndroid Build Coastguard Worker   uint8_t allocated_var_bits;
120*2d1272b8SAndroid Build Coastguard Worker   uint8_t serial;
121*2d1272b8SAndroid Build Coastguard Worker   uint32_t random_state;
122*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
123*2d1272b8SAndroid Build Coastguard Worker   unsigned int max_len; /* Maximum allowed len. */
124*2d1272b8SAndroid Build Coastguard Worker   int max_ops; /* Maximum allowed operations. */
125*2d1272b8SAndroid Build Coastguard Worker   /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
126*2d1272b8SAndroid Build Coastguard Worker 
127*2d1272b8SAndroid Build Coastguard Worker 
128*2d1272b8SAndroid Build Coastguard Worker   /*
129*2d1272b8SAndroid Build Coastguard Worker    * Messaging callback
130*2d1272b8SAndroid Build Coastguard Worker    */
131*2d1272b8SAndroid Build Coastguard Worker 
132*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BUFFER_MESSAGE
133*2d1272b8SAndroid Build Coastguard Worker   hb_buffer_message_func_t message_func;
134*2d1272b8SAndroid Build Coastguard Worker   void *message_data;
135*2d1272b8SAndroid Build Coastguard Worker   hb_destroy_func_t message_destroy;
136*2d1272b8SAndroid Build Coastguard Worker   unsigned message_depth; /* How deeply are we inside a message callback? */
137*2d1272b8SAndroid Build Coastguard Worker #else
138*2d1272b8SAndroid Build Coastguard Worker   static constexpr unsigned message_depth = 0u;
139*2d1272b8SAndroid Build Coastguard Worker #endif
140*2d1272b8SAndroid Build Coastguard Worker 
141*2d1272b8SAndroid Build Coastguard Worker 
142*2d1272b8SAndroid Build Coastguard Worker 
143*2d1272b8SAndroid Build Coastguard Worker   /* Methods */
144*2d1272b8SAndroid Build Coastguard Worker 
in_errorhb_buffer_t145*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD bool in_error () const { return !successful; }
146*2d1272b8SAndroid Build Coastguard Worker 
allocate_varhb_buffer_t147*2d1272b8SAndroid Build Coastguard Worker   void allocate_var (unsigned int start, unsigned int count)
148*2d1272b8SAndroid Build Coastguard Worker   {
149*2d1272b8SAndroid Build Coastguard Worker     unsigned int end = start + count;
150*2d1272b8SAndroid Build Coastguard Worker     assert (end <= 8);
151*2d1272b8SAndroid Build Coastguard Worker     unsigned int bits = (1u<<end) - (1u<<start);
152*2d1272b8SAndroid Build Coastguard Worker     assert (0 == (allocated_var_bits & bits));
153*2d1272b8SAndroid Build Coastguard Worker     allocated_var_bits |= bits;
154*2d1272b8SAndroid Build Coastguard Worker   }
try_allocate_varhb_buffer_t155*2d1272b8SAndroid Build Coastguard Worker   bool try_allocate_var (unsigned int start, unsigned int count)
156*2d1272b8SAndroid Build Coastguard Worker   {
157*2d1272b8SAndroid Build Coastguard Worker     unsigned int end = start + count;
158*2d1272b8SAndroid Build Coastguard Worker     assert (end <= 8);
159*2d1272b8SAndroid Build Coastguard Worker     unsigned int bits = (1u<<end) - (1u<<start);
160*2d1272b8SAndroid Build Coastguard Worker     if (allocated_var_bits & bits)
161*2d1272b8SAndroid Build Coastguard Worker       return false;
162*2d1272b8SAndroid Build Coastguard Worker     allocated_var_bits |= bits;
163*2d1272b8SAndroid Build Coastguard Worker     return true;
164*2d1272b8SAndroid Build Coastguard Worker   }
deallocate_varhb_buffer_t165*2d1272b8SAndroid Build Coastguard Worker   void deallocate_var (unsigned int start, unsigned int count)
166*2d1272b8SAndroid Build Coastguard Worker   {
167*2d1272b8SAndroid Build Coastguard Worker     unsigned int end = start + count;
168*2d1272b8SAndroid Build Coastguard Worker     assert (end <= 8);
169*2d1272b8SAndroid Build Coastguard Worker     unsigned int bits = (1u<<end) - (1u<<start);
170*2d1272b8SAndroid Build Coastguard Worker     assert (bits == (allocated_var_bits & bits));
171*2d1272b8SAndroid Build Coastguard Worker     allocated_var_bits &= ~bits;
172*2d1272b8SAndroid Build Coastguard Worker   }
assert_varhb_buffer_t173*2d1272b8SAndroid Build Coastguard Worker   void assert_var (unsigned int start, unsigned int count)
174*2d1272b8SAndroid Build Coastguard Worker   {
175*2d1272b8SAndroid Build Coastguard Worker     unsigned int end = start + count;
176*2d1272b8SAndroid Build Coastguard Worker     assert (end <= 8);
177*2d1272b8SAndroid Build Coastguard Worker     HB_UNUSED unsigned int bits = (1u<<end) - (1u<<start);
178*2d1272b8SAndroid Build Coastguard Worker     assert (bits == (allocated_var_bits & bits));
179*2d1272b8SAndroid Build Coastguard Worker   }
deallocate_var_allhb_buffer_t180*2d1272b8SAndroid Build Coastguard Worker   void deallocate_var_all ()
181*2d1272b8SAndroid Build Coastguard Worker   {
182*2d1272b8SAndroid Build Coastguard Worker     allocated_var_bits = 0;
183*2d1272b8SAndroid Build Coastguard Worker   }
184*2d1272b8SAndroid Build Coastguard Worker 
curhb_buffer_t185*2d1272b8SAndroid Build Coastguard Worker   hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
curhb_buffer_t186*2d1272b8SAndroid Build Coastguard Worker   hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
187*2d1272b8SAndroid Build Coastguard Worker 
cur_poshb_buffer_t188*2d1272b8SAndroid Build Coastguard Worker   hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
cur_poshb_buffer_t189*2d1272b8SAndroid Build Coastguard Worker   hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
190*2d1272b8SAndroid Build Coastguard Worker 
prevhb_buffer_t191*2d1272b8SAndroid Build Coastguard Worker   hb_glyph_info_t &prev ()      { return out_info[out_len ? out_len - 1 : 0]; }
prevhb_buffer_t192*2d1272b8SAndroid Build Coastguard Worker   hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
193*2d1272b8SAndroid Build Coastguard Worker 
digesthb_buffer_t194*2d1272b8SAndroid Build Coastguard Worker   hb_set_digest_t digest () const
195*2d1272b8SAndroid Build Coastguard Worker   {
196*2d1272b8SAndroid Build Coastguard Worker     hb_set_digest_t d;
197*2d1272b8SAndroid Build Coastguard Worker     d.init ();
198*2d1272b8SAndroid Build Coastguard Worker     d.add_array (&info[0].codepoint, len, sizeof (info[0]));
199*2d1272b8SAndroid Build Coastguard Worker     return d;
200*2d1272b8SAndroid Build Coastguard Worker   }
201*2d1272b8SAndroid Build Coastguard Worker 
202*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void similar (const hb_buffer_t &src);
203*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void reset ();
204*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void clear ();
205*2d1272b8SAndroid Build Coastguard Worker 
206*2d1272b8SAndroid Build Coastguard Worker   /* Called around shape() */
207*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void enter ();
208*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void leave ();
209*2d1272b8SAndroid Build Coastguard Worker 
210*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BUFFER_VERIFY
211*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL
212*2d1272b8SAndroid Build Coastguard Worker #endif
213*2d1272b8SAndroid Build Coastguard Worker   bool verify (hb_buffer_t        *text_buffer,
214*2d1272b8SAndroid Build Coastguard Worker 	       hb_font_t          *font,
215*2d1272b8SAndroid Build Coastguard Worker 	       const hb_feature_t *features,
216*2d1272b8SAndroid Build Coastguard Worker 	       unsigned int        num_features,
217*2d1272b8SAndroid Build Coastguard Worker 	       const char * const *shapers)
218*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_BUFFER_VERIFY
219*2d1272b8SAndroid Build Coastguard Worker   ;
220*2d1272b8SAndroid Build Coastguard Worker #else
221*2d1272b8SAndroid Build Coastguard Worker   { return true; }
222*2d1272b8SAndroid Build Coastguard Worker #endif
223*2d1272b8SAndroid Build Coastguard Worker 
backtrack_lenhb_buffer_t224*2d1272b8SAndroid Build Coastguard Worker   unsigned int backtrack_len () const { return have_output ? out_len : idx; }
lookahead_lenhb_buffer_t225*2d1272b8SAndroid Build Coastguard Worker   unsigned int lookahead_len () const { return len - idx; }
next_serialhb_buffer_t226*2d1272b8SAndroid Build Coastguard Worker   uint8_t next_serial () { return ++serial ? serial : ++serial; }
227*2d1272b8SAndroid Build Coastguard Worker 
228*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void add (hb_codepoint_t  codepoint,
229*2d1272b8SAndroid Build Coastguard Worker 			unsigned int    cluster);
230*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
231*2d1272b8SAndroid Build Coastguard Worker 
reverse_rangehb_buffer_t232*2d1272b8SAndroid Build Coastguard Worker   void reverse_range (unsigned start, unsigned end)
233*2d1272b8SAndroid Build Coastguard Worker   {
234*2d1272b8SAndroid Build Coastguard Worker     hb_array_t<hb_glyph_info_t> (info, len).reverse (start, end);
235*2d1272b8SAndroid Build Coastguard Worker     if (have_positions)
236*2d1272b8SAndroid Build Coastguard Worker       hb_array_t<hb_glyph_position_t> (pos, len).reverse (start, end);
237*2d1272b8SAndroid Build Coastguard Worker   }
reversehb_buffer_t238*2d1272b8SAndroid Build Coastguard Worker   void reverse () { reverse_range (0, len); }
239*2d1272b8SAndroid Build Coastguard Worker 
240*2d1272b8SAndroid Build Coastguard Worker   template <typename FuncType>
reverse_groupshb_buffer_t241*2d1272b8SAndroid Build Coastguard Worker   void reverse_groups (const FuncType& group,
242*2d1272b8SAndroid Build Coastguard Worker 		       bool merge_clusters = false)
243*2d1272b8SAndroid Build Coastguard Worker   {
244*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!len))
245*2d1272b8SAndroid Build Coastguard Worker       return;
246*2d1272b8SAndroid Build Coastguard Worker 
247*2d1272b8SAndroid Build Coastguard Worker     unsigned start = 0;
248*2d1272b8SAndroid Build Coastguard Worker     unsigned i;
249*2d1272b8SAndroid Build Coastguard Worker     for (i = 1; i < len; i++)
250*2d1272b8SAndroid Build Coastguard Worker     {
251*2d1272b8SAndroid Build Coastguard Worker       if (!group (info[i - 1], info[i]))
252*2d1272b8SAndroid Build Coastguard Worker       {
253*2d1272b8SAndroid Build Coastguard Worker 	if (merge_clusters)
254*2d1272b8SAndroid Build Coastguard Worker 	  this->merge_clusters (start, i);
255*2d1272b8SAndroid Build Coastguard Worker 	reverse_range (start, i);
256*2d1272b8SAndroid Build Coastguard Worker 	start = i;
257*2d1272b8SAndroid Build Coastguard Worker       }
258*2d1272b8SAndroid Build Coastguard Worker     }
259*2d1272b8SAndroid Build Coastguard Worker     if (merge_clusters)
260*2d1272b8SAndroid Build Coastguard Worker       this->merge_clusters (start, i);
261*2d1272b8SAndroid Build Coastguard Worker     reverse_range (start, i);
262*2d1272b8SAndroid Build Coastguard Worker 
263*2d1272b8SAndroid Build Coastguard Worker     reverse ();
264*2d1272b8SAndroid Build Coastguard Worker   }
265*2d1272b8SAndroid Build Coastguard Worker 
266*2d1272b8SAndroid Build Coastguard Worker   template <typename FuncType>
group_endhb_buffer_t267*2d1272b8SAndroid Build Coastguard Worker   unsigned group_end (unsigned start, const FuncType& group) const
268*2d1272b8SAndroid Build Coastguard Worker   {
269*2d1272b8SAndroid Build Coastguard Worker     while (++start < len && group (info[start - 1], info[start]))
270*2d1272b8SAndroid Build Coastguard Worker       ;
271*2d1272b8SAndroid Build Coastguard Worker 
272*2d1272b8SAndroid Build Coastguard Worker     return start;
273*2d1272b8SAndroid Build Coastguard Worker   }
274*2d1272b8SAndroid Build Coastguard Worker 
_cluster_group_funchb_buffer_t275*2d1272b8SAndroid Build Coastguard Worker   static bool _cluster_group_func (const hb_glyph_info_t& a,
276*2d1272b8SAndroid Build Coastguard Worker 				   const hb_glyph_info_t& b)
277*2d1272b8SAndroid Build Coastguard Worker   { return a.cluster == b.cluster; }
278*2d1272b8SAndroid Build Coastguard Worker 
reverse_clustershb_buffer_t279*2d1272b8SAndroid Build Coastguard Worker   void reverse_clusters () { reverse_groups (_cluster_group_func); }
280*2d1272b8SAndroid Build Coastguard Worker 
281*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void guess_segment_properties ();
282*2d1272b8SAndroid Build Coastguard Worker 
283*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL bool sync ();
284*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL int sync_so_far ();
285*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void clear_output ();
286*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void clear_positions ();
287*2d1272b8SAndroid Build Coastguard Worker 
288*2d1272b8SAndroid Build Coastguard Worker   template <typename T>
replace_glyphshb_buffer_t289*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD bool replace_glyphs (unsigned int num_in,
290*2d1272b8SAndroid Build Coastguard Worker 				    unsigned int num_out,
291*2d1272b8SAndroid Build Coastguard Worker 				    const T *glyph_data)
292*2d1272b8SAndroid Build Coastguard Worker   {
293*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!make_room_for (num_in, num_out))) return false;
294*2d1272b8SAndroid Build Coastguard Worker 
295*2d1272b8SAndroid Build Coastguard Worker     assert (idx + num_in <= len);
296*2d1272b8SAndroid Build Coastguard Worker 
297*2d1272b8SAndroid Build Coastguard Worker     merge_clusters (idx, idx + num_in);
298*2d1272b8SAndroid Build Coastguard Worker 
299*2d1272b8SAndroid Build Coastguard Worker     hb_glyph_info_t &orig_info = idx < len ? cur() : prev();
300*2d1272b8SAndroid Build Coastguard Worker 
301*2d1272b8SAndroid Build Coastguard Worker     hb_glyph_info_t *pinfo = &out_info[out_len];
302*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < num_out; i++)
303*2d1272b8SAndroid Build Coastguard Worker     {
304*2d1272b8SAndroid Build Coastguard Worker       *pinfo = orig_info;
305*2d1272b8SAndroid Build Coastguard Worker       pinfo->codepoint = glyph_data[i];
306*2d1272b8SAndroid Build Coastguard Worker       pinfo++;
307*2d1272b8SAndroid Build Coastguard Worker     }
308*2d1272b8SAndroid Build Coastguard Worker 
309*2d1272b8SAndroid Build Coastguard Worker     idx  += num_in;
310*2d1272b8SAndroid Build Coastguard Worker     out_len += num_out;
311*2d1272b8SAndroid Build Coastguard Worker     return true;
312*2d1272b8SAndroid Build Coastguard Worker   }
313*2d1272b8SAndroid Build Coastguard Worker 
replace_glyphhb_buffer_t314*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD bool replace_glyph (hb_codepoint_t glyph_index)
315*2d1272b8SAndroid Build Coastguard Worker   { return replace_glyphs (1, 1, &glyph_index); }
316*2d1272b8SAndroid Build Coastguard Worker 
317*2d1272b8SAndroid Build Coastguard Worker   /* Makes a copy of the glyph at idx to output and replace glyph_index */
output_glyphhb_buffer_t318*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD bool output_glyph (hb_codepoint_t glyph_index)
319*2d1272b8SAndroid Build Coastguard Worker   { return replace_glyphs (0, 1, &glyph_index); }
320*2d1272b8SAndroid Build Coastguard Worker 
output_infohb_buffer_t321*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD bool output_info (const hb_glyph_info_t &glyph_info)
322*2d1272b8SAndroid Build Coastguard Worker   {
323*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!make_room_for (0, 1))) return false;
324*2d1272b8SAndroid Build Coastguard Worker 
325*2d1272b8SAndroid Build Coastguard Worker     out_info[out_len] = glyph_info;
326*2d1272b8SAndroid Build Coastguard Worker 
327*2d1272b8SAndroid Build Coastguard Worker     out_len++;
328*2d1272b8SAndroid Build Coastguard Worker     return true;
329*2d1272b8SAndroid Build Coastguard Worker   }
330*2d1272b8SAndroid Build Coastguard Worker   /* Copies glyph at idx to output but doesn't advance idx */
copy_glyphhb_buffer_t331*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD bool copy_glyph ()
332*2d1272b8SAndroid Build Coastguard Worker   {
333*2d1272b8SAndroid Build Coastguard Worker     /* Extra copy because cur()'s return can be freed within
334*2d1272b8SAndroid Build Coastguard Worker      * output_info() call if buffer reallocates. */
335*2d1272b8SAndroid Build Coastguard Worker     return output_info (hb_glyph_info_t (cur()));
336*2d1272b8SAndroid Build Coastguard Worker   }
337*2d1272b8SAndroid Build Coastguard Worker 
338*2d1272b8SAndroid Build Coastguard Worker   /* Copies glyph at idx to output and advance idx.
339*2d1272b8SAndroid Build Coastguard Worker    * If there's no output, just advance idx. */
next_glyphhb_buffer_t340*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD bool next_glyph ()
341*2d1272b8SAndroid Build Coastguard Worker   {
342*2d1272b8SAndroid Build Coastguard Worker     if (have_output)
343*2d1272b8SAndroid Build Coastguard Worker     {
344*2d1272b8SAndroid Build Coastguard Worker       if (out_info != info || out_len != idx)
345*2d1272b8SAndroid Build Coastguard Worker       {
346*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely (!make_room_for (1, 1))) return false;
347*2d1272b8SAndroid Build Coastguard Worker 	out_info[out_len] = info[idx];
348*2d1272b8SAndroid Build Coastguard Worker       }
349*2d1272b8SAndroid Build Coastguard Worker       out_len++;
350*2d1272b8SAndroid Build Coastguard Worker     }
351*2d1272b8SAndroid Build Coastguard Worker 
352*2d1272b8SAndroid Build Coastguard Worker     idx++;
353*2d1272b8SAndroid Build Coastguard Worker     return true;
354*2d1272b8SAndroid Build Coastguard Worker   }
355*2d1272b8SAndroid Build Coastguard Worker   /* Copies n glyphs at idx to output and advance idx.
356*2d1272b8SAndroid Build Coastguard Worker    * If there's no output, just advance idx. */
next_glyphshb_buffer_t357*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD bool next_glyphs (unsigned int n)
358*2d1272b8SAndroid Build Coastguard Worker   {
359*2d1272b8SAndroid Build Coastguard Worker     if (have_output)
360*2d1272b8SAndroid Build Coastguard Worker     {
361*2d1272b8SAndroid Build Coastguard Worker       if (out_info != info || out_len != idx)
362*2d1272b8SAndroid Build Coastguard Worker       {
363*2d1272b8SAndroid Build Coastguard Worker 	if (unlikely (!make_room_for (n, n))) return false;
364*2d1272b8SAndroid Build Coastguard Worker 	memmove (out_info + out_len, info + idx, n * sizeof (out_info[0]));
365*2d1272b8SAndroid Build Coastguard Worker       }
366*2d1272b8SAndroid Build Coastguard Worker       out_len += n;
367*2d1272b8SAndroid Build Coastguard Worker     }
368*2d1272b8SAndroid Build Coastguard Worker 
369*2d1272b8SAndroid Build Coastguard Worker     idx += n;
370*2d1272b8SAndroid Build Coastguard Worker     return true;
371*2d1272b8SAndroid Build Coastguard Worker   }
372*2d1272b8SAndroid Build Coastguard Worker   /* Advance idx without copying to output. */
skip_glyphhb_buffer_t373*2d1272b8SAndroid Build Coastguard Worker   void skip_glyph () { idx++; }
reset_maskshb_buffer_t374*2d1272b8SAndroid Build Coastguard Worker   void reset_masks (hb_mask_t mask)
375*2d1272b8SAndroid Build Coastguard Worker   {
376*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int j = 0; j < len; j++)
377*2d1272b8SAndroid Build Coastguard Worker       info[j].mask = mask;
378*2d1272b8SAndroid Build Coastguard Worker   }
add_maskshb_buffer_t379*2d1272b8SAndroid Build Coastguard Worker   void add_masks (hb_mask_t mask)
380*2d1272b8SAndroid Build Coastguard Worker   {
381*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int j = 0; j < len; j++)
382*2d1272b8SAndroid Build Coastguard Worker       info[j].mask |= mask;
383*2d1272b8SAndroid Build Coastguard Worker   }
384*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask,
385*2d1272b8SAndroid Build Coastguard Worker 			      unsigned int cluster_start, unsigned int cluster_end);
386*2d1272b8SAndroid Build Coastguard Worker 
merge_clustershb_buffer_t387*2d1272b8SAndroid Build Coastguard Worker   void merge_clusters (unsigned int start, unsigned int end)
388*2d1272b8SAndroid Build Coastguard Worker   {
389*2d1272b8SAndroid Build Coastguard Worker     if (end - start < 2)
390*2d1272b8SAndroid Build Coastguard Worker       return;
391*2d1272b8SAndroid Build Coastguard Worker     merge_clusters_impl (start, end);
392*2d1272b8SAndroid Build Coastguard Worker   }
393*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end);
394*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
395*2d1272b8SAndroid Build Coastguard Worker   /* Merge clusters for deleting current glyph, and skip it. */
396*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void delete_glyph ();
397*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void delete_glyphs_inplace (bool (*filter) (const hb_glyph_info_t *info));
398*2d1272b8SAndroid Build Coastguard Worker 
399*2d1272b8SAndroid Build Coastguard Worker 
400*2d1272b8SAndroid Build Coastguard Worker 
401*2d1272b8SAndroid Build Coastguard Worker   /* Adds glyph flags in mask to infos with clusters between start and end.
402*2d1272b8SAndroid Build Coastguard Worker    * The start index will be from out-buffer if from_out_buffer is true.
403*2d1272b8SAndroid Build Coastguard Worker    * If interior is true, then the cluster having the minimum value is skipped. */
_set_glyph_flagshb_buffer_t404*2d1272b8SAndroid Build Coastguard Worker   void _set_glyph_flags (hb_mask_t mask,
405*2d1272b8SAndroid Build Coastguard Worker 			 unsigned start = 0,
406*2d1272b8SAndroid Build Coastguard Worker 			 unsigned end = (unsigned) -1,
407*2d1272b8SAndroid Build Coastguard Worker 			 bool interior = false,
408*2d1272b8SAndroid Build Coastguard Worker 			 bool from_out_buffer = false)
409*2d1272b8SAndroid Build Coastguard Worker   {
410*2d1272b8SAndroid Build Coastguard Worker     end = hb_min (end, len);
411*2d1272b8SAndroid Build Coastguard Worker 
412*2d1272b8SAndroid Build Coastguard Worker     if (interior && !from_out_buffer && end - start < 2)
413*2d1272b8SAndroid Build Coastguard Worker       return;
414*2d1272b8SAndroid Build Coastguard Worker 
415*2d1272b8SAndroid Build Coastguard Worker     scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
416*2d1272b8SAndroid Build Coastguard Worker 
417*2d1272b8SAndroid Build Coastguard Worker     if (!from_out_buffer || !have_output)
418*2d1272b8SAndroid Build Coastguard Worker     {
419*2d1272b8SAndroid Build Coastguard Worker       if (!interior)
420*2d1272b8SAndroid Build Coastguard Worker       {
421*2d1272b8SAndroid Build Coastguard Worker 	for (unsigned i = start; i < end; i++)
422*2d1272b8SAndroid Build Coastguard Worker 	  info[i].mask |= mask;
423*2d1272b8SAndroid Build Coastguard Worker       }
424*2d1272b8SAndroid Build Coastguard Worker       else
425*2d1272b8SAndroid Build Coastguard Worker       {
426*2d1272b8SAndroid Build Coastguard Worker 	unsigned cluster = _infos_find_min_cluster (info, start, end);
427*2d1272b8SAndroid Build Coastguard Worker 	_infos_set_glyph_flags (info, start, end, cluster, mask);
428*2d1272b8SAndroid Build Coastguard Worker       }
429*2d1272b8SAndroid Build Coastguard Worker     }
430*2d1272b8SAndroid Build Coastguard Worker     else
431*2d1272b8SAndroid Build Coastguard Worker     {
432*2d1272b8SAndroid Build Coastguard Worker       assert (start <= out_len);
433*2d1272b8SAndroid Build Coastguard Worker       assert (idx <= end);
434*2d1272b8SAndroid Build Coastguard Worker 
435*2d1272b8SAndroid Build Coastguard Worker       if (!interior)
436*2d1272b8SAndroid Build Coastguard Worker       {
437*2d1272b8SAndroid Build Coastguard Worker 	for (unsigned i = start; i < out_len; i++)
438*2d1272b8SAndroid Build Coastguard Worker 	  out_info[i].mask |= mask;
439*2d1272b8SAndroid Build Coastguard Worker 	for (unsigned i = idx; i < end; i++)
440*2d1272b8SAndroid Build Coastguard Worker 	  info[i].mask |= mask;
441*2d1272b8SAndroid Build Coastguard Worker       }
442*2d1272b8SAndroid Build Coastguard Worker       else
443*2d1272b8SAndroid Build Coastguard Worker       {
444*2d1272b8SAndroid Build Coastguard Worker 	unsigned cluster = _infos_find_min_cluster (info, idx, end);
445*2d1272b8SAndroid Build Coastguard Worker 	cluster = _infos_find_min_cluster (out_info, start, out_len, cluster);
446*2d1272b8SAndroid Build Coastguard Worker 
447*2d1272b8SAndroid Build Coastguard Worker 	_infos_set_glyph_flags (out_info, start, out_len, cluster, mask);
448*2d1272b8SAndroid Build Coastguard Worker 	_infos_set_glyph_flags (info, idx, end, cluster, mask);
449*2d1272b8SAndroid Build Coastguard Worker       }
450*2d1272b8SAndroid Build Coastguard Worker     }
451*2d1272b8SAndroid Build Coastguard Worker   }
452*2d1272b8SAndroid Build Coastguard Worker 
unsafe_to_breakhb_buffer_t453*2d1272b8SAndroid Build Coastguard Worker   void unsafe_to_break (unsigned int start = 0, unsigned int end = -1)
454*2d1272b8SAndroid Build Coastguard Worker   {
455*2d1272b8SAndroid Build Coastguard Worker     _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
456*2d1272b8SAndroid Build Coastguard Worker 		      start, end,
457*2d1272b8SAndroid Build Coastguard Worker 		      true);
458*2d1272b8SAndroid Build Coastguard Worker   }
safe_to_insert_tatweelhb_buffer_t459*2d1272b8SAndroid Build Coastguard Worker   void safe_to_insert_tatweel (unsigned int start = 0, unsigned int end = -1)
460*2d1272b8SAndroid Build Coastguard Worker   {
461*2d1272b8SAndroid Build Coastguard Worker     if ((flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL) == 0)
462*2d1272b8SAndroid Build Coastguard Worker     {
463*2d1272b8SAndroid Build Coastguard Worker       unsafe_to_break (start, end);
464*2d1272b8SAndroid Build Coastguard Worker       return;
465*2d1272b8SAndroid Build Coastguard Worker     }
466*2d1272b8SAndroid Build Coastguard Worker     _set_glyph_flags (HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL,
467*2d1272b8SAndroid Build Coastguard Worker 		      start, end,
468*2d1272b8SAndroid Build Coastguard Worker 		      true);
469*2d1272b8SAndroid Build Coastguard Worker   }
470*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_OPTIMIZE_SIZE
471*2d1272b8SAndroid Build Coastguard Worker   HB_ALWAYS_INLINE
472*2d1272b8SAndroid Build Coastguard Worker #endif
unsafe_to_concathb_buffer_t473*2d1272b8SAndroid Build Coastguard Worker   void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1)
474*2d1272b8SAndroid Build Coastguard Worker   {
475*2d1272b8SAndroid Build Coastguard Worker     if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
476*2d1272b8SAndroid Build Coastguard Worker       return;
477*2d1272b8SAndroid Build Coastguard Worker     _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
478*2d1272b8SAndroid Build Coastguard Worker 		      start, end,
479*2d1272b8SAndroid Build Coastguard Worker 		      false);
480*2d1272b8SAndroid Build Coastguard Worker   }
unsafe_to_break_from_outbufferhb_buffer_t481*2d1272b8SAndroid Build Coastguard Worker   void unsafe_to_break_from_outbuffer (unsigned int start = 0, unsigned int end = -1)
482*2d1272b8SAndroid Build Coastguard Worker   {
483*2d1272b8SAndroid Build Coastguard Worker     _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
484*2d1272b8SAndroid Build Coastguard Worker 		      start, end,
485*2d1272b8SAndroid Build Coastguard Worker 		      true, true);
486*2d1272b8SAndroid Build Coastguard Worker   }
487*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_OPTIMIZE_SIZE
488*2d1272b8SAndroid Build Coastguard Worker   HB_ALWAYS_INLINE
489*2d1272b8SAndroid Build Coastguard Worker #endif
unsafe_to_concat_from_outbufferhb_buffer_t490*2d1272b8SAndroid Build Coastguard Worker   void unsafe_to_concat_from_outbuffer (unsigned int start = 0, unsigned int end = -1)
491*2d1272b8SAndroid Build Coastguard Worker   {
492*2d1272b8SAndroid Build Coastguard Worker     if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
493*2d1272b8SAndroid Build Coastguard Worker       return;
494*2d1272b8SAndroid Build Coastguard Worker     _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
495*2d1272b8SAndroid Build Coastguard Worker 		      start, end,
496*2d1272b8SAndroid Build Coastguard Worker 		      false, true);
497*2d1272b8SAndroid Build Coastguard Worker   }
498*2d1272b8SAndroid Build Coastguard Worker 
499*2d1272b8SAndroid Build Coastguard Worker 
500*2d1272b8SAndroid Build Coastguard Worker   /* Internal methods */
501*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */
502*2d1272b8SAndroid Build Coastguard Worker 
503*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD HB_INTERNAL bool enlarge (unsigned int size);
504*2d1272b8SAndroid Build Coastguard Worker 
resizehb_buffer_t505*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD bool resize (unsigned length)
506*2d1272b8SAndroid Build Coastguard Worker   {
507*2d1272b8SAndroid Build Coastguard Worker     assert (!have_output);
508*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!ensure (length))) return false;
509*2d1272b8SAndroid Build Coastguard Worker     len = length;
510*2d1272b8SAndroid Build Coastguard Worker     return true;
511*2d1272b8SAndroid Build Coastguard Worker   }
ensurehb_buffer_t512*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD bool ensure (unsigned int size)
513*2d1272b8SAndroid Build Coastguard Worker   { return likely (!size || size < allocated) ? true : enlarge (size); }
514*2d1272b8SAndroid Build Coastguard Worker 
ensure_inplacehb_buffer_t515*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD bool ensure_inplace (unsigned int size)
516*2d1272b8SAndroid Build Coastguard Worker   { return likely (!size || size < allocated); }
517*2d1272b8SAndroid Build Coastguard Worker 
assert_glyphshb_buffer_t518*2d1272b8SAndroid Build Coastguard Worker   void assert_glyphs ()
519*2d1272b8SAndroid Build Coastguard Worker   {
520*2d1272b8SAndroid Build Coastguard Worker     assert ((content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS) ||
521*2d1272b8SAndroid Build Coastguard Worker 	    (!len && (content_type == HB_BUFFER_CONTENT_TYPE_INVALID)));
522*2d1272b8SAndroid Build Coastguard Worker   }
assert_unicodehb_buffer_t523*2d1272b8SAndroid Build Coastguard Worker   void assert_unicode ()
524*2d1272b8SAndroid Build Coastguard Worker   {
525*2d1272b8SAndroid Build Coastguard Worker     assert ((content_type == HB_BUFFER_CONTENT_TYPE_UNICODE) ||
526*2d1272b8SAndroid Build Coastguard Worker 	    (!len && (content_type == HB_BUFFER_CONTENT_TYPE_INVALID)));
527*2d1272b8SAndroid Build Coastguard Worker   }
ensure_glyphshb_buffer_t528*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD bool ensure_glyphs ()
529*2d1272b8SAndroid Build Coastguard Worker   {
530*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (content_type != HB_BUFFER_CONTENT_TYPE_GLYPHS))
531*2d1272b8SAndroid Build Coastguard Worker     {
532*2d1272b8SAndroid Build Coastguard Worker       if (content_type != HB_BUFFER_CONTENT_TYPE_INVALID)
533*2d1272b8SAndroid Build Coastguard Worker 	return false;
534*2d1272b8SAndroid Build Coastguard Worker       assert (len == 0);
535*2d1272b8SAndroid Build Coastguard Worker       content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
536*2d1272b8SAndroid Build Coastguard Worker     }
537*2d1272b8SAndroid Build Coastguard Worker     return true;
538*2d1272b8SAndroid Build Coastguard Worker   }
ensure_unicodehb_buffer_t539*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD bool ensure_unicode ()
540*2d1272b8SAndroid Build Coastguard Worker   {
541*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (content_type != HB_BUFFER_CONTENT_TYPE_UNICODE))
542*2d1272b8SAndroid Build Coastguard Worker     {
543*2d1272b8SAndroid Build Coastguard Worker       if (content_type != HB_BUFFER_CONTENT_TYPE_INVALID)
544*2d1272b8SAndroid Build Coastguard Worker 	return false;
545*2d1272b8SAndroid Build Coastguard Worker       assert (len == 0);
546*2d1272b8SAndroid Build Coastguard Worker       content_type = HB_BUFFER_CONTENT_TYPE_UNICODE;
547*2d1272b8SAndroid Build Coastguard Worker     }
548*2d1272b8SAndroid Build Coastguard Worker     return true;
549*2d1272b8SAndroid Build Coastguard Worker   }
550*2d1272b8SAndroid Build Coastguard Worker 
551*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
552*2d1272b8SAndroid Build Coastguard Worker   HB_NODISCARD HB_INTERNAL bool shift_forward (unsigned int count);
553*2d1272b8SAndroid Build Coastguard Worker 
554*2d1272b8SAndroid Build Coastguard Worker   typedef long scratch_buffer_t;
555*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);
556*2d1272b8SAndroid Build Coastguard Worker 
clear_contexthb_buffer_t557*2d1272b8SAndroid Build Coastguard Worker   void clear_context (unsigned int side) { context_len[side] = 0; }
558*2d1272b8SAndroid Build Coastguard Worker 
559*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
560*2d1272b8SAndroid Build Coastguard Worker 
messaginghb_buffer_t561*2d1272b8SAndroid Build Coastguard Worker   bool messaging ()
562*2d1272b8SAndroid Build Coastguard Worker   {
563*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_NO_BUFFER_MESSAGE
564*2d1272b8SAndroid Build Coastguard Worker     return false;
565*2d1272b8SAndroid Build Coastguard Worker #else
566*2d1272b8SAndroid Build Coastguard Worker     return unlikely (message_func);
567*2d1272b8SAndroid Build Coastguard Worker #endif
568*2d1272b8SAndroid Build Coastguard Worker   }
messagehb_buffer_t569*2d1272b8SAndroid Build Coastguard Worker   bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
570*2d1272b8SAndroid Build Coastguard Worker   {
571*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_NO_BUFFER_MESSAGE
572*2d1272b8SAndroid Build Coastguard Worker     return true;
573*2d1272b8SAndroid Build Coastguard Worker #else
574*2d1272b8SAndroid Build Coastguard Worker     if (likely (!messaging ()))
575*2d1272b8SAndroid Build Coastguard Worker       return true;
576*2d1272b8SAndroid Build Coastguard Worker 
577*2d1272b8SAndroid Build Coastguard Worker     va_list ap;
578*2d1272b8SAndroid Build Coastguard Worker     va_start (ap, fmt);
579*2d1272b8SAndroid Build Coastguard Worker     bool ret = message_impl (font, fmt, ap);
580*2d1272b8SAndroid Build Coastguard Worker     va_end (ap);
581*2d1272b8SAndroid Build Coastguard Worker 
582*2d1272b8SAndroid Build Coastguard Worker     return ret;
583*2d1272b8SAndroid Build Coastguard Worker #endif
584*2d1272b8SAndroid Build Coastguard Worker   }
585*2d1272b8SAndroid Build Coastguard Worker   HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
586*2d1272b8SAndroid Build Coastguard Worker 
587*2d1272b8SAndroid Build Coastguard Worker   static void
set_clusterhb_buffer_t588*2d1272b8SAndroid Build Coastguard Worker   set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
589*2d1272b8SAndroid Build Coastguard Worker   {
590*2d1272b8SAndroid Build Coastguard Worker     if (inf.cluster != cluster)
591*2d1272b8SAndroid Build Coastguard Worker       inf.mask = (inf.mask & ~HB_GLYPH_FLAG_DEFINED) | (mask & HB_GLYPH_FLAG_DEFINED);
592*2d1272b8SAndroid Build Coastguard Worker     inf.cluster = cluster;
593*2d1272b8SAndroid Build Coastguard Worker   }
594*2d1272b8SAndroid Build Coastguard Worker   void
_infos_set_glyph_flagshb_buffer_t595*2d1272b8SAndroid Build Coastguard Worker   _infos_set_glyph_flags (hb_glyph_info_t *infos,
596*2d1272b8SAndroid Build Coastguard Worker 			  unsigned int start, unsigned int end,
597*2d1272b8SAndroid Build Coastguard Worker 			  unsigned int cluster,
598*2d1272b8SAndroid Build Coastguard Worker 			  hb_mask_t mask)
599*2d1272b8SAndroid Build Coastguard Worker   {
600*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (start == end))
601*2d1272b8SAndroid Build Coastguard Worker       return;
602*2d1272b8SAndroid Build Coastguard Worker 
603*2d1272b8SAndroid Build Coastguard Worker     unsigned cluster_first = infos[start].cluster;
604*2d1272b8SAndroid Build Coastguard Worker     unsigned cluster_last = infos[end - 1].cluster;
605*2d1272b8SAndroid Build Coastguard Worker 
606*2d1272b8SAndroid Build Coastguard Worker     if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS ||
607*2d1272b8SAndroid Build Coastguard Worker 	(cluster != cluster_first && cluster != cluster_last))
608*2d1272b8SAndroid Build Coastguard Worker     {
609*2d1272b8SAndroid Build Coastguard Worker       for (unsigned int i = start; i < end; i++)
610*2d1272b8SAndroid Build Coastguard Worker 	if (cluster != infos[i].cluster)
611*2d1272b8SAndroid Build Coastguard Worker 	{
612*2d1272b8SAndroid Build Coastguard Worker 	  scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
613*2d1272b8SAndroid Build Coastguard Worker 	  infos[i].mask |= mask;
614*2d1272b8SAndroid Build Coastguard Worker 	}
615*2d1272b8SAndroid Build Coastguard Worker       return;
616*2d1272b8SAndroid Build Coastguard Worker     }
617*2d1272b8SAndroid Build Coastguard Worker 
618*2d1272b8SAndroid Build Coastguard Worker     /* Monotone clusters */
619*2d1272b8SAndroid Build Coastguard Worker 
620*2d1272b8SAndroid Build Coastguard Worker     if (cluster == cluster_first)
621*2d1272b8SAndroid Build Coastguard Worker     {
622*2d1272b8SAndroid Build Coastguard Worker       for (unsigned int i = end; start < i && infos[i - 1].cluster != cluster_first; i--)
623*2d1272b8SAndroid Build Coastguard Worker       {
624*2d1272b8SAndroid Build Coastguard Worker 	scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
625*2d1272b8SAndroid Build Coastguard Worker 	infos[i - 1].mask |= mask;
626*2d1272b8SAndroid Build Coastguard Worker       }
627*2d1272b8SAndroid Build Coastguard Worker     }
628*2d1272b8SAndroid Build Coastguard Worker     else /* cluster == cluster_last */
629*2d1272b8SAndroid Build Coastguard Worker     {
630*2d1272b8SAndroid Build Coastguard Worker       for (unsigned int i = start; i < end && infos[i].cluster != cluster_last; i++)
631*2d1272b8SAndroid Build Coastguard Worker       {
632*2d1272b8SAndroid Build Coastguard Worker 	scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
633*2d1272b8SAndroid Build Coastguard Worker 	infos[i].mask |= mask;
634*2d1272b8SAndroid Build Coastguard Worker       }
635*2d1272b8SAndroid Build Coastguard Worker     }
636*2d1272b8SAndroid Build Coastguard Worker   }
637*2d1272b8SAndroid Build Coastguard Worker   unsigned
_infos_find_min_clusterhb_buffer_t638*2d1272b8SAndroid Build Coastguard Worker   _infos_find_min_cluster (const hb_glyph_info_t *infos,
639*2d1272b8SAndroid Build Coastguard Worker 			   unsigned start, unsigned end,
640*2d1272b8SAndroid Build Coastguard Worker 			   unsigned cluster = UINT_MAX)
641*2d1272b8SAndroid Build Coastguard Worker   {
642*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (start == end))
643*2d1272b8SAndroid Build Coastguard Worker       return cluster;
644*2d1272b8SAndroid Build Coastguard Worker 
645*2d1272b8SAndroid Build Coastguard Worker     if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
646*2d1272b8SAndroid Build Coastguard Worker     {
647*2d1272b8SAndroid Build Coastguard Worker       for (unsigned int i = start; i < end; i++)
648*2d1272b8SAndroid Build Coastguard Worker 	cluster = hb_min (cluster, infos[i].cluster);
649*2d1272b8SAndroid Build Coastguard Worker       return cluster;
650*2d1272b8SAndroid Build Coastguard Worker     }
651*2d1272b8SAndroid Build Coastguard Worker 
652*2d1272b8SAndroid Build Coastguard Worker     return hb_min (cluster, hb_min (infos[start].cluster, infos[end - 1].cluster));
653*2d1272b8SAndroid Build Coastguard Worker   }
654*2d1272b8SAndroid Build Coastguard Worker 
clear_glyph_flagshb_buffer_t655*2d1272b8SAndroid Build Coastguard Worker   void clear_glyph_flags (hb_mask_t mask = 0)
656*2d1272b8SAndroid Build Coastguard Worker   {
657*2d1272b8SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < len; i++)
658*2d1272b8SAndroid Build Coastguard Worker       info[i].mask = (info[i].mask & ~HB_GLYPH_FLAG_DEFINED) | (mask & HB_GLYPH_FLAG_DEFINED);
659*2d1272b8SAndroid Build Coastguard Worker   }
660*2d1272b8SAndroid Build Coastguard Worker };
661*2d1272b8SAndroid Build Coastguard Worker DECLARE_NULL_INSTANCE (hb_buffer_t);
662*2d1272b8SAndroid Build Coastguard Worker 
663*2d1272b8SAndroid Build Coastguard Worker 
664*2d1272b8SAndroid Build Coastguard Worker #define foreach_group(buffer, start, end, group_func) \
665*2d1272b8SAndroid Build Coastguard Worker   for (unsigned int \
666*2d1272b8SAndroid Build Coastguard Worker        _count = buffer->len, \
667*2d1272b8SAndroid Build Coastguard Worker        start = 0, end = _count ? buffer->group_end (0, group_func) : 0; \
668*2d1272b8SAndroid Build Coastguard Worker        start < _count; \
669*2d1272b8SAndroid Build Coastguard Worker        start = end, end = buffer->group_end (start, group_func))
670*2d1272b8SAndroid Build Coastguard Worker 
671*2d1272b8SAndroid Build Coastguard Worker #define foreach_cluster(buffer, start, end) \
672*2d1272b8SAndroid Build Coastguard Worker 	foreach_group (buffer, start, end, hb_buffer_t::_cluster_group_func)
673*2d1272b8SAndroid Build Coastguard Worker 
674*2d1272b8SAndroid Build Coastguard Worker 
675*2d1272b8SAndroid Build Coastguard Worker #define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
676*2d1272b8SAndroid Build Coastguard Worker   b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
677*2d1272b8SAndroid Build Coastguard Worker 	   sizeof (b->info[0].var))
678*2d1272b8SAndroid Build Coastguard Worker #define HB_BUFFER_ALLOCATE_VAR(b, var)		HB_BUFFER_XALLOCATE_VAR (b, allocate_var,     var ())
679*2d1272b8SAndroid Build Coastguard Worker #define HB_BUFFER_TRY_ALLOCATE_VAR(b, var)	HB_BUFFER_XALLOCATE_VAR (b, try_allocate_var, var ())
680*2d1272b8SAndroid Build Coastguard Worker #define HB_BUFFER_DEALLOCATE_VAR(b, var)	HB_BUFFER_XALLOCATE_VAR (b, deallocate_var,   var ())
681*2d1272b8SAndroid Build Coastguard Worker #define HB_BUFFER_ASSERT_VAR(b, var)		HB_BUFFER_XALLOCATE_VAR (b, assert_var,       var ())
682*2d1272b8SAndroid Build Coastguard Worker 
683*2d1272b8SAndroid Build Coastguard Worker 
684*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_BUFFER_HH */
685