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_PRIVATE_HH
     31 #define HB_BUFFER_PRIVATE_HH
     32 
     33 #include "hb-private.hh"
     34 #include "hb-object-private.hh"
     35 #include "hb-unicode-private.hh"
     36 
     37 
     38 #ifndef HB_BUFFER_MAX_LEN_FACTOR
     39 #define HB_BUFFER_MAX_LEN_FACTOR 32
     40 #endif
     41 #ifndef HB_BUFFER_MAX_LEN_MIN
     42 #define HB_BUFFER_MAX_LEN_MIN 8192
     43 #endif
     44 #ifndef HB_BUFFER_MAX_LEN_DEFAULT
     45 #define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
     46 #endif
     47 
     48 #ifndef HB_BUFFER_MAX_OPS_FACTOR
     49 #define HB_BUFFER_MAX_OPS_FACTOR 64
     50 #endif
     51 #ifndef HB_BUFFER_MAX_OPS_MIN
     52 #define HB_BUFFER_MAX_OPS_MIN 1024
     53 #endif
     54 #ifndef HB_BUFFER_MAX_OPS_DEFAULT
     55 #define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */
     56 #endif
     57 
     58 static_assert ((sizeof (hb_glyph_info_t) == 20), "");
     59 static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
     60 
     61 HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
     62 HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
     63 HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
     64 
     65 enum hb_buffer_scratch_flags_t {
     66   HB_BUFFER_SCRATCH_FLAG_DEFAULT			= 0x00000000u,
     67   HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII			= 0x00000001u,
     68   HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES		= 0x00000002u,
     69   HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK		= 0x00000004u,
     70   HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT		= 0x00000008u,
     71   HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK		= 0x00000010u,
     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   hb_object_header_t header;
     88   ASSERT_POD ();
     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_buffer_scratch_flags_t scratch_flags; /* Have space-flallback, etc. */
     96   unsigned int max_len; /* Maximum allowed len. */
     97   int max_ops; /* Maximum allowed operations. */
     98 
     99   /* Buffer contents */
    100   hb_buffer_content_type_t content_type;
    101   hb_segment_properties_t props; /* Script, language, direction */
    102 
    103   bool in_error; /* Allocation failed */
    104   bool have_output; /* Whether we have an output buffer going on */
    105   bool have_positions; /* Whether we have positions */
    106 
    107   unsigned int idx; /* Cursor into ->info and ->pos arrays */
    108   unsigned int len; /* Length of ->info and ->pos arrays */
    109   unsigned int out_len; /* Length of ->out array if have_output */
    110 
    111   unsigned int allocated; /* Length of allocated arrays */
    112   hb_glyph_info_t     *info;
    113   hb_glyph_info_t     *out_info;
    114   hb_glyph_position_t *pos;
    115 
    116   unsigned int serial;
    117 
    118   /* Text before / after the main buffer contents.
    119    * Always in Unicode, and ordered outward.
    120    * Index 0 is for "pre-context", 1 for "post-context". */
    121   static const unsigned int CONTEXT_LENGTH = 5;
    122   hb_codepoint_t context[2][CONTEXT_LENGTH];
    123   unsigned int context_len[2];
    124 
    125   /* Debugging API */
    126   hb_buffer_message_func_t message_func;
    127   void *message_data;
    128   hb_destroy_func_t message_destroy;
    129 
    130   /* Internal debugging. */
    131   /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
    132 #ifndef HB_NDEBUG
    133   uint8_t allocated_var_bits;
    134 #endif
    135 
    136 
    137   /* Methods */
    138 
    139   inline void allocate_var (unsigned int start, unsigned int count)
    140   {
    141 #ifndef HB_NDEBUG
    142     unsigned int end = start + count;
    143     assert (end <= 8);
    144     unsigned int bits = (1u<<end) - (1u<<start);
    145     assert (0 == (allocated_var_bits & bits));
    146     allocated_var_bits |= bits;
    147 #endif
    148   }
    149   inline void deallocate_var (unsigned int start, unsigned int count)
    150   {
    151 #ifndef HB_NDEBUG
    152     unsigned int end = start + count;
    153     assert (end <= 8);
    154     unsigned int bits = (1u<<end) - (1u<<start);
    155     assert (bits == (allocated_var_bits & bits));
    156     allocated_var_bits &= ~bits;
    157 #endif
    158   }
    159   inline void assert_var (unsigned int start, unsigned int count)
    160   {
    161 #ifndef HB_NDEBUG
    162     unsigned int end = start + count;
    163     assert (end <= 8);
    164     unsigned int bits = (1u<<end) - (1u<<start);
    165     assert (bits == (allocated_var_bits & bits));
    166 #endif
    167   }
    168   inline void deallocate_var_all (void)
    169   {
    170 #ifndef HB_NDEBUG
    171     allocated_var_bits = 0;
    172 #endif
    173   }
    174 
    175   inline hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
    176   inline hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
    177 
    178   inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
    179   inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
    180 
    181   inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; }
    182   inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; }
    183 
    184   inline bool has_separate_output (void) const { return info != out_info; }
    185 
    186 
    187   HB_INTERNAL void reset (void);
    188   HB_INTERNAL void clear (void);
    189 
    190   inline unsigned int backtrack_len (void) const
    191   { return have_output? out_len : idx; }
    192   inline unsigned int lookahead_len (void) const
    193   { return len - idx; }
    194   inline unsigned int next_serial (void) { return serial++; }
    195 
    196   HB_INTERNAL void add (hb_codepoint_t  codepoint,
    197 			unsigned int    cluster);
    198   HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
    199 
    200   HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
    201   HB_INTERNAL void reverse (void);
    202   HB_INTERNAL void reverse_clusters (void);
    203   HB_INTERNAL void guess_segment_properties (void);
    204 
    205   HB_INTERNAL void swap_buffers (void);
    206   HB_INTERNAL void remove_output (void);
    207   HB_INTERNAL void clear_output (void);
    208   HB_INTERNAL void clear_positions (void);
    209 
    210   HB_INTERNAL void replace_glyphs (unsigned int num_in,
    211 				   unsigned int num_out,
    212 				   const hb_codepoint_t *glyph_data);
    213 
    214   HB_INTERNAL void replace_glyph (hb_codepoint_t glyph_index);
    215   /* Makes a copy of the glyph at idx to output and replace glyph_index */
    216   HB_INTERNAL void output_glyph (hb_codepoint_t glyph_index);
    217   HB_INTERNAL void output_info (const hb_glyph_info_t &glyph_info);
    218   /* Copies glyph at idx to output but doesn't advance idx */
    219   HB_INTERNAL void copy_glyph (void);
    220   HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */
    221   /* Copies glyph at idx to output and advance idx.
    222    * If there's no output, just advance idx. */
    223   inline void
    224   next_glyph (void)
    225   {
    226     if (have_output)
    227     {
    228       if (unlikely (out_info != info || out_len != idx)) {
    229 	if (unlikely (!make_room_for (1, 1))) return;
    230 	out_info[out_len] = info[idx];
    231       }
    232       out_len++;
    233     }
    234 
    235     idx++;
    236   }
    237 
    238   /* Advance idx without copying to output. */
    239   inline void skip_glyph (void) { idx++; }
    240 
    241   inline void reset_masks (hb_mask_t mask)
    242   {
    243     for (unsigned int j = 0; j < len; j++)
    244       info[j].mask = mask;
    245   }
    246   inline void add_masks (hb_mask_t mask)
    247   {
    248     for (unsigned int j = 0; j < len; j++)
    249       info[j].mask |= mask;
    250   }
    251   HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask,
    252 			      unsigned int cluster_start, unsigned int cluster_end);
    253 
    254   inline void merge_clusters (unsigned int start, unsigned int end)
    255   {
    256     if (end - start < 2)
    257       return;
    258     merge_clusters_impl (start, end);
    259   }
    260   HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end);
    261   HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
    262   /* Merge clusters for deleting current glyph, and skip it. */
    263   HB_INTERNAL void delete_glyph (void);
    264 
    265   inline void unsafe_to_break (unsigned int start,
    266 			       unsigned int end)
    267   {
    268     if (end - start < 2)
    269       return;
    270     unsafe_to_break_impl (start, end);
    271   }
    272   HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
    273   HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);
    274 
    275 
    276   /* Internal methods */
    277   HB_INTERNAL bool enlarge (unsigned int size);
    278 
    279   inline bool ensure (unsigned int size)
    280   { return likely (!size || size < allocated) ? true : enlarge (size); }
    281 
    282   inline bool ensure_inplace (unsigned int size)
    283   { return likely (!size || size < allocated); }
    284 
    285   HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
    286   HB_INTERNAL bool shift_forward (unsigned int count);
    287 
    288   typedef long scratch_buffer_t;
    289   HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);
    290 
    291   inline void clear_context (unsigned int side) { context_len[side] = 0; }
    292 
    293   HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
    294 
    295   inline bool messaging (void) { return unlikely (message_func); }
    296   inline bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
    297   {
    298     if (!messaging ())
    299       return true;
    300     va_list ap;
    301     va_start (ap, fmt);
    302     bool ret = message_impl (font, fmt, ap);
    303     va_end (ap);
    304     return ret;
    305   }
    306   HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
    307 
    308   static inline void
    309   set_cluster (hb_glyph_info_t &info, unsigned int cluster, unsigned int mask = 0)
    310   {
    311     if (info.cluster != cluster)
    312     {
    313       if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
    314 	info.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
    315       else
    316 	info.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
    317     }
    318     info.cluster = cluster;
    319   }
    320 
    321   inline int
    322   _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *info,
    323 				     unsigned int start, unsigned int end,
    324 				     unsigned int cluster) const
    325   {
    326     for (unsigned int i = start; i < end; i++)
    327       cluster = MIN<unsigned int> (cluster, info[i].cluster);
    328     return cluster;
    329   }
    330   inline void
    331   _unsafe_to_break_set_mask (hb_glyph_info_t *info,
    332 			     unsigned int start, unsigned int end,
    333 			     unsigned int cluster)
    334   {
    335     for (unsigned int i = start; i < end; i++)
    336       if (cluster != info[i].cluster)
    337       {
    338 	scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
    339 	info[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
    340       }
    341   }
    342 
    343   inline void
    344   unsafe_to_break_all (void)
    345   {
    346     for (unsigned int i = 0; i < len; i++)
    347       info[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
    348   }
    349   inline void
    350   safe_to_break_all (void)
    351   {
    352     for (unsigned int i = 0; i < len; i++)
    353       info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
    354   }
    355 };
    356 
    357 
    358 /* Loop over clusters. Duplicated in foreach_syllable(). */
    359 #define foreach_cluster(buffer, start, end) \
    360   for (unsigned int \
    361        _count = buffer->len, \
    362        start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
    363        start < _count; \
    364        start = end, end = _next_cluster (buffer, start))
    365 
    366 static inline unsigned int
    367 _next_cluster (hb_buffer_t *buffer, unsigned int start)
    368 {
    369   hb_glyph_info_t *info = buffer->info;
    370   unsigned int count = buffer->len;
    371 
    372   unsigned int cluster = info[start].cluster;
    373   while (++start < count && cluster == info[start].cluster)
    374     ;
    375 
    376   return start;
    377 }
    378 
    379 
    380 #define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
    381   b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
    382 	   sizeof (b->info[0].var))
    383 #define HB_BUFFER_ALLOCATE_VAR(b, var)		HB_BUFFER_XALLOCATE_VAR (b, allocate_var,   var ())
    384 #define HB_BUFFER_DEALLOCATE_VAR(b, var)	HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
    385 #define HB_BUFFER_ASSERT_VAR(b, var)		HB_BUFFER_XALLOCATE_VAR (b, assert_var,     var ())
    386 
    387 
    388 #endif /* HB_BUFFER_PRIVATE_HH */
    389