Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright  1998-2004  David Turner and Werner Lemberg
      3  * Copyright  2004,2007,2009,2010  Red Hat, Inc.
      4  * Copyright  2011,2012  Google, Inc.
      5  *
      6  *  This is part of HarfBuzz, a text shaping library.
      7  *
      8  * Permission is hereby granted, without written agreement and without
      9  * license or royalty fees, to use, copy, modify, and distribute this
     10  * software and its documentation for any purpose, provided that the
     11  * above copyright notice and the following two paragraphs appear in
     12  * all copies of this software.
     13  *
     14  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     15  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     16  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     17  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     18  * DAMAGE.
     19  *
     20  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     21  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     22  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     23  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     24  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     25  *
     26  * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
     27  * Google Author(s): Behdad Esfahbod
     28  */
     29 
     30 #ifndef HB_BUFFER_HH
     31 #define HB_BUFFER_HH
     32 
     33 #include "hb.hh"
     34 #include "hb-unicode.hh"
     35 
     36 
     37 #ifndef HB_BUFFER_MAX_LEN_FACTOR
     38 #define HB_BUFFER_MAX_LEN_FACTOR 32
     39 #endif
     40 #ifndef HB_BUFFER_MAX_LEN_MIN
     41 #define HB_BUFFER_MAX_LEN_MIN 8192
     42 #endif
     43 #ifndef HB_BUFFER_MAX_LEN_DEFAULT
     44 #define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
     45 #endif
     46 
     47 #ifndef HB_BUFFER_MAX_OPS_FACTOR
     48 #define HB_BUFFER_MAX_OPS_FACTOR 64
     49 #endif
     50 #ifndef HB_BUFFER_MAX_OPS_MIN
     51 #define HB_BUFFER_MAX_OPS_MIN 1024
     52 #endif
     53 #ifndef HB_BUFFER_MAX_OPS_DEFAULT
     54 #define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */
     55 #endif
     56 
     57 static_assert ((sizeof (hb_glyph_info_t) == 20), "");
     58 static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
     59 
     60 HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
     61 HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
     62 HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
     63 
     64 enum hb_buffer_scratch_flags_t {
     65   HB_BUFFER_SCRATCH_FLAG_DEFAULT			= 0x00000000u,
     66   HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII			= 0x00000001u,
     67   HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES		= 0x00000002u,
     68   HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK		= 0x00000004u,
     69   HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT		= 0x00000008u,
     70   HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK		= 0x00000010u,
     71   HB_BUFFER_SCRATCH_FLAG_HAS_CGJ			= 0x00000020u,
     72 
     73   /* Reserved for complex shapers' internal use. */
     74   HB_BUFFER_SCRATCH_FLAG_COMPLEX0			= 0x01000000u,
     75   HB_BUFFER_SCRATCH_FLAG_COMPLEX1			= 0x02000000u,
     76   HB_BUFFER_SCRATCH_FLAG_COMPLEX2			= 0x04000000u,
     77   HB_BUFFER_SCRATCH_FLAG_COMPLEX3			= 0x08000000u,
     78 };
     79 HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
     80 
     81 
     82 /*
     83  * hb_buffer_t
     84  */
     85 
     86 struct hb_buffer_t
     87 {
     88   hb_object_header_t header;
     89 
     90   /* Information about how the text in the buffer should be treated */
     91   hb_unicode_funcs_t *unicode; /* Unicode functions */
     92   hb_buffer_flags_t flags; /* BOT / EOT / etc. */
     93   hb_buffer_cluster_level_t cluster_level;
     94   hb_codepoint_t replacement; /* U+FFFD or something else. */
     95   hb_codepoint_t invisible; /* 0 or something else. */
     96   hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
     97   unsigned int max_len; /* Maximum allowed len. */
     98   int max_ops; /* Maximum allowed operations. */
     99 
    100   /* Buffer contents */
    101   hb_buffer_content_type_t content_type;
    102   hb_segment_properties_t props; /* Script, language, direction */
    103 
    104   bool successful; /* Allocations successful */
    105   bool have_output; /* Whether we have an output buffer going on */
    106   bool have_positions; /* Whether we have positions */
    107 
    108   unsigned int idx; /* Cursor into ->info and ->pos arrays */
    109   unsigned int len; /* Length of ->info and ->pos arrays */
    110   unsigned int out_len; /* Length of ->out array if have_output */
    111 
    112   unsigned int allocated; /* Length of allocated arrays */
    113   hb_glyph_info_t     *info;
    114   hb_glyph_info_t     *out_info;
    115   hb_glyph_position_t *pos;
    116 
    117   unsigned int serial;
    118 
    119   /* Text before / after the main buffer contents.
    120    * Always in Unicode, and ordered outward.
    121    * Index 0 is for "pre-context", 1 for "post-context". */
    122   enum { CONTEXT_LENGTH = 5 };
    123   hb_codepoint_t context[2][CONTEXT_LENGTH];
    124   unsigned int context_len[2];
    125 
    126   /* Debugging API */
    127   hb_buffer_message_func_t message_func;
    128   void *message_data;
    129   hb_destroy_func_t message_destroy;
    130 
    131   /* Internal debugging. */
    132   /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
    133 #ifndef HB_NDEBUG
    134   uint8_t allocated_var_bits;
    135 #endif
    136 
    137 
    138   /* Methods */
    139 
    140   bool in_error () const { return !successful; }
    141 
    142   void allocate_var (unsigned int start, unsigned int count)
    143   {
    144 #ifndef HB_NDEBUG
    145     unsigned int end = start + count;
    146     assert (end <= 8);
    147     unsigned int bits = (1u<<end) - (1u<<start);
    148     assert (0 == (allocated_var_bits & bits));
    149     allocated_var_bits |= bits;
    150 #endif
    151   }
    152   void deallocate_var (unsigned int start, unsigned int count)
    153   {
    154 #ifndef HB_NDEBUG
    155     unsigned int end = start + count;
    156     assert (end <= 8);
    157     unsigned int bits = (1u<<end) - (1u<<start);
    158     assert (bits == (allocated_var_bits & bits));
    159     allocated_var_bits &= ~bits;
    160 #endif
    161   }
    162   void assert_var (unsigned int start, unsigned int count)
    163   {
    164 #ifndef HB_NDEBUG
    165     unsigned int end = start + count;
    166     assert (end <= 8);
    167     unsigned int bits = (1u<<end) - (1u<<start);
    168     assert (bits == (allocated_var_bits & bits));
    169 #endif
    170   }
    171   void deallocate_var_all ()
    172   {
    173 #ifndef HB_NDEBUG
    174     allocated_var_bits = 0;
    175 #endif
    176   }
    177 
    178   hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
    179   hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
    180 
    181   hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
    182   hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
    183 
    184   hb_glyph_info_t &prev ()      { return out_info[out_len ? out_len - 1 : 0]; }
    185   hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
    186 
    187   bool has_separate_output () const { return info != out_info; }
    188 
    189 
    190   HB_INTERNAL void reset ();
    191   HB_INTERNAL void clear ();
    192 
    193   unsigned int backtrack_len () const { return have_output? out_len : idx; }
    194   unsigned int lookahead_len () const { return len - idx; }
    195   unsigned int next_serial () { return serial++; }
    196 
    197   HB_INTERNAL void add (hb_codepoint_t  codepoint,
    198 			unsigned int    cluster);
    199   HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
    200 
    201   HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
    202   HB_INTERNAL void reverse ();
    203   HB_INTERNAL void reverse_clusters ();
    204   HB_INTERNAL void guess_segment_properties ();
    205 
    206   HB_INTERNAL void swap_buffers ();
    207   HB_INTERNAL void remove_output ();
    208   HB_INTERNAL void clear_output ();
    209   HB_INTERNAL void clear_positions ();
    210 
    211   HB_INTERNAL void replace_glyphs (unsigned int num_in,
    212 				   unsigned int num_out,
    213 				   const hb_codepoint_t *glyph_data);
    214 
    215   void replace_glyph (hb_codepoint_t glyph_index)
    216   {
    217     if (unlikely (out_info != info || out_len != idx)) {
    218       if (unlikely (!make_room_for (1, 1))) return;
    219       out_info[out_len] = info[idx];
    220     }
    221     out_info[out_len].codepoint = glyph_index;
    222 
    223     idx++;
    224     out_len++;
    225   }
    226   /* Makes a copy of the glyph at idx to output and replace glyph_index */
    227   hb_glyph_info_t & output_glyph (hb_codepoint_t glyph_index)
    228   {
    229     if (unlikely (!make_room_for (0, 1))) return Crap(hb_glyph_info_t);
    230 
    231     if (unlikely (idx == len && !out_len))
    232       return Crap(hb_glyph_info_t);
    233 
    234     out_info[out_len] = idx < len ? info[idx] : out_info[out_len - 1];
    235     out_info[out_len].codepoint = glyph_index;
    236 
    237     out_len++;
    238 
    239     return out_info[out_len - 1];
    240   }
    241   void output_info (const hb_glyph_info_t &glyph_info)
    242   {
    243     if (unlikely (!make_room_for (0, 1))) return;
    244 
    245     out_info[out_len] = glyph_info;
    246 
    247     out_len++;
    248   }
    249   /* Copies glyph at idx to output but doesn't advance idx */
    250   void copy_glyph ()
    251   {
    252     if (unlikely (!make_room_for (0, 1))) return;
    253 
    254     out_info[out_len] = info[idx];
    255 
    256     out_len++;
    257   }
    258   /* Copies glyph at idx to output and advance idx.
    259    * If there's no output, just advance idx. */
    260   void
    261   next_glyph ()
    262   {
    263     if (have_output)
    264     {
    265       if (out_info != info || out_len != idx)
    266       {
    267 	if (unlikely (!make_room_for (1, 1))) return;
    268 	out_info[out_len] = info[idx];
    269       }
    270       out_len++;
    271     }
    272 
    273     idx++;
    274   }
    275   /* Copies n glyphs at idx to output and advance idx.
    276    * If there's no output, just advance idx. */
    277   void
    278   next_glyphs (unsigned int n)
    279   {
    280     if (have_output)
    281     {
    282       if (out_info != info || out_len != idx)
    283       {
    284 	if (unlikely (!make_room_for (n, n))) return;
    285 	memmove (out_info + out_len, info + idx, n * sizeof (out_info[0]));
    286       }
    287       out_len += n;
    288     }
    289 
    290     idx += n;
    291   }
    292   /* Advance idx without copying to output. */
    293   void skip_glyph () { idx++; }
    294   void reset_masks (hb_mask_t mask)
    295   {
    296     for (unsigned int j = 0; j < len; j++)
    297       info[j].mask = mask;
    298   }
    299   void add_masks (hb_mask_t mask)
    300   {
    301     for (unsigned int j = 0; j < len; j++)
    302       info[j].mask |= mask;
    303   }
    304   HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask,
    305 			      unsigned int cluster_start, unsigned int cluster_end);
    306 
    307   void merge_clusters (unsigned int start, unsigned int end)
    308   {
    309     if (end - start < 2)
    310       return;
    311     merge_clusters_impl (start, end);
    312   }
    313   HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end);
    314   HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
    315   /* Merge clusters for deleting current glyph, and skip it. */
    316   HB_INTERNAL void delete_glyph ();
    317 
    318   void unsafe_to_break (unsigned int start,
    319 			       unsigned int end)
    320   {
    321     if (end - start < 2)
    322       return;
    323     unsafe_to_break_impl (start, end);
    324   }
    325   HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
    326   HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);
    327 
    328 
    329   /* Internal methods */
    330   HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */
    331 
    332   HB_INTERNAL bool enlarge (unsigned int size);
    333 
    334   bool ensure (unsigned int size)
    335   { return likely (!size || size < allocated) ? true : enlarge (size); }
    336 
    337   bool ensure_inplace (unsigned int size)
    338   { return likely (!size || size < allocated); }
    339 
    340   HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
    341   HB_INTERNAL bool shift_forward (unsigned int count);
    342 
    343   typedef long scratch_buffer_t;
    344   HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);
    345 
    346   void clear_context (unsigned int side) { context_len[side] = 0; }
    347 
    348   HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
    349 
    350   bool messaging () { return unlikely (message_func); }
    351   bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
    352   {
    353     if (!messaging ())
    354       return true;
    355     va_list ap;
    356     va_start (ap, fmt);
    357     bool ret = message_impl (font, fmt, ap);
    358     va_end (ap);
    359     return ret;
    360   }
    361   HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
    362 
    363   static void
    364   set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
    365   {
    366     if (inf.cluster != cluster)
    367     {
    368       if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
    369 	inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
    370       else
    371 	inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
    372     }
    373     inf.cluster = cluster;
    374   }
    375 
    376   int
    377   _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
    378 				     unsigned int start, unsigned int end,
    379 				     unsigned int cluster) const
    380   {
    381     for (unsigned int i = start; i < end; i++)
    382       cluster = MIN<unsigned int> (cluster, infos[i].cluster);
    383     return cluster;
    384   }
    385   void
    386   _unsafe_to_break_set_mask (hb_glyph_info_t *infos,
    387 			     unsigned int start, unsigned int end,
    388 			     unsigned int cluster)
    389   {
    390     for (unsigned int i = start; i < end; i++)
    391       if (cluster != infos[i].cluster)
    392       {
    393 	scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
    394 	infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
    395       }
    396   }
    397 
    398   void unsafe_to_break_all ()
    399   { unsafe_to_break_impl (0, len); }
    400   void safe_to_break_all ()
    401   {
    402     for (unsigned int i = 0; i < len; i++)
    403       info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
    404   }
    405 };
    406 DECLARE_NULL_INSTANCE (hb_buffer_t);
    407 
    408 
    409 /* Loop over clusters. Duplicated in foreach_syllable(). */
    410 #define foreach_cluster(buffer, start, end) \
    411   for (unsigned int \
    412        _count = buffer->len, \
    413        start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
    414        start < _count; \
    415        start = end, end = _next_cluster (buffer, start))
    416 
    417 static inline unsigned int
    418 _next_cluster (hb_buffer_t *buffer, unsigned int start)
    419 {
    420   hb_glyph_info_t *info = buffer->info;
    421   unsigned int count = buffer->len;
    422 
    423   unsigned int cluster = info[start].cluster;
    424   while (++start < count && cluster == info[start].cluster)
    425     ;
    426 
    427   return start;
    428 }
    429 
    430 
    431 #define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
    432   b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
    433 	   sizeof (b->info[0].var))
    434 #define HB_BUFFER_ALLOCATE_VAR(b, var)		HB_BUFFER_XALLOCATE_VAR (b, allocate_var,   var ())
    435 #define HB_BUFFER_DEALLOCATE_VAR(b, var)	HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
    436 #define HB_BUFFER_ASSERT_VAR(b, var)		HB_BUFFER_XALLOCATE_VAR (b, assert_var,     var ())
    437 
    438 
    439 #endif /* HB_BUFFER_HH */
    440