LCOV - code coverage report
Current view: directory - gfx/harfbuzz/src - hb-buffer.cc (source / functions) Found Hit Coverage
Test: app.info Lines: 343 2 0.6 %
Date: 2012-06-02 Functions: 56 2 3.6 %

       1                 : /*
       2                 :  * Copyright © 1998-2004  David Turner and Werner Lemberg
       3                 :  * Copyright © 2004,2007,2009,2010  Red Hat, Inc.
       4                 :  * Copyright © 2011  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                 : #include "hb-buffer-private.hh"
      31                 : 
      32                 : #include <string.h>
      33                 : 
      34                 : 
      35                 : 
      36                 : #ifndef HB_DEBUG_BUFFER
      37                 : #define HB_DEBUG_BUFFER (HB_DEBUG+0)
      38                 : #endif
      39                 : 
      40                 : 
      41                 : static hb_buffer_t _hb_buffer_nil = {
      42                 :   HB_OBJECT_HEADER_STATIC,
      43                 : 
      44                 :   &_hb_unicode_funcs_default,
      45                 :   {
      46                 :     HB_DIRECTION_INVALID,
      47                 :     HB_SCRIPT_INVALID,
      48                 :     NULL,
      49                 :   },
      50                 : 
      51                 :   TRUE, /* in_error */
      52                 :   TRUE, /* have_output */
      53                 :   TRUE  /* have_positions */
      54            1464 : };
      55                 : 
      56                 : /* Here is how the buffer works internally:
      57                 :  *
      58                 :  * There are two info pointers: info and out_info.  They always have
      59                 :  * the same allocated size, but different lengths.
      60                 :  *
      61                 :  * As an optimization, both info and out_info may point to the
      62                 :  * same piece of memory, which is owned by info.  This remains the
      63                 :  * case as long as out_len doesn't exceed i at any time.
      64                 :  * In that case, swap_buffers() is no-op and the glyph operations operate
      65                 :  * mostly in-place.
      66                 :  *
      67                 :  * As soon as out_info gets longer than info, out_info is moved over
      68                 :  * to an alternate buffer (which we reuse the pos buffer for!), and its
      69                 :  * current contents (out_len entries) are copied to the new place.
      70                 :  * This should all remain transparent to the user.  swap_buffers() then
      71                 :  * switches info and out_info.
      72                 :  */
      73                 : 
      74                 : 
      75                 : 
      76                 : /* Internal API */
      77                 : 
      78                 : bool
      79               0 : hb_buffer_t::enlarge (unsigned int size)
      80                 : {
      81               0 :   if (unlikely (in_error))
      82               0 :     return FALSE;
      83                 : 
      84               0 :   unsigned int new_allocated = allocated;
      85               0 :   hb_glyph_position_t *new_pos = NULL;
      86               0 :   hb_glyph_info_t *new_info = NULL;
      87               0 :   bool separate_out = out_info != info;
      88                 : 
      89               0 :   if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
      90               0 :     goto done;
      91                 : 
      92               0 :   while (size > new_allocated)
      93               0 :     new_allocated += (new_allocated >> 1) + 32;
      94                 : 
      95                 :   ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0]));
      96               0 :   if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0]))))
      97               0 :     goto done;
      98                 : 
      99               0 :   new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0]));
     100               0 :   new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0]));
     101                 : 
     102                 : done:
     103               0 :   if (unlikely (!new_pos || !new_info))
     104               0 :     in_error = TRUE;
     105                 : 
     106               0 :   if (likely (new_pos))
     107               0 :     pos = new_pos;
     108                 : 
     109               0 :   if (likely (new_info))
     110               0 :     info = new_info;
     111                 : 
     112               0 :   out_info = separate_out ? (hb_glyph_info_t *) pos : info;
     113               0 :   if (likely (!in_error))
     114               0 :     allocated = new_allocated;
     115                 : 
     116               0 :   return likely (!in_error);
     117                 : }
     118                 : 
     119                 : bool
     120               0 : hb_buffer_t::make_room_for (unsigned int num_in,
     121                 :                             unsigned int num_out)
     122                 : {
     123               0 :   if (unlikely (!ensure (out_len + num_out))) return FALSE;
     124                 : 
     125               0 :   if (out_info == info &&
     126                 :       out_len + num_out > idx + num_in)
     127                 :   {
     128               0 :     assert (have_output);
     129                 : 
     130               0 :     out_info = (hb_glyph_info_t *) pos;
     131               0 :     memcpy (out_info, info, out_len * sizeof (out_info[0]));
     132                 :   }
     133                 : 
     134               0 :   return TRUE;
     135                 : }
     136                 : 
     137                 : void *
     138               0 : hb_buffer_t::get_scratch_buffer (unsigned int *size)
     139                 : {
     140               0 :   have_output = FALSE;
     141               0 :   have_positions = FALSE;
     142               0 :   out_len = 0;
     143               0 :   *size = allocated * sizeof (pos[0]);
     144               0 :   return pos;
     145                 : }
     146                 : 
     147                 : 
     148                 : /* HarfBuzz-Internal API */
     149                 : 
     150                 : void
     151               0 : hb_buffer_t::reset (void)
     152                 : {
     153               0 :   if (unlikely (hb_object_is_inert (this)))
     154               0 :     return;
     155                 : 
     156               0 :   hb_unicode_funcs_destroy (unicode);
     157               0 :   unicode = _hb_buffer_nil.unicode;
     158                 : 
     159               0 :   props = _hb_buffer_nil.props;
     160                 : 
     161               0 :   in_error = FALSE;
     162               0 :   have_output = FALSE;
     163               0 :   have_positions = FALSE;
     164                 : 
     165               0 :   idx = 0;
     166               0 :   len = 0;
     167               0 :   out_len = 0;
     168                 : 
     169               0 :   serial = 0;
     170               0 :   memset (allocated_var_bytes, 0, sizeof allocated_var_bytes);
     171               0 :   memset (allocated_var_owner, 0, sizeof allocated_var_owner);
     172                 : 
     173               0 :   out_info = info;
     174                 : }
     175                 : 
     176                 : void
     177               0 : hb_buffer_t::add (hb_codepoint_t  codepoint,
     178                 :                   hb_mask_t       mask,
     179                 :                   unsigned int    cluster)
     180                 : {
     181                 :   hb_glyph_info_t *glyph;
     182                 : 
     183               0 :   if (unlikely (!ensure (len + 1))) return;
     184                 : 
     185               0 :   glyph = &info[len];
     186                 : 
     187               0 :   memset (glyph, 0, sizeof (*glyph));
     188               0 :   glyph->codepoint = codepoint;
     189               0 :   glyph->mask = mask;
     190               0 :   glyph->cluster = cluster;
     191                 : 
     192               0 :   len++;
     193                 : }
     194                 : 
     195                 : void
     196               0 : hb_buffer_t::clear_output (void)
     197                 : {
     198               0 :   if (unlikely (hb_object_is_inert (this)))
     199               0 :     return;
     200                 : 
     201               0 :   have_output = TRUE;
     202               0 :   have_positions = FALSE;
     203                 : 
     204               0 :   out_len = 0;
     205               0 :   out_info = info;
     206                 : }
     207                 : 
     208                 : void
     209               0 : hb_buffer_t::clear_positions (void)
     210                 : {
     211               0 :   if (unlikely (hb_object_is_inert (this)))
     212               0 :     return;
     213                 : 
     214               0 :   have_output = FALSE;
     215               0 :   have_positions = TRUE;
     216                 : 
     217               0 :   memset (pos, 0, sizeof (pos[0]) * len);
     218                 : }
     219                 : 
     220                 : void
     221               0 : hb_buffer_t::swap_buffers (void)
     222                 : {
     223               0 :   if (unlikely (in_error)) return;
     224                 : 
     225               0 :   assert (have_output);
     226                 : 
     227               0 :   if (out_info != info)
     228                 :   {
     229                 :     hb_glyph_info_t *tmp_string;
     230               0 :     tmp_string = info;
     231               0 :     info = out_info;
     232               0 :     out_info = tmp_string;
     233               0 :     pos = (hb_glyph_position_t *) out_info;
     234                 :   }
     235                 : 
     236                 :   unsigned int tmp;
     237               0 :   tmp = len;
     238               0 :   len = out_len;
     239               0 :   out_len = tmp;
     240                 : 
     241               0 :   idx = 0;
     242                 : }
     243                 : 
     244                 : void
     245               0 : hb_buffer_t::replace_glyphs_be16 (unsigned int num_in,
     246                 :                                   unsigned int num_out,
     247                 :                                   const uint16_t *glyph_data_be)
     248                 : {
     249               0 :   if (!make_room_for (num_in, num_out)) return;
     250                 : 
     251               0 :   hb_glyph_info_t orig_info = info[idx];
     252               0 :   for (unsigned int i = 1; i < num_in; i++)
     253                 :   {
     254               0 :     hb_glyph_info_t *inf = &info[idx + i];
     255               0 :     orig_info.cluster = MIN (orig_info.cluster, inf->cluster);
     256                 :   }
     257                 : 
     258               0 :   hb_glyph_info_t *pinfo = &out_info[out_len];
     259               0 :   for (unsigned int i = 0; i < num_out; i++)
     260                 :   {
     261               0 :     *pinfo = orig_info;
     262               0 :     pinfo->codepoint = hb_be_uint16 (glyph_data_be[i]);
     263               0 :     pinfo++;
     264                 :   }
     265                 : 
     266               0 :   idx  += num_in;
     267               0 :   out_len += num_out;
     268                 : }
     269                 : 
     270                 : void
     271               0 : hb_buffer_t::replace_glyphs (unsigned int num_in,
     272                 :                              unsigned int num_out,
     273                 :                              const uint16_t *glyph_data)
     274                 : {
     275               0 :   if (!make_room_for (num_in, num_out)) return;
     276                 : 
     277               0 :   hb_glyph_info_t orig_info = info[idx];
     278               0 :   for (unsigned int i = 1; i < num_in; i++)
     279                 :   {
     280               0 :     hb_glyph_info_t *inf = &info[idx + i];
     281               0 :     orig_info.cluster = MIN (orig_info.cluster, inf->cluster);
     282                 :   }
     283                 : 
     284               0 :   hb_glyph_info_t *pinfo = &out_info[out_len];
     285               0 :   for (unsigned int i = 0; i < num_out; i++)
     286                 :   {
     287               0 :     *pinfo = orig_info;
     288               0 :     pinfo->codepoint = glyph_data[i];
     289               0 :     pinfo++;
     290                 :   }
     291                 : 
     292               0 :   idx  += num_in;
     293               0 :   out_len += num_out;
     294                 : }
     295                 : 
     296                 : void
     297               0 : hb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
     298                 : {
     299               0 :   if (!make_room_for (0, 1)) return;
     300                 : 
     301               0 :   out_info[out_len] = info[idx];
     302               0 :   out_info[out_len].codepoint = glyph_index;
     303                 : 
     304               0 :   out_len++;
     305                 : }
     306                 : 
     307                 : void
     308               0 : hb_buffer_t::copy_glyph (void)
     309                 : {
     310               0 :   if (!make_room_for (0, 1)) return;
     311                 : 
     312               0 :   out_info[out_len] = info[idx];
     313                 : 
     314               0 :   out_len++;
     315                 : }
     316                 : 
     317                 : void
     318               0 : hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
     319                 : {
     320               0 :   if (!make_room_for (1, 1)) return;
     321                 : 
     322               0 :   out_info[out_len] = info[idx];
     323               0 :   out_info[out_len].codepoint = glyph_index;
     324                 : 
     325               0 :   idx++;
     326               0 :   out_len++;
     327                 : }
     328                 : 
     329                 : void
     330               0 : hb_buffer_t::next_glyph (void)
     331                 : {
     332               0 :   if (have_output)
     333                 :   {
     334               0 :     if (out_info != info)
     335                 :     {
     336               0 :       if (unlikely (!ensure (out_len + 1))) return;
     337               0 :       out_info[out_len] = info[idx];
     338                 :     }
     339               0 :     else if (out_len != idx)
     340               0 :       out_info[out_len] = info[idx];
     341                 : 
     342               0 :     out_len++;
     343                 :   }
     344                 : 
     345               0 :   idx++;
     346                 : }
     347                 : 
     348                 : void
     349               0 : hb_buffer_t::set_masks (hb_mask_t    value,
     350                 :                         hb_mask_t    mask,
     351                 :                         unsigned int cluster_start,
     352                 :                         unsigned int cluster_end)
     353                 : {
     354               0 :   hb_mask_t not_mask = ~mask;
     355               0 :   value &= mask;
     356                 : 
     357               0 :   if (!mask)
     358               0 :     return;
     359                 : 
     360               0 :   if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
     361               0 :     unsigned int count = len;
     362               0 :     for (unsigned int i = 0; i < count; i++)
     363               0 :       info[i].mask = (info[i].mask & not_mask) | value;
     364               0 :     return;
     365                 :   }
     366                 : 
     367               0 :   unsigned int count = len;
     368               0 :   for (unsigned int i = 0; i < count; i++)
     369               0 :     if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end)
     370               0 :       info[i].mask = (info[i].mask & not_mask) | value;
     371                 : }
     372                 : 
     373                 : void
     374               0 : hb_buffer_t::reverse_range (unsigned int start,
     375                 :                             unsigned int end)
     376                 : {
     377                 :   unsigned int i, j;
     378                 : 
     379               0 :   if (start == end - 1)
     380               0 :     return;
     381                 : 
     382               0 :   for (i = start, j = end - 1; i < j; i++, j--) {
     383                 :     hb_glyph_info_t t;
     384                 : 
     385               0 :     t = info[i];
     386               0 :     info[i] = info[j];
     387               0 :     info[j] = t;
     388                 :   }
     389                 : 
     390               0 :   if (pos) {
     391               0 :     for (i = start, j = end - 1; i < j; i++, j--) {
     392                 :       hb_glyph_position_t t;
     393                 : 
     394               0 :       t = pos[i];
     395               0 :       pos[i] = pos[j];
     396               0 :       pos[j] = t;
     397                 :     }
     398                 :   }
     399                 : }
     400                 : 
     401                 : void
     402               0 : hb_buffer_t::reverse (void)
     403                 : {
     404               0 :   if (unlikely (!len))
     405               0 :     return;
     406                 : 
     407               0 :   reverse_range (0, len);
     408                 : }
     409                 : 
     410                 : void
     411               0 : hb_buffer_t::reverse_clusters (void)
     412                 : {
     413                 :   unsigned int i, start, count, last_cluster;
     414                 : 
     415               0 :   if (unlikely (!len))
     416               0 :     return;
     417                 : 
     418               0 :   reverse ();
     419                 : 
     420               0 :   count = len;
     421               0 :   start = 0;
     422               0 :   last_cluster = info[0].cluster;
     423               0 :   for (i = 1; i < count; i++) {
     424               0 :     if (last_cluster != info[i].cluster) {
     425               0 :       reverse_range (start, i);
     426               0 :       start = i;
     427               0 :       last_cluster = info[i].cluster;
     428                 :     }
     429                 :   }
     430               0 :   reverse_range (start, i);
     431                 : }
     432                 : 
     433                 : void
     434               0 : hb_buffer_t::guess_properties (void)
     435                 : {
     436                 :   /* If script is set to INVALID, guess from buffer contents */
     437               0 :   if (props.script == HB_SCRIPT_INVALID) {
     438               0 :     for (unsigned int i = 0; i < len; i++) {
     439               0 :       hb_script_t script = hb_unicode_script (unicode, info[i].codepoint);
     440               0 :       if (likely (script != HB_SCRIPT_COMMON &&
     441                 :                   script != HB_SCRIPT_INHERITED &&
     442                 :                   script != HB_SCRIPT_UNKNOWN)) {
     443               0 :         props.script = script;
     444               0 :         break;
     445                 :       }
     446                 :     }
     447                 :   }
     448                 : 
     449                 :   /* If direction is set to INVALID, guess from script */
     450               0 :   if (props.direction == HB_DIRECTION_INVALID) {
     451               0 :     props.direction = hb_script_get_horizontal_direction (props.script);
     452                 :   }
     453                 : 
     454                 :   /* If language is not set, use default language from locale */
     455               0 :   if (props.language == HB_LANGUAGE_INVALID) {
     456                 :     /* TODO get_default_for_script? using $LANGUAGE */
     457               0 :     props.language = hb_language_get_default ();
     458                 :   }
     459               0 : }
     460                 : 
     461                 : 
     462                 : static inline void
     463               0 : dump_var_allocation (const hb_buffer_t *buffer)
     464                 : {
     465                 :   char buf[80];
     466               0 :   for (unsigned int i = 0; i < 8; i++)
     467               0 :     buf[i] = '0' + buffer->allocated_var_bytes[7 - i];
     468               0 :   buf[8] = '\0';
     469                 :   DEBUG_MSG (BUFFER, buffer,
     470                 :              "Current var allocation: %s",
     471               0 :              buf);
     472               0 : }
     473                 : 
     474               0 : void hb_buffer_t::allocate_var (unsigned int byte_i, unsigned int count, const char *owner)
     475                 : {
     476               0 :   assert (byte_i < 8 && byte_i + count <= 8);
     477                 : 
     478               0 :   if (DEBUG (BUFFER))
     479               0 :     dump_var_allocation (this);
     480                 :   DEBUG_MSG (BUFFER, this,
     481                 :              "Allocating var bytes %d..%d for %s",
     482               0 :              byte_i, byte_i + count - 1, owner);
     483                 : 
     484               0 :   for (unsigned int i = byte_i; i < byte_i + count; i++) {
     485               0 :     assert (!allocated_var_bytes[i]);
     486               0 :     allocated_var_bytes[i]++;
     487               0 :     allocated_var_owner[i] = owner;
     488                 :   }
     489               0 : }
     490                 : 
     491               0 : void hb_buffer_t::deallocate_var (unsigned int byte_i, unsigned int count, const char *owner)
     492                 : {
     493               0 :   if (DEBUG (BUFFER))
     494               0 :     dump_var_allocation (this);
     495                 : 
     496                 :   DEBUG_MSG (BUFFER, this,
     497                 :              "Deallocating var bytes %d..%d for %s",
     498               0 :              byte_i, byte_i + count - 1, owner);
     499                 : 
     500               0 :   assert (byte_i < 8 && byte_i + count <= 8);
     501               0 :   for (unsigned int i = byte_i; i < byte_i + count; i++) {
     502               0 :     assert (allocated_var_bytes[i]);
     503               0 :     assert (0 == strcmp (allocated_var_owner[i], owner));
     504               0 :     allocated_var_bytes[i]--;
     505                 :   }
     506               0 : }
     507                 : 
     508               0 : void hb_buffer_t::deallocate_var_all (void)
     509                 : {
     510               0 :   memset (allocated_var_bytes, 0, sizeof (allocated_var_bytes));
     511               0 :   memset (allocated_var_owner, 0, sizeof (allocated_var_owner));
     512               0 : }
     513                 : 
     514                 : /* Public API */
     515                 : 
     516                 : hb_buffer_t *
     517               0 : hb_buffer_create ()
     518                 : {
     519                 :   hb_buffer_t *buffer;
     520                 : 
     521               0 :   if (!(buffer = hb_object_create<hb_buffer_t> ()))
     522               0 :     return &_hb_buffer_nil;
     523                 : 
     524               0 :   buffer->reset ();
     525                 : 
     526               0 :   return buffer;
     527                 : }
     528                 : 
     529                 : hb_buffer_t *
     530               0 : hb_buffer_get_empty (void)
     531                 : {
     532               0 :   return &_hb_buffer_nil;
     533                 : }
     534                 : 
     535                 : hb_buffer_t *
     536               0 : hb_buffer_reference (hb_buffer_t *buffer)
     537                 : {
     538               0 :   return hb_object_reference (buffer);
     539                 : }
     540                 : 
     541                 : void
     542               0 : hb_buffer_destroy (hb_buffer_t *buffer)
     543                 : {
     544               0 :   if (!hb_object_destroy (buffer)) return;
     545                 : 
     546               0 :   hb_unicode_funcs_destroy (buffer->unicode);
     547                 : 
     548               0 :   free (buffer->info);
     549               0 :   free (buffer->pos);
     550                 : 
     551               0 :   free (buffer);
     552                 : }
     553                 : 
     554                 : hb_bool_t
     555               0 : hb_buffer_set_user_data (hb_buffer_t        *buffer,
     556                 :                          hb_user_data_key_t *key,
     557                 :                          void *              data,
     558                 :                          hb_destroy_func_t   destroy,
     559                 :                          hb_bool_t           replace)
     560                 : {
     561               0 :   return hb_object_set_user_data (buffer, key, data, destroy, replace);
     562                 : }
     563                 : 
     564                 : void *
     565               0 : hb_buffer_get_user_data (hb_buffer_t        *buffer,
     566                 :                          hb_user_data_key_t *key)
     567                 : {
     568               0 :   return hb_object_get_user_data (buffer, key);
     569                 : }
     570                 : 
     571                 : 
     572                 : void
     573               0 : hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
     574                 :                              hb_unicode_funcs_t *unicode)
     575                 : {
     576               0 :   if (unlikely (hb_object_is_inert (buffer)))
     577               0 :     return;
     578                 : 
     579               0 :   if (!unicode)
     580               0 :     unicode = _hb_buffer_nil.unicode;
     581                 : 
     582               0 :   hb_unicode_funcs_reference (unicode);
     583               0 :   hb_unicode_funcs_destroy (buffer->unicode);
     584               0 :   buffer->unicode = unicode;
     585                 : }
     586                 : 
     587                 : hb_unicode_funcs_t *
     588               0 : hb_buffer_get_unicode_funcs (hb_buffer_t        *buffer)
     589                 : {
     590               0 :   return buffer->unicode;
     591                 : }
     592                 : 
     593                 : void
     594               0 : hb_buffer_set_direction (hb_buffer_t    *buffer,
     595                 :                          hb_direction_t  direction)
     596                 : 
     597                 : {
     598               0 :   if (unlikely (hb_object_is_inert (buffer)))
     599               0 :     return;
     600                 : 
     601               0 :   buffer->props.direction = direction;
     602                 : }
     603                 : 
     604                 : hb_direction_t
     605               0 : hb_buffer_get_direction (hb_buffer_t    *buffer)
     606                 : {
     607               0 :   return buffer->props.direction;
     608                 : }
     609                 : 
     610                 : void
     611               0 : hb_buffer_set_script (hb_buffer_t *buffer,
     612                 :                       hb_script_t  script)
     613                 : {
     614               0 :   if (unlikely (hb_object_is_inert (buffer)))
     615               0 :     return;
     616                 : 
     617               0 :   buffer->props.script = script;
     618                 : }
     619                 : 
     620                 : hb_script_t
     621               0 : hb_buffer_get_script (hb_buffer_t *buffer)
     622                 : {
     623               0 :   return buffer->props.script;
     624                 : }
     625                 : 
     626                 : void
     627               0 : hb_buffer_set_language (hb_buffer_t   *buffer,
     628                 :                         hb_language_t  language)
     629                 : {
     630               0 :   if (unlikely (hb_object_is_inert (buffer)))
     631               0 :     return;
     632                 : 
     633               0 :   buffer->props.language = language;
     634                 : }
     635                 : 
     636                 : hb_language_t
     637               0 : hb_buffer_get_language (hb_buffer_t *buffer)
     638                 : {
     639               0 :   return buffer->props.language;
     640                 : }
     641                 : 
     642                 : 
     643                 : void
     644               0 : hb_buffer_reset (hb_buffer_t *buffer)
     645                 : {
     646               0 :   buffer->reset ();
     647               0 : }
     648                 : 
     649                 : hb_bool_t
     650               0 : hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
     651                 : {
     652               0 :   return buffer->ensure (size);
     653                 : }
     654                 : 
     655                 : hb_bool_t
     656               0 : hb_buffer_allocation_successful (hb_buffer_t  *buffer)
     657                 : {
     658               0 :   return !buffer->in_error;
     659                 : }
     660                 : 
     661                 : void
     662               0 : hb_buffer_add (hb_buffer_t    *buffer,
     663                 :                hb_codepoint_t  codepoint,
     664                 :                hb_mask_t       mask,
     665                 :                unsigned int    cluster)
     666                 : {
     667               0 :   buffer->add (codepoint, mask, cluster);
     668               0 : }
     669                 : 
     670                 : hb_bool_t
     671               0 : hb_buffer_set_length (hb_buffer_t  *buffer,
     672                 :                       unsigned int  length)
     673                 : {
     674               0 :   if (!buffer->ensure (length))
     675               0 :     return FALSE;
     676                 : 
     677                 :   /* Wipe the new space */
     678               0 :   if (length > buffer->len) {
     679               0 :     memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
     680               0 :     if (buffer->have_positions)
     681               0 :       memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
     682                 :   }
     683                 : 
     684               0 :   buffer->len = length;
     685               0 :   return TRUE;
     686                 : }
     687                 : 
     688                 : unsigned int
     689               0 : hb_buffer_get_length (hb_buffer_t *buffer)
     690                 : {
     691               0 :   return buffer->len;
     692                 : }
     693                 : 
     694                 : /* Return value valid as long as buffer not modified */
     695                 : hb_glyph_info_t *
     696               0 : hb_buffer_get_glyph_infos (hb_buffer_t  *buffer,
     697                 :                            unsigned int *length)
     698                 : {
     699               0 :   if (length)
     700               0 :     *length = buffer->len;
     701                 : 
     702               0 :   return (hb_glyph_info_t *) buffer->info;
     703                 : }
     704                 : 
     705                 : /* Return value valid as long as buffer not modified */
     706                 : hb_glyph_position_t *
     707               0 : hb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
     708                 :                                unsigned int *length)
     709                 : {
     710               0 :   if (!buffer->have_positions)
     711               0 :     buffer->clear_positions ();
     712                 : 
     713               0 :   if (length)
     714               0 :     *length = buffer->len;
     715                 : 
     716               0 :   return (hb_glyph_position_t *) buffer->pos;
     717                 : }
     718                 : 
     719                 : void
     720               0 : hb_buffer_reverse (hb_buffer_t *buffer)
     721                 : {
     722               0 :   buffer->reverse ();
     723               0 : }
     724                 : 
     725                 : void
     726               0 : hb_buffer_reverse_clusters (hb_buffer_t *buffer)
     727                 : {
     728               0 :   buffer->reverse_clusters ();
     729               0 : }
     730                 : 
     731                 : void
     732               0 : hb_buffer_guess_properties (hb_buffer_t *buffer)
     733                 : {
     734               0 :   buffer->guess_properties ();
     735               0 : }
     736                 : 
     737                 : #define ADD_UTF(T) \
     738                 :         HB_STMT_START { \
     739                 :           if (text_length == -1) { \
     740                 :             text_length = 0; \
     741                 :             const T *p = (const T *) text; \
     742                 :             while (*p) { \
     743                 :               text_length++; \
     744                 :               p++; \
     745                 :             } \
     746                 :           } \
     747                 :           if (item_length == -1) \
     748                 :             item_length = text_length - item_offset; \
     749                 :           buffer->ensure (buffer->len + item_length * sizeof (T) / 4); \
     750                 :           const T *next = (const T *) text + item_offset; \
     751                 :           const T *end = next + item_length; \
     752                 :           while (next < end) { \
     753                 :             hb_codepoint_t u; \
     754                 :             const T *old_next = next; \
     755                 :             next = UTF_NEXT (next, end, u); \
     756                 :             hb_buffer_add (buffer, u, 1,  old_next - (const T *) text); \
     757                 :           } \
     758                 :         } HB_STMT_END
     759                 : 
     760                 : 
     761                 : #define UTF8_COMPUTE(Char, Mask, Len) \
     762                 :   if (Char < 128) { Len = 1; Mask = 0x7f; } \
     763                 :   else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \
     764                 :   else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \
     765                 :   else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \
     766                 :   else Len = 0;
     767                 : 
     768                 : static inline const uint8_t *
     769               0 : hb_utf8_next (const uint8_t *text,
     770                 :               const uint8_t *end,
     771                 :               hb_codepoint_t *unicode)
     772                 : {
     773               0 :   uint8_t c = *text;
     774                 :   unsigned int mask, len;
     775                 : 
     776                 :   /* TODO check for overlong sequences? */
     777                 : 
     778               0 :   UTF8_COMPUTE (c, mask, len);
     779               0 :   if (unlikely (!len || (unsigned int) (end - text) < len)) {
     780               0 :     *unicode = -1;
     781               0 :     return text + 1;
     782                 :   } else {
     783                 :     hb_codepoint_t result;
     784                 :     unsigned int i;
     785               0 :     result = c & mask;
     786               0 :     for (i = 1; i < len; i++)
     787                 :       {
     788               0 :         if (unlikely ((text[i] & 0xc0) != 0x80))
     789                 :           {
     790               0 :             *unicode = -1;
     791               0 :             return text + 1;
     792                 :           }
     793               0 :         result <<= 6;
     794               0 :         result |= (text[i] & 0x3f);
     795                 :       }
     796               0 :     *unicode = result;
     797               0 :     return text + len;
     798                 :   }
     799                 : }
     800                 : 
     801                 : void
     802               0 : hb_buffer_add_utf8 (hb_buffer_t  *buffer,
     803                 :                     const char   *text,
     804                 :                     int           text_length,
     805                 :                     unsigned int  item_offset,
     806                 :                     int           item_length)
     807                 : {
     808                 : #define UTF_NEXT(S, E, U)       hb_utf8_next (S, E, &(U))
     809               0 :   ADD_UTF (uint8_t);
     810                 : #undef UTF_NEXT
     811               0 : }
     812                 : 
     813                 : static inline const uint16_t *
     814               0 : hb_utf16_next (const uint16_t *text,
     815                 :                const uint16_t *end,
     816                 :                hb_codepoint_t *unicode)
     817                 : {
     818               0 :   uint16_t c = *text++;
     819                 : 
     820               0 :   if (unlikely (c >= 0xd800 && c < 0xdc00)) {
     821                 :     /* high surrogate */
     822                 :     uint16_t l;
     823               0 :     if (text < end && ((l = *text), likely (l >= 0xdc00 && l < 0xe000))) {
     824                 :       /* low surrogate */
     825               0 :       *unicode = ((hb_codepoint_t) ((c) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000);
     826               0 :        text++;
     827                 :     } else
     828               0 :       *unicode = -1;
     829                 :   } else
     830               0 :     *unicode = c;
     831                 : 
     832               0 :   return text;
     833                 : }
     834                 : 
     835                 : void
     836               0 : hb_buffer_add_utf16 (hb_buffer_t    *buffer,
     837                 :                      const uint16_t *text,
     838                 :                      int             text_length,
     839                 :                      unsigned int    item_offset,
     840                 :                      int            item_length)
     841                 : {
     842                 : #define UTF_NEXT(S, E, U)       hb_utf16_next (S, E, &(U))
     843               0 :   ADD_UTF (uint16_t);
     844                 : #undef UTF_NEXT
     845               0 : }
     846                 : 
     847                 : void
     848               0 : hb_buffer_add_utf32 (hb_buffer_t    *buffer,
     849                 :                      const uint32_t *text,
     850                 :                      int             text_length,
     851                 :                      unsigned int    item_offset,
     852                 :                      int             item_length)
     853                 : {
     854                 : #define UTF_NEXT(S, E, U)       ((U) = *(S), (S)+1)
     855               0 :   ADD_UTF (uint32_t);
     856                 : #undef UTF_NEXT
     857            4392 : }
     858                 : 
     859                 : 

Generated by: LCOV version 1.7