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