LCOV - code coverage report
Current view: top level - gfx/harfbuzz/src - hb-buffer.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 138 536 25.7 %
Date: 2017-07-14 16:53:18 Functions: 19 81 23.5 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "hb-buffer-private.hh"
      31             : #include "hb-utf-private.hh"
      32             : 
      33             : 
      34             : #ifndef HB_DEBUG_BUFFER
      35             : #define HB_DEBUG_BUFFER (HB_DEBUG+0)
      36             : #endif
      37             : 
      38             : /**
      39             :  * SECTION: hb-buffer
      40             :  * @title: Buffers
      41             :  * @short_description: Input and output buffers
      42             :  * @include: hb.h
      43             :  *
      44             :  * Buffers serve dual role in HarfBuzz; they hold the input characters that are
      45             :  * passed hb_shape(), and after shaping they hold the output glyphs.
      46             :  **/
      47             : 
      48             : /**
      49             :  * hb_segment_properties_equal:
      50             :  * @a: first #hb_segment_properties_t to compare.
      51             :  * @b: second #hb_segment_properties_t to compare.
      52             :  *
      53             :  * Checks the equality of two #hb_segment_properties_t's.
      54             :  *
      55             :  * Return value:
      56             :  * %true if all properties of @a equal those of @b, false otherwise.
      57             :  *
      58             :  * Since: 0.9.7
      59             :  **/
      60             : hb_bool_t
      61          66 : hb_segment_properties_equal (const hb_segment_properties_t *a,
      62             :                              const hb_segment_properties_t *b)
      63             : {
      64         132 :   return a->direction == b->direction &&
      65         132 :          a->script    == b->script    &&
      66         132 :          a->language  == b->language  &&
      67         198 :          a->reserved1 == b->reserved1 &&
      68         132 :          a->reserved2 == b->reserved2;
      69             : 
      70             : }
      71             : 
      72             : /**
      73             :  * hb_segment_properties_hash:
      74             :  * @p: #hb_segment_properties_t to hash.
      75             :  *
      76             :  * Creates a hash representing @p.
      77             :  *
      78             :  * Return value:
      79             :  * A hash of @p.
      80             :  *
      81             :  * Since: 0.9.7
      82             :  **/
      83             : unsigned int
      84           0 : hb_segment_properties_hash (const hb_segment_properties_t *p)
      85             : {
      86           0 :   return (unsigned int) p->direction ^
      87           0 :          (unsigned int) p->script ^
      88           0 :          (intptr_t) (p->language);
      89             : }
      90             : 
      91             : 
      92             : 
      93             : /* Here is how the buffer works internally:
      94             :  *
      95             :  * There are two info pointers: info and out_info.  They always have
      96             :  * the same allocated size, but different lengths.
      97             :  *
      98             :  * As an optimization, both info and out_info may point to the
      99             :  * same piece of memory, which is owned by info.  This remains the
     100             :  * case as long as out_len doesn't exceed i at any time.
     101             :  * In that case, swap_buffers() is no-op and the glyph operations operate
     102             :  * mostly in-place.
     103             :  *
     104             :  * As soon as out_info gets longer than info, out_info is moved over
     105             :  * to an alternate buffer (which we reuse the pos buffer for!), and its
     106             :  * current contents (out_len entries) are copied to the new place.
     107             :  * This should all remain transparent to the user.  swap_buffers() then
     108             :  * switches info and out_info.
     109             :  */
     110             : 
     111             : 
     112             : 
     113             : /* Internal API */
     114             : 
     115             : bool
     116           3 : hb_buffer_t::enlarge (unsigned int size)
     117             : {
     118           3 :   if (unlikely (in_error))
     119           0 :     return false;
     120           3 :   if (unlikely (size > max_len))
     121             :   {
     122           0 :     in_error = true;
     123           0 :     return false;
     124             :   }
     125             : 
     126           3 :   unsigned int new_allocated = allocated;
     127           3 :   hb_glyph_position_t *new_pos = NULL;
     128           3 :   hb_glyph_info_t *new_info = NULL;
     129           3 :   bool separate_out = out_info != info;
     130             : 
     131           3 :   if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
     132           0 :     goto done;
     133             : 
     134           9 :   while (size >= new_allocated)
     135           3 :     new_allocated += (new_allocated >> 1) + 32;
     136             : 
     137             :   ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0]));
     138           3 :   if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0]))))
     139           0 :     goto done;
     140             : 
     141           3 :   new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0]));
     142           3 :   new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0]));
     143             : 
     144             : done:
     145           3 :   if (unlikely (!new_pos || !new_info))
     146           0 :     in_error = true;
     147             : 
     148           3 :   if (likely (new_pos))
     149           3 :     pos = new_pos;
     150             : 
     151           3 :   if (likely (new_info))
     152           3 :     info = new_info;
     153             : 
     154           3 :   out_info = separate_out ? (hb_glyph_info_t *) pos : info;
     155           3 :   if (likely (!in_error))
     156           3 :     allocated = new_allocated;
     157             : 
     158           3 :   return likely (!in_error);
     159             : }
     160             : 
     161             : bool
     162           0 : hb_buffer_t::make_room_for (unsigned int num_in,
     163             :                             unsigned int num_out)
     164             : {
     165           0 :   if (unlikely (!ensure (out_len + num_out))) return false;
     166             : 
     167           0 :   if (out_info == info &&
     168           0 :       out_len + num_out > idx + num_in)
     169             :   {
     170           0 :     assert (have_output);
     171             : 
     172           0 :     out_info = (hb_glyph_info_t *) pos;
     173           0 :     memcpy (out_info, info, out_len * sizeof (out_info[0]));
     174             :   }
     175             : 
     176           0 :   return true;
     177             : }
     178             : 
     179             : bool
     180           0 : hb_buffer_t::shift_forward (unsigned int count)
     181             : {
     182           0 :   assert (have_output);
     183           0 :   if (unlikely (!ensure (len + count))) return false;
     184             : 
     185           0 :   memmove (info + idx + count, info + idx, (len - idx) * sizeof (info[0]));
     186           0 :   if (idx + count > len)
     187             :   {
     188             :     /* Under memory failure we might expose this area.  At least
     189             :      * clean it up.  Oh well... */
     190           0 :     memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
     191             :   }
     192           0 :   len += count;
     193           0 :   idx += count;
     194             : 
     195           0 :   return true;
     196             : }
     197             : 
     198             : hb_buffer_t::scratch_buffer_t *
     199           0 : hb_buffer_t::get_scratch_buffer (unsigned int *size)
     200             : {
     201           0 :   have_output = false;
     202           0 :   have_positions = false;
     203             : 
     204           0 :   out_len = 0;
     205           0 :   out_info = info;
     206             : 
     207           0 :   assert ((uintptr_t) pos % sizeof (scratch_buffer_t) == 0);
     208           0 :   *size = allocated * sizeof (pos[0]) / sizeof (scratch_buffer_t);
     209           0 :   return (scratch_buffer_t *) (void *) pos;
     210             : }
     211             : 
     212             : 
     213             : 
     214             : /* HarfBuzz-Internal API */
     215             : 
     216             : void
     217           2 : hb_buffer_t::reset (void)
     218             : {
     219           2 :   if (unlikely (hb_object_is_inert (this)))
     220           0 :     return;
     221             : 
     222           2 :   hb_unicode_funcs_destroy (unicode);
     223           2 :   unicode = hb_unicode_funcs_get_default ();
     224           2 :   flags = HB_BUFFER_FLAG_DEFAULT;
     225           2 :   replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
     226             : 
     227           2 :   clear ();
     228             : }
     229             : 
     230             : void
     231          36 : hb_buffer_t::clear (void)
     232             : {
     233          36 :   if (unlikely (hb_object_is_inert (this)))
     234           0 :     return;
     235             : 
     236          36 :   hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
     237          36 :   props = default_props;
     238          36 :   scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
     239             : 
     240          36 :   content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
     241          36 :   in_error = false;
     242          36 :   have_output = false;
     243          36 :   have_positions = false;
     244             : 
     245          36 :   idx = 0;
     246          36 :   len = 0;
     247          36 :   out_len = 0;
     248          36 :   out_info = info;
     249             : 
     250          36 :   serial = 0;
     251             : 
     252          36 :   memset (context, 0, sizeof context);
     253          36 :   memset (context_len, 0, sizeof context_len);
     254             : 
     255          36 :   deallocate_var_all ();
     256             : }
     257             : 
     258             : void
     259         265 : hb_buffer_t::add (hb_codepoint_t  codepoint,
     260             :                   unsigned int    cluster)
     261             : {
     262             :   hb_glyph_info_t *glyph;
     263             : 
     264         265 :   if (unlikely (!ensure (len + 1))) return;
     265             : 
     266         265 :   glyph = &info[len];
     267             : 
     268         265 :   memset (glyph, 0, sizeof (*glyph));
     269         265 :   glyph->codepoint = codepoint;
     270         265 :   glyph->mask = 1;
     271         265 :   glyph->cluster = cluster;
     272             : 
     273         265 :   len++;
     274             : }
     275             : 
     276             : void
     277           0 : hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info)
     278             : {
     279           0 :   if (unlikely (!ensure (len + 1))) return;
     280             : 
     281           0 :   info[len] = glyph_info;
     282             : 
     283           0 :   len++;
     284             : }
     285             : 
     286             : 
     287             : void
     288           0 : hb_buffer_t::remove_output (void)
     289             : {
     290           0 :   if (unlikely (hb_object_is_inert (this)))
     291           0 :     return;
     292             : 
     293           0 :   have_output = false;
     294           0 :   have_positions = false;
     295             : 
     296           0 :   out_len = 0;
     297           0 :   out_info = info;
     298             : }
     299             : 
     300             : void
     301         320 : hb_buffer_t::clear_output (void)
     302             : {
     303         320 :   if (unlikely (hb_object_is_inert (this)))
     304           0 :     return;
     305             : 
     306         320 :   have_output = true;
     307         320 :   have_positions = false;
     308             : 
     309         320 :   out_len = 0;
     310         320 :   out_info = info;
     311             : }
     312             : 
     313             : void
     314          34 : hb_buffer_t::clear_positions (void)
     315             : {
     316          34 :   if (unlikely (hb_object_is_inert (this)))
     317           0 :     return;
     318             : 
     319          34 :   have_output = false;
     320          34 :   have_positions = true;
     321             : 
     322          34 :   out_len = 0;
     323          34 :   out_info = info;
     324             : 
     325          34 :   memset (pos, 0, sizeof (pos[0]) * len);
     326             : }
     327             : 
     328             : void
     329          68 : hb_buffer_t::swap_buffers (void)
     330             : {
     331          68 :   if (unlikely (in_error)) return;
     332             : 
     333          68 :   assert (have_output);
     334          68 :   have_output = false;
     335             : 
     336          68 :   if (out_info != info)
     337             :   {
     338             :     hb_glyph_info_t *tmp_string;
     339           0 :     tmp_string = info;
     340           0 :     info = out_info;
     341           0 :     out_info = tmp_string;
     342           0 :     pos = (hb_glyph_position_t *) out_info;
     343             :   }
     344             : 
     345             :   unsigned int tmp;
     346          68 :   tmp = len;
     347          68 :   len = out_len;
     348          68 :   out_len = tmp;
     349             : 
     350          68 :   idx = 0;
     351             : }
     352             : 
     353             : 
     354             : void
     355           0 : hb_buffer_t::replace_glyphs (unsigned int num_in,
     356             :                              unsigned int num_out,
     357             :                              const uint32_t *glyph_data)
     358             : {
     359           0 :   if (unlikely (!make_room_for (num_in, num_out))) return;
     360             : 
     361           0 :   merge_clusters (idx, idx + num_in);
     362             : 
     363           0 :   hb_glyph_info_t orig_info = info[idx];
     364           0 :   hb_glyph_info_t *pinfo = &out_info[out_len];
     365           0 :   for (unsigned int i = 0; i < num_out; i++)
     366             :   {
     367           0 :     *pinfo = orig_info;
     368           0 :     pinfo->codepoint = glyph_data[i];
     369           0 :     pinfo++;
     370             :   }
     371             : 
     372           0 :   idx  += num_in;
     373           0 :   out_len += num_out;
     374             : }
     375             : 
     376             : void
     377           0 : hb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
     378             : {
     379           0 :   if (unlikely (!make_room_for (0, 1))) return;
     380             : 
     381           0 :   out_info[out_len] = info[idx];
     382           0 :   out_info[out_len].codepoint = glyph_index;
     383             : 
     384           0 :   out_len++;
     385             : }
     386             : 
     387             : void
     388           0 : hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info)
     389             : {
     390           0 :   if (unlikely (!make_room_for (0, 1))) return;
     391             : 
     392           0 :   out_info[out_len] = glyph_info;
     393             : 
     394           0 :   out_len++;
     395             : }
     396             : 
     397             : void
     398           0 : hb_buffer_t::copy_glyph (void)
     399             : {
     400           0 :   if (unlikely (!make_room_for (0, 1))) return;
     401             : 
     402           0 :   out_info[out_len] = info[idx];
     403             : 
     404           0 :   out_len++;
     405             : }
     406             : 
     407             : bool
     408           0 : hb_buffer_t::move_to (unsigned int i)
     409             : {
     410           0 :   if (!have_output)
     411             :   {
     412           0 :     assert (i <= len);
     413           0 :     idx = i;
     414           0 :     return true;
     415             :   }
     416           0 :   if (unlikely (in_error))
     417           0 :     return false;
     418             : 
     419           0 :   assert (i <= out_len + (len - idx));
     420             : 
     421           0 :   if (out_len < i)
     422             :   {
     423           0 :     unsigned int count = i - out_len;
     424           0 :     if (unlikely (!make_room_for (count, count))) return false;
     425             : 
     426           0 :     memmove (out_info + out_len, info + idx, count * sizeof (out_info[0]));
     427           0 :     idx += count;
     428           0 :     out_len += count;
     429             :   }
     430           0 :   else if (out_len > i)
     431             :   {
     432             :     /* Tricky part: rewinding... */
     433           0 :     unsigned int count = out_len - i;
     434             : 
     435             :     /* This will blow in our face if memory allocation fails later
     436             :      * in this same lookup... */
     437           0 :     if (unlikely (idx < count && !shift_forward (count + 32))) return false;
     438             : 
     439           0 :     assert (idx >= count);
     440             : 
     441           0 :     idx -= count;
     442           0 :     out_len -= count;
     443           0 :     memmove (info + idx, out_info + out_len, count * sizeof (out_info[0]));
     444             :   }
     445             : 
     446           0 :   return true;
     447             : }
     448             : 
     449             : void
     450           0 : hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
     451             : {
     452           0 :   if (unlikely (out_info != info || out_len != idx)) {
     453           0 :     if (unlikely (!make_room_for (1, 1))) return;
     454           0 :     out_info[out_len] = info[idx];
     455             :   }
     456           0 :   out_info[out_len].codepoint = glyph_index;
     457             : 
     458           0 :   idx++;
     459           0 :   out_len++;
     460             : }
     461             : 
     462             : 
     463             : void
     464           0 : hb_buffer_t::set_masks (hb_mask_t    value,
     465             :                         hb_mask_t    mask,
     466             :                         unsigned int cluster_start,
     467             :                         unsigned int cluster_end)
     468             : {
     469           0 :   hb_mask_t not_mask = ~mask;
     470           0 :   value &= mask;
     471             : 
     472           0 :   if (!mask)
     473           0 :     return;
     474             : 
     475           0 :   if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
     476           0 :     unsigned int count = len;
     477           0 :     for (unsigned int i = 0; i < count; i++)
     478           0 :       info[i].mask = (info[i].mask & not_mask) | value;
     479           0 :     return;
     480             :   }
     481             : 
     482           0 :   unsigned int count = len;
     483           0 :   for (unsigned int i = 0; i < count; i++)
     484           0 :     if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end)
     485           0 :       info[i].mask = (info[i].mask & not_mask) | value;
     486             : }
     487             : 
     488             : void
     489           0 : hb_buffer_t::reverse_range (unsigned int start,
     490             :                             unsigned int end)
     491             : {
     492             :   unsigned int i, j;
     493             : 
     494           0 :   if (end - start < 2)
     495           0 :     return;
     496             : 
     497           0 :   for (i = start, j = end - 1; i < j; i++, j--) {
     498             :     hb_glyph_info_t t;
     499             : 
     500           0 :     t = info[i];
     501           0 :     info[i] = info[j];
     502           0 :     info[j] = t;
     503             :   }
     504             : 
     505           0 :   if (have_positions) {
     506           0 :     for (i = start, j = end - 1; i < j; i++, j--) {
     507             :       hb_glyph_position_t t;
     508             : 
     509           0 :       t = pos[i];
     510           0 :       pos[i] = pos[j];
     511           0 :       pos[j] = t;
     512             :     }
     513             :   }
     514             : }
     515             : 
     516             : void
     517           0 : hb_buffer_t::reverse (void)
     518             : {
     519           0 :   if (unlikely (!len))
     520           0 :     return;
     521             : 
     522           0 :   reverse_range (0, len);
     523             : }
     524             : 
     525             : void
     526           0 : hb_buffer_t::reverse_clusters (void)
     527             : {
     528             :   unsigned int i, start, count, last_cluster;
     529             : 
     530           0 :   if (unlikely (!len))
     531           0 :     return;
     532             : 
     533           0 :   reverse ();
     534             : 
     535           0 :   count = len;
     536           0 :   start = 0;
     537           0 :   last_cluster = info[0].cluster;
     538           0 :   for (i = 1; i < count; i++) {
     539           0 :     if (last_cluster != info[i].cluster) {
     540           0 :       reverse_range (start, i);
     541           0 :       start = i;
     542           0 :       last_cluster = info[i].cluster;
     543             :     }
     544             :   }
     545           0 :   reverse_range (start, i);
     546             : }
     547             : 
     548             : void
     549           0 : hb_buffer_t::merge_clusters_impl (unsigned int start,
     550             :                                   unsigned int end)
     551             : {
     552           0 :   if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
     553           0 :     return;
     554             : 
     555           0 :   unsigned int cluster = info[start].cluster;
     556             : 
     557           0 :   for (unsigned int i = start + 1; i < end; i++)
     558           0 :     cluster = MIN (cluster, info[i].cluster);
     559             : 
     560             :   /* Extend end */
     561           0 :   while (end < len && info[end - 1].cluster == info[end].cluster)
     562           0 :     end++;
     563             : 
     564             :   /* Extend start */
     565           0 :   while (idx < start && info[start - 1].cluster == info[start].cluster)
     566           0 :     start--;
     567             : 
     568             :   /* If we hit the start of buffer, continue in out-buffer. */
     569           0 :   if (idx == start)
     570           0 :     for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--)
     571           0 :       out_info[i - 1].cluster = cluster;
     572             : 
     573           0 :   for (unsigned int i = start; i < end; i++)
     574           0 :     info[i].cluster = cluster;
     575             : }
     576             : void
     577           0 : hb_buffer_t::merge_out_clusters (unsigned int start,
     578             :                                  unsigned int end)
     579             : {
     580           0 :   if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
     581           0 :     return;
     582             : 
     583           0 :   if (unlikely (end - start < 2))
     584           0 :     return;
     585             : 
     586           0 :   unsigned int cluster = out_info[start].cluster;
     587             : 
     588           0 :   for (unsigned int i = start + 1; i < end; i++)
     589           0 :     cluster = MIN (cluster, out_info[i].cluster);
     590             : 
     591             :   /* Extend start */
     592           0 :   while (start && out_info[start - 1].cluster == out_info[start].cluster)
     593           0 :     start--;
     594             : 
     595             :   /* Extend end */
     596           0 :   while (end < out_len && out_info[end - 1].cluster == out_info[end].cluster)
     597           0 :     end++;
     598             : 
     599             :   /* If we hit the end of out-buffer, continue in buffer. */
     600           0 :   if (end == out_len)
     601           0 :     for (unsigned int i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++)
     602           0 :       info[i].cluster = cluster;
     603             : 
     604           0 :   for (unsigned int i = start; i < end; i++)
     605           0 :     out_info[i].cluster = cluster;
     606             : }
     607             : void
     608           0 : hb_buffer_t::delete_glyph ()
     609             : {
     610           0 :   unsigned int cluster = info[idx].cluster;
     611           0 :   if (idx + 1 < len && cluster == info[idx + 1].cluster)
     612             :   {
     613             :     /* Cluster survives; do nothing. */
     614           0 :     goto done;
     615             :   }
     616             : 
     617           0 :   if (out_len)
     618             :   {
     619             :     /* Merge cluster backward. */
     620           0 :     if (cluster < out_info[out_len - 1].cluster)
     621             :     {
     622           0 :       unsigned int old_cluster = out_info[out_len - 1].cluster;
     623           0 :       for (unsigned i = out_len; i && out_info[i - 1].cluster == old_cluster; i--)
     624           0 :         out_info[i - 1].cluster = cluster;
     625             :     }
     626           0 :     goto done;
     627             :   }
     628             : 
     629           0 :   if (idx + 1 < len)
     630             :   {
     631             :     /* Merge cluster forward. */
     632           0 :     merge_clusters (idx, idx + 2);
     633           0 :     goto done;
     634             :   }
     635             : 
     636             : done:
     637           0 :   skip_glyph ();
     638           0 : }
     639             : 
     640             : void
     641           0 : hb_buffer_t::guess_segment_properties (void)
     642             : {
     643           0 :   assert (content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
     644             :           (!len && content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
     645             : 
     646             :   /* If script is set to INVALID, guess from buffer contents */
     647           0 :   if (props.script == HB_SCRIPT_INVALID) {
     648           0 :     for (unsigned int i = 0; i < len; i++) {
     649           0 :       hb_script_t script = unicode->script (info[i].codepoint);
     650           0 :       if (likely (script != HB_SCRIPT_COMMON &&
     651             :                   script != HB_SCRIPT_INHERITED &&
     652             :                   script != HB_SCRIPT_UNKNOWN)) {
     653           0 :         props.script = script;
     654           0 :         break;
     655             :       }
     656             :     }
     657             :   }
     658             : 
     659             :   /* If direction is set to INVALID, guess from script */
     660           0 :   if (props.direction == HB_DIRECTION_INVALID) {
     661           0 :     props.direction = hb_script_get_horizontal_direction (props.script);
     662             :   }
     663             : 
     664             :   /* If language is not set, use default language from locale */
     665           0 :   if (props.language == HB_LANGUAGE_INVALID) {
     666             :     /* TODO get_default_for_script? using $LANGUAGE */
     667           0 :     props.language = hb_language_get_default ();
     668             :   }
     669           0 : }
     670             : 
     671             : 
     672             : /* Public API */
     673             : 
     674             : /**
     675             :  * hb_buffer_create: (Xconstructor)
     676             :  *
     677             :  * Creates a new #hb_buffer_t with all properties to defaults.
     678             :  *
     679             :  * Return value: (transfer full):
     680             :  * A newly allocated #hb_buffer_t with a reference count of 1. The initial
     681             :  * reference count should be released with hb_buffer_destroy() when you are done
     682             :  * using the #hb_buffer_t. This function never returns %NULL. If memory cannot
     683             :  * be allocated, a special #hb_buffer_t object will be returned on which
     684             :  * hb_buffer_allocation_successful() returns %false.
     685             :  *
     686             :  * Since: 0.9.2
     687             :  **/
     688             : hb_buffer_t *
     689           2 : hb_buffer_create (void)
     690             : {
     691             :   hb_buffer_t *buffer;
     692             : 
     693           2 :   if (!(buffer = hb_object_create<hb_buffer_t> ()))
     694           0 :     return hb_buffer_get_empty ();
     695             : 
     696           2 :   buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
     697             : 
     698           2 :   buffer->reset ();
     699             : 
     700           2 :   return buffer;
     701             : }
     702             : 
     703             : /**
     704             :  * hb_buffer_get_empty:
     705             :  *
     706             :  * 
     707             :  *
     708             :  * Return value: (transfer full):
     709             :  *
     710             :  * Since: 0.9.2
     711             :  **/
     712             : hb_buffer_t *
     713           0 : hb_buffer_get_empty (void)
     714             : {
     715             :   static const hb_buffer_t _hb_buffer_nil = {
     716             :     HB_OBJECT_HEADER_STATIC,
     717             : 
     718             :     const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
     719             :     HB_BUFFER_FLAG_DEFAULT,
     720             :     HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
     721             :     HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
     722             :     HB_BUFFER_SCRATCH_FLAG_DEFAULT,
     723             :     HB_BUFFER_MAX_LEN_DEFAULT,
     724             : 
     725             :     HB_BUFFER_CONTENT_TYPE_INVALID,
     726             :     HB_SEGMENT_PROPERTIES_DEFAULT,
     727             :     true, /* in_error */
     728             :     true, /* have_output */
     729             :     true  /* have_positions */
     730             : 
     731             :     /* Zero is good enough for everything else. */
     732             :   };
     733             : 
     734           0 :   return const_cast<hb_buffer_t *> (&_hb_buffer_nil);
     735             : }
     736             : 
     737             : /**
     738             :  * hb_buffer_reference: (skip)
     739             :  * @buffer: an #hb_buffer_t.
     740             :  *
     741             :  * Increases the reference count on @buffer by one. This prevents @buffer from
     742             :  * being destroyed until a matching call to hb_buffer_destroy() is made.
     743             :  *
     744             :  * Return value: (transfer full):
     745             :  * The referenced #hb_buffer_t.
     746             :  *
     747             :  * Since: 0.9.2
     748             :  **/
     749             : hb_buffer_t *
     750           0 : hb_buffer_reference (hb_buffer_t *buffer)
     751             : {
     752           0 :   return hb_object_reference (buffer);
     753             : }
     754             : 
     755             : /**
     756             :  * hb_buffer_destroy: (skip)
     757             :  * @buffer: an #hb_buffer_t.
     758             :  *
     759             :  * Deallocate the @buffer.
     760             :  * Decreases the reference count on @buffer by one. If the result is zero, then
     761             :  * @buffer and all associated resources are freed. See hb_buffer_reference().
     762             :  *
     763             :  * Since: 0.9.2
     764             :  **/
     765             : void
     766           0 : hb_buffer_destroy (hb_buffer_t *buffer)
     767             : {
     768           0 :   if (!hb_object_destroy (buffer)) return;
     769             : 
     770           0 :   hb_unicode_funcs_destroy (buffer->unicode);
     771             : 
     772           0 :   free (buffer->info);
     773           0 :   free (buffer->pos);
     774           0 :   if (buffer->message_destroy)
     775           0 :     buffer->message_destroy (buffer->message_data);
     776             : 
     777           0 :   free (buffer);
     778             : }
     779             : 
     780             : /**
     781             :  * hb_buffer_set_user_data: (skip)
     782             :  * @buffer: an #hb_buffer_t.
     783             :  * @key: 
     784             :  * @data: 
     785             :  * @destroy: 
     786             :  * @replace: 
     787             :  *
     788             :  * 
     789             :  *
     790             :  * Return value: 
     791             :  *
     792             :  * Since: 0.9.2
     793             :  **/
     794             : hb_bool_t
     795           0 : hb_buffer_set_user_data (hb_buffer_t        *buffer,
     796             :                          hb_user_data_key_t *key,
     797             :                          void *              data,
     798             :                          hb_destroy_func_t   destroy,
     799             :                          hb_bool_t           replace)
     800             : {
     801           0 :   return hb_object_set_user_data (buffer, key, data, destroy, replace);
     802             : }
     803             : 
     804             : /**
     805             :  * hb_buffer_get_user_data: (skip)
     806             :  * @buffer: an #hb_buffer_t.
     807             :  * @key: 
     808             :  *
     809             :  * 
     810             :  *
     811             :  * Return value: 
     812             :  *
     813             :  * Since: 0.9.2
     814             :  **/
     815             : void *
     816           0 : hb_buffer_get_user_data (hb_buffer_t        *buffer,
     817             :                          hb_user_data_key_t *key)
     818             : {
     819           0 :   return hb_object_get_user_data (buffer, key);
     820             : }
     821             : 
     822             : 
     823             : /**
     824             :  * hb_buffer_set_content_type:
     825             :  * @buffer: an #hb_buffer_t.
     826             :  * @content_type: the type of buffer contents to set
     827             :  *
     828             :  * Sets the type of @buffer contents, buffers are either empty, contain
     829             :  * characters (before shaping) or glyphs (the result of shaping).
     830             :  *
     831             :  * Since: 0.9.5
     832             :  **/
     833             : void
     834           0 : hb_buffer_set_content_type (hb_buffer_t              *buffer,
     835             :                             hb_buffer_content_type_t  content_type)
     836             : {
     837           0 :   buffer->content_type = content_type;
     838           0 : }
     839             : 
     840             : /**
     841             :  * hb_buffer_get_content_type:
     842             :  * @buffer: an #hb_buffer_t.
     843             :  *
     844             :  * see hb_buffer_set_content_type().
     845             :  *
     846             :  * Return value:
     847             :  * The type of @buffer contents.
     848             :  *
     849             :  * Since: 0.9.5
     850             :  **/
     851             : hb_buffer_content_type_t
     852           0 : hb_buffer_get_content_type (hb_buffer_t *buffer)
     853             : {
     854           0 :   return buffer->content_type;
     855             : }
     856             : 
     857             : 
     858             : /**
     859             :  * hb_buffer_set_unicode_funcs:
     860             :  * @buffer: an #hb_buffer_t.
     861             :  * @unicode_funcs: 
     862             :  *
     863             :  * 
     864             :  *
     865             :  * Since: 0.9.2
     866             :  **/
     867             : void
     868           2 : hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
     869             :                              hb_unicode_funcs_t *unicode_funcs)
     870             : {
     871           2 :   if (unlikely (hb_object_is_inert (buffer)))
     872           0 :     return;
     873             : 
     874           2 :   if (!unicode_funcs)
     875           0 :     unicode_funcs = hb_unicode_funcs_get_default ();
     876             : 
     877             : 
     878           2 :   hb_unicode_funcs_reference (unicode_funcs);
     879           2 :   hb_unicode_funcs_destroy (buffer->unicode);
     880           2 :   buffer->unicode = unicode_funcs;
     881             : }
     882             : 
     883             : /**
     884             :  * hb_buffer_get_unicode_funcs:
     885             :  * @buffer: an #hb_buffer_t.
     886             :  *
     887             :  * 
     888             :  *
     889             :  * Return value: 
     890             :  *
     891             :  * Since: 0.9.2
     892             :  **/
     893             : hb_unicode_funcs_t *
     894           0 : hb_buffer_get_unicode_funcs (hb_buffer_t        *buffer)
     895             : {
     896           0 :   return buffer->unicode;
     897             : }
     898             : 
     899             : /**
     900             :  * hb_buffer_set_direction:
     901             :  * @buffer: an #hb_buffer_t.
     902             :  * @direction: the #hb_direction_t of the @buffer
     903             :  *
     904             :  * Set the text flow direction of the buffer. No shaping can happen without
     905             :  * setting @buffer direction, and it controls the visual direction for the
     906             :  * output glyphs; for RTL direction the glyphs will be reversed. Many layout
     907             :  * features depend on the proper setting of the direction, for example,
     908             :  * reversing RTL text before shaping, then shaping with LTR direction is not
     909             :  * the same as keeping the text in logical order and shaping with RTL
     910             :  * direction.
     911             :  *
     912             :  * Since: 0.9.2
     913             :  **/
     914             : void
     915          34 : hb_buffer_set_direction (hb_buffer_t    *buffer,
     916             :                          hb_direction_t  direction)
     917             : 
     918             : {
     919          34 :   if (unlikely (hb_object_is_inert (buffer)))
     920           0 :     return;
     921             : 
     922          34 :   buffer->props.direction = direction;
     923             : }
     924             : 
     925             : /**
     926             :  * hb_buffer_get_direction:
     927             :  * @buffer: an #hb_buffer_t.
     928             :  *
     929             :  * See hb_buffer_set_direction()
     930             :  *
     931             :  * Return value:
     932             :  * The direction of the @buffer.
     933             :  *
     934             :  * Since: 0.9.2
     935             :  **/
     936             : hb_direction_t
     937           0 : hb_buffer_get_direction (hb_buffer_t    *buffer)
     938             : {
     939           0 :   return buffer->props.direction;
     940             : }
     941             : 
     942             : /**
     943             :  * hb_buffer_set_script:
     944             :  * @buffer: an #hb_buffer_t.
     945             :  * @script: an #hb_script_t to set.
     946             :  *
     947             :  * Sets the script of @buffer to @script.
     948             :  *
     949             :  * Script is crucial for choosing the proper shaping behaviour for scripts that
     950             :  * require it (e.g. Arabic) and the which OpenType features defined in the font
     951             :  * to be applied.
     952             :  *
     953             :  * You can pass one of the predefined #hb_script_t values, or use
     954             :  * hb_script_from_string() or hb_script_from_iso15924_tag() to get the
     955             :  * corresponding script from an ISO 15924 script tag.
     956             :  *
     957             :  * Since: 0.9.2
     958             :  **/
     959             : void
     960          34 : hb_buffer_set_script (hb_buffer_t *buffer,
     961             :                       hb_script_t  script)
     962             : {
     963          34 :   if (unlikely (hb_object_is_inert (buffer)))
     964           0 :     return;
     965             : 
     966          34 :   buffer->props.script = script;
     967             : }
     968             : 
     969             : /**
     970             :  * hb_buffer_get_script:
     971             :  * @buffer: an #hb_buffer_t.
     972             :  *
     973             :  * See hb_buffer_set_script().
     974             :  *
     975             :  * Return value:
     976             :  * The #hb_script_t of the @buffer.
     977             :  *
     978             :  * Since: 0.9.2
     979             :  **/
     980             : hb_script_t
     981           0 : hb_buffer_get_script (hb_buffer_t *buffer)
     982             : {
     983           0 :   return buffer->props.script;
     984             : }
     985             : 
     986             : /**
     987             :  * hb_buffer_set_language:
     988             :  * @buffer: an #hb_buffer_t.
     989             :  * @language: an hb_language_t to set.
     990             :  *
     991             :  * Sets the language of @buffer to @language.
     992             :  *
     993             :  * Languages are crucial for selecting which OpenType feature to apply to the
     994             :  * buffer which can result in applying language-specific behaviour. Languages
     995             :  * are orthogonal to the scripts, and though they are related, they are
     996             :  * different concepts and should not be confused with each other.
     997             :  *
     998             :  * Use hb_language_from_string() to convert from ISO 639 language codes to
     999             :  * #hb_language_t.
    1000             :  *
    1001             :  * Since: 0.9.2
    1002             :  **/
    1003             : void
    1004          34 : hb_buffer_set_language (hb_buffer_t   *buffer,
    1005             :                         hb_language_t  language)
    1006             : {
    1007          34 :   if (unlikely (hb_object_is_inert (buffer)))
    1008           0 :     return;
    1009             : 
    1010          34 :   buffer->props.language = language;
    1011             : }
    1012             : 
    1013             : /**
    1014             :  * hb_buffer_get_language:
    1015             :  * @buffer: an #hb_buffer_t.
    1016             :  *
    1017             :  * See hb_buffer_set_language().
    1018             :  *
    1019             :  * Return value: (transfer none):
    1020             :  * The #hb_language_t of the buffer. Must not be freed by the caller.
    1021             :  *
    1022             :  * Since: 0.9.2
    1023             :  **/
    1024             : hb_language_t
    1025           0 : hb_buffer_get_language (hb_buffer_t *buffer)
    1026             : {
    1027           0 :   return buffer->props.language;
    1028             : }
    1029             : 
    1030             : /**
    1031             :  * hb_buffer_set_segment_properties:
    1032             :  * @buffer: an #hb_buffer_t.
    1033             :  * @props: an #hb_segment_properties_t to use.
    1034             :  *
    1035             :  * Sets the segment properties of the buffer, a shortcut for calling
    1036             :  * hb_buffer_set_direction(), hb_buffer_set_script() and
    1037             :  * hb_buffer_set_language() individually.
    1038             :  *
    1039             :  * Since: 0.9.7
    1040             :  **/
    1041             : void
    1042           0 : hb_buffer_set_segment_properties (hb_buffer_t *buffer,
    1043             :                                   const hb_segment_properties_t *props)
    1044             : {
    1045           0 :   if (unlikely (hb_object_is_inert (buffer)))
    1046           0 :     return;
    1047             : 
    1048           0 :   buffer->props = *props;
    1049             : }
    1050             : 
    1051             : /**
    1052             :  * hb_buffer_get_segment_properties:
    1053             :  * @buffer: an #hb_buffer_t.
    1054             :  * @props: (out): the output #hb_segment_properties_t.
    1055             :  *
    1056             :  * Sets @props to the #hb_segment_properties_t of @buffer.
    1057             :  *
    1058             :  * Since: 0.9.7
    1059             :  **/
    1060             : void
    1061           0 : hb_buffer_get_segment_properties (hb_buffer_t *buffer,
    1062             :                                   hb_segment_properties_t *props)
    1063             : {
    1064           0 :   *props = buffer->props;
    1065           0 : }
    1066             : 
    1067             : 
    1068             : /**
    1069             :  * hb_buffer_set_flags:
    1070             :  * @buffer: an #hb_buffer_t.
    1071             :  * @flags: the buffer flags to set.
    1072             :  *
    1073             :  * Sets @buffer flags to @flags. See #hb_buffer_flags_t.
    1074             :  *
    1075             :  * Since: 0.9.7
    1076             :  **/
    1077             : void
    1078           0 : hb_buffer_set_flags (hb_buffer_t       *buffer,
    1079             :                      hb_buffer_flags_t  flags)
    1080             : {
    1081           0 :   if (unlikely (hb_object_is_inert (buffer)))
    1082           0 :     return;
    1083             : 
    1084           0 :   buffer->flags = flags;
    1085             : }
    1086             : 
    1087             : /**
    1088             :  * hb_buffer_get_flags:
    1089             :  * @buffer: an #hb_buffer_t.
    1090             :  *
    1091             :  * See hb_buffer_set_flags().
    1092             :  *
    1093             :  * Return value: 
    1094             :  * The @buffer flags.
    1095             :  *
    1096             :  * Since: 0.9.7
    1097             :  **/
    1098             : hb_buffer_flags_t
    1099           0 : hb_buffer_get_flags (hb_buffer_t *buffer)
    1100             : {
    1101           0 :   return buffer->flags;
    1102             : }
    1103             : 
    1104             : /**
    1105             :  * hb_buffer_set_cluster_level:
    1106             :  * @buffer: an #hb_buffer_t.
    1107             :  * @cluster_level: 
    1108             :  *
    1109             :  * 
    1110             :  *
    1111             :  * Since: 0.9.42
    1112             :  **/
    1113             : void
    1114           2 : hb_buffer_set_cluster_level (hb_buffer_t       *buffer,
    1115             :                      hb_buffer_cluster_level_t  cluster_level)
    1116             : {
    1117           2 :   if (unlikely (hb_object_is_inert (buffer)))
    1118           0 :     return;
    1119             : 
    1120           2 :   buffer->cluster_level = cluster_level;
    1121             : }
    1122             : 
    1123             : /**
    1124             :  * hb_buffer_get_cluster_level:
    1125             :  * @buffer: an #hb_buffer_t.
    1126             :  *
    1127             :  * 
    1128             :  *
    1129             :  * Return value: 
    1130             :  *
    1131             :  * Since: 0.9.42
    1132             :  **/
    1133             : hb_buffer_cluster_level_t
    1134           0 : hb_buffer_get_cluster_level (hb_buffer_t *buffer)
    1135             : {
    1136           0 :   return buffer->cluster_level;
    1137             : }
    1138             : 
    1139             : 
    1140             : /**
    1141             :  * hb_buffer_set_replacement_codepoint:
    1142             :  * @buffer: an #hb_buffer_t.
    1143             :  * @replacement: the replacement #hb_codepoint_t
    1144             :  *
    1145             :  * Sets the #hb_codepoint_t that replaces invalid entries for a given encoding
    1146             :  * when adding text to @buffer.
    1147             :  *
    1148             :  * Default is %HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT.
    1149             :  *
    1150             :  * Since: 0.9.31
    1151             :  **/
    1152             : void
    1153           0 : hb_buffer_set_replacement_codepoint (hb_buffer_t    *buffer,
    1154             :                                      hb_codepoint_t  replacement)
    1155             : {
    1156           0 :   if (unlikely (hb_object_is_inert (buffer)))
    1157           0 :     return;
    1158             : 
    1159           0 :   buffer->replacement = replacement;
    1160             : }
    1161             : 
    1162             : /**
    1163             :  * hb_buffer_get_replacement_codepoint:
    1164             :  * @buffer: an #hb_buffer_t.
    1165             :  *
    1166             :  * See hb_buffer_set_replacement_codepoint().
    1167             :  *
    1168             :  * Return value: 
    1169             :  * The @buffer replacement #hb_codepoint_t.
    1170             :  *
    1171             :  * Since: 0.9.31
    1172             :  **/
    1173             : hb_codepoint_t
    1174           0 : hb_buffer_get_replacement_codepoint (hb_buffer_t    *buffer)
    1175             : {
    1176           0 :   return buffer->replacement;
    1177             : }
    1178             : 
    1179             : 
    1180             : /**
    1181             :  * hb_buffer_reset:
    1182             :  * @buffer: an #hb_buffer_t.
    1183             :  *
    1184             :  * Resets the buffer to its initial status, as if it was just newly created
    1185             :  * with hb_buffer_create().
    1186             :  *
    1187             :  * Since: 0.9.2
    1188             :  **/
    1189             : void
    1190           0 : hb_buffer_reset (hb_buffer_t *buffer)
    1191             : {
    1192           0 :   buffer->reset ();
    1193           0 : }
    1194             : 
    1195             : /**
    1196             :  * hb_buffer_clear_contents:
    1197             :  * @buffer: an #hb_buffer_t.
    1198             :  *
    1199             :  * Similar to hb_buffer_reset(), but does not clear the Unicode functions and
    1200             :  * the replacement code point.
    1201             :  *
    1202             :  * Since: 0.9.11
    1203             :  **/
    1204             : void
    1205          34 : hb_buffer_clear_contents (hb_buffer_t *buffer)
    1206             : {
    1207          34 :   buffer->clear ();
    1208          34 : }
    1209             : 
    1210             : /**
    1211             :  * hb_buffer_pre_allocate:
    1212             :  * @buffer: an #hb_buffer_t.
    1213             :  * @size: number of items to pre allocate.
    1214             :  *
    1215             :  * Pre allocates memory for @buffer to fit at least @size number of items.
    1216             :  *
    1217             :  * Return value:
    1218             :  * %true if @buffer memory allocation succeeded, %false otherwise.
    1219             :  *
    1220             :  * Since: 0.9.2
    1221             :  **/
    1222             : hb_bool_t
    1223           0 : hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
    1224             : {
    1225           0 :   return buffer->ensure (size);
    1226             : }
    1227             : 
    1228             : /**
    1229             :  * hb_buffer_allocation_successful:
    1230             :  * @buffer: an #hb_buffer_t.
    1231             :  *
    1232             :  * Check if allocating memory for the buffer succeeded.
    1233             :  *
    1234             :  * Return value:
    1235             :  * %true if @buffer memory allocation succeeded, %false otherwise.
    1236             :  *
    1237             :  * Since: 0.9.2
    1238             :  **/
    1239             : hb_bool_t
    1240           0 : hb_buffer_allocation_successful (hb_buffer_t  *buffer)
    1241             : {
    1242           0 :   return !buffer->in_error;
    1243             : }
    1244             : 
    1245             : /**
    1246             :  * hb_buffer_add:
    1247             :  * @buffer: an #hb_buffer_t.
    1248             :  * @codepoint: a Unicode code point.
    1249             :  * @cluster: the cluster value of @codepoint.
    1250             :  *
    1251             :  * Appends a character with the Unicode value of @codepoint to @buffer, and
    1252             :  * gives it the initial cluster value of @cluster. Clusters can be any thing
    1253             :  * the client wants, they are usually used to refer to the index of the
    1254             :  * character in the input text stream and are output in
    1255             :  * #hb_glyph_info_t.cluster field.
    1256             :  *
    1257             :  * This function does not check the validity of @codepoint, it is up to the
    1258             :  * caller to ensure it is a valid Unicode code point.
    1259             :  *
    1260             :  * Since: 0.9.7
    1261             :  **/
    1262             : void
    1263           0 : hb_buffer_add (hb_buffer_t    *buffer,
    1264             :                hb_codepoint_t  codepoint,
    1265             :                unsigned int    cluster)
    1266             : {
    1267           0 :   buffer->add (codepoint, cluster);
    1268           0 :   buffer->clear_context (1);
    1269           0 : }
    1270             : 
    1271             : /**
    1272             :  * hb_buffer_set_length:
    1273             :  * @buffer: an #hb_buffer_t.
    1274             :  * @length: the new length of @buffer.
    1275             :  *
    1276             :  * Similar to hb_buffer_pre_allocate(), but clears any new items added at the
    1277             :  * end.
    1278             :  *
    1279             :  * Return value: 
    1280             :  * %true if @buffer memory allocation succeeded, %false otherwise.
    1281             :  *
    1282             :  * Since: 0.9.2
    1283             :  **/
    1284             : hb_bool_t
    1285           0 : hb_buffer_set_length (hb_buffer_t  *buffer,
    1286             :                       unsigned int  length)
    1287             : {
    1288           0 :   if (unlikely (hb_object_is_inert (buffer)))
    1289           0 :     return length == 0;
    1290             : 
    1291           0 :   if (!buffer->ensure (length))
    1292           0 :     return false;
    1293             : 
    1294             :   /* Wipe the new space */
    1295           0 :   if (length > buffer->len) {
    1296           0 :     memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
    1297           0 :     if (buffer->have_positions)
    1298           0 :       memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
    1299             :   }
    1300             : 
    1301           0 :   buffer->len = length;
    1302             : 
    1303           0 :   if (!length)
    1304             :   {
    1305           0 :     buffer->content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
    1306           0 :     buffer->clear_context (0);
    1307             :   }
    1308           0 :   buffer->clear_context (1);
    1309             : 
    1310           0 :   return true;
    1311             : }
    1312             : 
    1313             : /**
    1314             :  * hb_buffer_get_length:
    1315             :  * @buffer: an #hb_buffer_t.
    1316             :  *
    1317             :  * Returns the number of items in the buffer.
    1318             :  *
    1319             :  * Return value:
    1320             :  * The @buffer length.
    1321             :  * The value valid as long as buffer has not been modified.
    1322             :  *
    1323             :  * Since: 0.9.2
    1324             :  **/
    1325             : unsigned int
    1326           0 : hb_buffer_get_length (hb_buffer_t *buffer)
    1327             : {
    1328           0 :   return buffer->len;
    1329             : }
    1330             : 
    1331             : /**
    1332             :  * hb_buffer_get_glyph_infos:
    1333             :  * @buffer: an #hb_buffer_t.
    1334             :  * @length: (out): output array length.
    1335             :  *
    1336             :  * Returns @buffer glyph information array.  Returned pointer
    1337             :  * is valid as long as @buffer contents are not modified.
    1338             :  *
    1339             :  * Return value: (transfer none) (array length=length):
    1340             :  * The @buffer glyph information array.
    1341             :  * The value valid as long as buffer has not been modified.
    1342             :  *
    1343             :  * Since: 0.9.2
    1344             :  **/
    1345             : hb_glyph_info_t *
    1346          34 : hb_buffer_get_glyph_infos (hb_buffer_t  *buffer,
    1347             :                            unsigned int *length)
    1348             : {
    1349          34 :   if (length)
    1350          34 :     *length = buffer->len;
    1351             : 
    1352          34 :   return (hb_glyph_info_t *) buffer->info;
    1353             : }
    1354             : 
    1355             : /**
    1356             :  * hb_buffer_get_glyph_positions:
    1357             :  * @buffer: an #hb_buffer_t.
    1358             :  * @length: (out): output length.
    1359             :  *
    1360             :  * Returns @buffer glyph position array.  Returned pointer
    1361             :  * is valid as long as @buffer contents are not modified.
    1362             :  *
    1363             :  * Return value: (transfer none) (array length=length):
    1364             :  * The @buffer glyph position array.
    1365             :  * The value valid as long as buffer has not been modified.
    1366             :  *
    1367             :  * Since: 0.9.2
    1368             :  **/
    1369             : hb_glyph_position_t *
    1370          68 : hb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
    1371             :                                unsigned int *length)
    1372             : {
    1373          68 :   if (!buffer->have_positions)
    1374           0 :     buffer->clear_positions ();
    1375             : 
    1376          68 :   if (length)
    1377          34 :     *length = buffer->len;
    1378             : 
    1379          68 :   return (hb_glyph_position_t *) buffer->pos;
    1380             : }
    1381             : 
    1382             : /**
    1383             :  * hb_buffer_reverse:
    1384             :  * @buffer: an #hb_buffer_t.
    1385             :  *
    1386             :  * Reverses buffer contents.
    1387             :  *
    1388             :  * Since: 0.9.2
    1389             :  **/
    1390             : void
    1391           0 : hb_buffer_reverse (hb_buffer_t *buffer)
    1392             : {
    1393           0 :   buffer->reverse ();
    1394           0 : }
    1395             : 
    1396             : /**
    1397             :  * hb_buffer_reverse_range:
    1398             :  * @buffer: an #hb_buffer_t.
    1399             :  * @start: start index.
    1400             :  * @end: end index.
    1401             :  *
    1402             :  * Reverses buffer contents between start to end.
    1403             :  *
    1404             :  * Since: 0.9.41
    1405             :  **/
    1406             : void
    1407           0 : hb_buffer_reverse_range (hb_buffer_t *buffer,
    1408             :                          unsigned int start, unsigned int end)
    1409             : {
    1410           0 :   buffer->reverse_range (start, end);
    1411           0 : }
    1412             : 
    1413             : /**
    1414             :  * hb_buffer_reverse_clusters:
    1415             :  * @buffer: an #hb_buffer_t.
    1416             :  *
    1417             :  * Reverses buffer clusters.  That is, the buffer contents are
    1418             :  * reversed, then each cluster (consecutive items having the
    1419             :  * same cluster number) are reversed again.
    1420             :  *
    1421             :  * Since: 0.9.2
    1422             :  **/
    1423             : void
    1424           0 : hb_buffer_reverse_clusters (hb_buffer_t *buffer)
    1425             : {
    1426           0 :   buffer->reverse_clusters ();
    1427           0 : }
    1428             : 
    1429             : /**
    1430             :  * hb_buffer_guess_segment_properties:
    1431             :  * @buffer: an #hb_buffer_t.
    1432             :  *
    1433             :  * Sets unset buffer segment properties based on buffer Unicode
    1434             :  * contents.  If buffer is not empty, it must have content type
    1435             :  * %HB_BUFFER_CONTENT_TYPE_UNICODE.
    1436             :  *
    1437             :  * If buffer script is not set (ie. is %HB_SCRIPT_INVALID), it
    1438             :  * will be set to the Unicode script of the first character in
    1439             :  * the buffer that has a script other than %HB_SCRIPT_COMMON,
    1440             :  * %HB_SCRIPT_INHERITED, and %HB_SCRIPT_UNKNOWN.
    1441             :  *
    1442             :  * Next, if buffer direction is not set (ie. is %HB_DIRECTION_INVALID),
    1443             :  * it will be set to the natural horizontal direction of the
    1444             :  * buffer script as returned by hb_script_get_horizontal_direction().
    1445             :  *
    1446             :  * Finally, if buffer language is not set (ie. is %HB_LANGUAGE_INVALID),
    1447             :  * it will be set to the process's default language as returned by
    1448             :  * hb_language_get_default().  This may change in the future by
    1449             :  * taking buffer script into consideration when choosing a language.
    1450             :  *
    1451             :  * Since: 0.9.7
    1452             :  **/
    1453             : void
    1454           0 : hb_buffer_guess_segment_properties (hb_buffer_t *buffer)
    1455             : {
    1456           0 :   buffer->guess_segment_properties ();
    1457           0 : }
    1458             : 
    1459             : template <typename utf_t>
    1460             : static inline void
    1461          34 : hb_buffer_add_utf (hb_buffer_t  *buffer,
    1462             :                    const typename utf_t::codepoint_t *text,
    1463             :                    int           text_length,
    1464             :                    unsigned int  item_offset,
    1465             :                    int           item_length)
    1466             : {
    1467             :   typedef typename utf_t::codepoint_t T;
    1468          34 :   const hb_codepoint_t replacement = buffer->replacement;
    1469             : 
    1470          34 :   assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
    1471             :           (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
    1472             : 
    1473          34 :   if (unlikely (hb_object_is_inert (buffer)))
    1474           0 :     return;
    1475             : 
    1476          34 :   if (text_length == -1)
    1477           0 :     text_length = utf_t::strlen (text);
    1478             : 
    1479          34 :   if (item_length == -1)
    1480           0 :     item_length = text_length - item_offset;
    1481             : 
    1482          34 :   buffer->ensure (buffer->len + item_length * sizeof (T) / 4);
    1483             : 
    1484             :   /* If buffer is empty and pre-context provided, install it.
    1485             :    * This check is written this way, to make sure people can
    1486             :    * provide pre-context in one add_utf() call, then provide
    1487             :    * text in a follow-up call.  See:
    1488             :    *
    1489             :    * https://bugzilla.mozilla.org/show_bug.cgi?id=801410#c13
    1490             :    */
    1491          34 :   if (!buffer->len && item_offset > 0)
    1492             :   {
    1493             :     /* Add pre-context */
    1494           0 :     buffer->clear_context (0);
    1495           0 :     const T *prev = text + item_offset;
    1496           0 :     const T *start = text;
    1497           0 :     while (start < prev && buffer->context_len[0] < buffer->CONTEXT_LENGTH)
    1498             :     {
    1499             :       hb_codepoint_t u;
    1500           0 :       prev = utf_t::prev (prev, start, &u, replacement);
    1501           0 :       buffer->context[0][buffer->context_len[0]++] = u;
    1502             :     }
    1503             :   }
    1504             : 
    1505          34 :   const T *next = text + item_offset;
    1506          34 :   const T *end = next + item_length;
    1507         564 :   while (next < end)
    1508             :   {
    1509             :     hb_codepoint_t u;
    1510         265 :     const T *old_next = next;
    1511         265 :     next = utf_t::next (next, end, &u, replacement);
    1512         265 :     buffer->add (u, old_next - (const T *) text);
    1513             :   }
    1514             : 
    1515             :   /* Add post-context */
    1516          34 :   buffer->clear_context (1);
    1517          34 :   end = text + text_length;
    1518          34 :   while (next < end && buffer->context_len[1] < buffer->CONTEXT_LENGTH)
    1519             :   {
    1520             :     hb_codepoint_t u;
    1521           0 :     next = utf_t::next (next, end, &u, replacement);
    1522           0 :     buffer->context[1][buffer->context_len[1]++] = u;
    1523             :   }
    1524             : 
    1525          34 :   buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE;
    1526             : }
    1527             : 
    1528             : /**
    1529             :  * hb_buffer_add_utf8:
    1530             :  * @buffer: an #hb_buffer_t.
    1531             :  * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8
    1532             :  *               characters to append.
    1533             :  * @text_length: the length of the @text, or -1 if it is %NULL terminated.
    1534             :  * @item_offset: the offset of the first character to add to the @buffer.
    1535             :  * @item_length: the number of characters to add to the @buffer, or -1 for the
    1536             :  *               end of @text (assuming it is %NULL terminated).
    1537             :  *
    1538             :  * See hb_buffer_add_codepoints().
    1539             :  *
    1540             :  * Replaces invalid UTF-8 characters with the @buffer replacement code point,
    1541             :  * see hb_buffer_set_replacement_codepoint().
    1542             :  *
    1543             :  * Since: 0.9.2
    1544             :  **/
    1545             : void
    1546           0 : hb_buffer_add_utf8 (hb_buffer_t  *buffer,
    1547             :                     const char   *text,
    1548             :                     int           text_length,
    1549             :                     unsigned int  item_offset,
    1550             :                     int           item_length)
    1551             : {
    1552           0 :   hb_buffer_add_utf<hb_utf8_t> (buffer, (const uint8_t *) text, text_length, item_offset, item_length);
    1553           0 : }
    1554             : 
    1555             : /**
    1556             :  * hb_buffer_add_utf16:
    1557             :  * @buffer: an #hb_buffer_t.
    1558             :  * @text: (array length=text_length): an array of UTF-16 characters to append.
    1559             :  * @text_length: the length of the @text, or -1 if it is %NULL terminated.
    1560             :  * @item_offset: the offset of the first character to add to the @buffer.
    1561             :  * @item_length: the number of characters to add to the @buffer, or -1 for the
    1562             :  *               end of @text (assuming it is %NULL terminated).
    1563             :  *
    1564             :  * See hb_buffer_add_codepoints().
    1565             :  *
    1566             :  * Replaces invalid UTF-16 characters with the @buffer replacement code point,
    1567             :  * see hb_buffer_set_replacement_codepoint().
    1568             :  *
    1569             :  * Since: 0.9.2
    1570             :  **/
    1571             : void
    1572          34 : hb_buffer_add_utf16 (hb_buffer_t    *buffer,
    1573             :                      const uint16_t *text,
    1574             :                      int             text_length,
    1575             :                      unsigned int    item_offset,
    1576             :                      int             item_length)
    1577             : {
    1578          34 :   hb_buffer_add_utf<hb_utf16_t> (buffer, text, text_length, item_offset, item_length);
    1579          34 : }
    1580             : 
    1581             : /**
    1582             :  * hb_buffer_add_utf32:
    1583             :  * @buffer: an #hb_buffer_t.
    1584             :  * @text: (array length=text_length): an array of UTF-32 characters to append.
    1585             :  * @text_length: the length of the @text, or -1 if it is %NULL terminated.
    1586             :  * @item_offset: the offset of the first character to add to the @buffer.
    1587             :  * @item_length: the number of characters to add to the @buffer, or -1 for the
    1588             :  *               end of @text (assuming it is %NULL terminated).
    1589             :  *
    1590             :  * See hb_buffer_add_codepoints().
    1591             :  *
    1592             :  * Replaces invalid UTF-32 characters with the @buffer replacement code point,
    1593             :  * see hb_buffer_set_replacement_codepoint().
    1594             :  *
    1595             :  * Since: 0.9.2
    1596             :  **/
    1597             : void
    1598           0 : hb_buffer_add_utf32 (hb_buffer_t    *buffer,
    1599             :                      const uint32_t *text,
    1600             :                      int             text_length,
    1601             :                      unsigned int    item_offset,
    1602             :                      int             item_length)
    1603             : {
    1604           0 :   hb_buffer_add_utf<hb_utf32_t<> > (buffer, text, text_length, item_offset, item_length);
    1605           0 : }
    1606             : 
    1607             : /**
    1608             :  * hb_buffer_add_latin1:
    1609             :  * @buffer: an #hb_buffer_t.
    1610             :  * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8
    1611             :  *               characters to append.
    1612             :  * @text_length: the length of the @text, or -1 if it is %NULL terminated.
    1613             :  * @item_offset: the offset of the first character to add to the @buffer.
    1614             :  * @item_length: the number of characters to add to the @buffer, or -1 for the
    1615             :  *               end of @text (assuming it is %NULL terminated).
    1616             :  *
    1617             :  * Similar to hb_buffer_add_codepoints(), but allows only access to first 256
    1618             :  * Unicode code points that can fit in 8-bit strings.
    1619             :  *
    1620             :  * <note>Has nothing to do with non-Unicode Latin-1 encoding.</note>
    1621             :  *
    1622             :  * Since: 0.9.39
    1623             :  **/
    1624             : void
    1625           0 : hb_buffer_add_latin1 (hb_buffer_t   *buffer,
    1626             :                       const uint8_t *text,
    1627             :                       int            text_length,
    1628             :                       unsigned int   item_offset,
    1629             :                       int            item_length)
    1630             : {
    1631           0 :   hb_buffer_add_utf<hb_latin1_t> (buffer, text, text_length, item_offset, item_length);
    1632           0 : }
    1633             : 
    1634             : /**
    1635             :  * hb_buffer_add_codepoints:
    1636             :  * @buffer: a #hb_buffer_t to append characters to.
    1637             :  * @text: (array length=text_length): an array of Unicode code points to append.
    1638             :  * @text_length: the length of the @text, or -1 if it is %NULL terminated.
    1639             :  * @item_offset: the offset of the first code point to add to the @buffer.
    1640             :  * @item_length: the number of code points to add to the @buffer, or -1 for the
    1641             :  *               end of @text (assuming it is %NULL terminated).
    1642             :  *
    1643             :  * Appends characters from @text array to @buffer. The @item_offset is the
    1644             :  * position of the first character from @text that will be appended, and
    1645             :  * @item_length is the number of character. When shaping part of a larger text
    1646             :  * (e.g. a run of text from a paragraph), instead of passing just the substring
    1647             :  * corresponding to the run, it is preferable to pass the whole
    1648             :  * paragraph and specify the run start and length as @item_offset and
    1649             :  * @item_length, respectively, to give HarfBuzz the full context to be able,
    1650             :  * for example, to do cross-run Arabic shaping or properly handle combining
    1651             :  * marks at stat of run.
    1652             :  *
    1653             :  * This function does not check the validity of @text, it is up to the caller
    1654             :  * to ensure it contains a valid Unicode code points.
    1655             :  *
    1656             :  * Since: 0.9.31
    1657             :  **/
    1658             : void
    1659           0 : hb_buffer_add_codepoints (hb_buffer_t          *buffer,
    1660             :                           const hb_codepoint_t *text,
    1661             :                           int                   text_length,
    1662             :                           unsigned int          item_offset,
    1663             :                           int                   item_length)
    1664             : {
    1665           0 :   hb_buffer_add_utf<hb_utf32_t<false> > (buffer, text, text_length, item_offset, item_length);
    1666           0 : }
    1667             : 
    1668             : 
    1669             : static int
    1670           0 : compare_info_codepoint (const hb_glyph_info_t *pa,
    1671             :                         const hb_glyph_info_t *pb)
    1672             : {
    1673           0 :   return (int) pb->codepoint - (int) pa->codepoint;
    1674             : }
    1675             : 
    1676             : static inline void
    1677           0 : normalize_glyphs_cluster (hb_buffer_t *buffer,
    1678             :                           unsigned int start,
    1679             :                           unsigned int end,
    1680             :                           bool backward)
    1681             : {
    1682           0 :   hb_glyph_position_t *pos = buffer->pos;
    1683             : 
    1684             :   /* Total cluster advance */
    1685           0 :   hb_position_t total_x_advance = 0, total_y_advance = 0;
    1686           0 :   for (unsigned int i = start; i < end; i++)
    1687             :   {
    1688           0 :     total_x_advance += pos[i].x_advance;
    1689           0 :     total_y_advance += pos[i].y_advance;
    1690             :   }
    1691             : 
    1692           0 :   hb_position_t x_advance = 0, y_advance = 0;
    1693           0 :   for (unsigned int i = start; i < end; i++)
    1694             :   {
    1695           0 :     pos[i].x_offset += x_advance;
    1696           0 :     pos[i].y_offset += y_advance;
    1697             : 
    1698           0 :     x_advance += pos[i].x_advance;
    1699           0 :     y_advance += pos[i].y_advance;
    1700             : 
    1701           0 :     pos[i].x_advance = 0;
    1702           0 :     pos[i].y_advance = 0;
    1703             :   }
    1704             : 
    1705           0 :   if (backward)
    1706             :   {
    1707             :     /* Transfer all cluster advance to the last glyph. */
    1708           0 :     pos[end - 1].x_advance = total_x_advance;
    1709           0 :     pos[end - 1].y_advance = total_y_advance;
    1710             : 
    1711           0 :     hb_stable_sort (buffer->info + start, end - start - 1, compare_info_codepoint, buffer->pos + start);
    1712             :   } else {
    1713             :     /* Transfer all cluster advance to the first glyph. */
    1714           0 :     pos[start].x_advance += total_x_advance;
    1715           0 :     pos[start].y_advance += total_y_advance;
    1716           0 :     for (unsigned int i = start + 1; i < end; i++) {
    1717           0 :       pos[i].x_offset -= total_x_advance;
    1718           0 :       pos[i].y_offset -= total_y_advance;
    1719             :     }
    1720           0 :     hb_stable_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + start + 1);
    1721             :   }
    1722           0 : }
    1723             : 
    1724             : /**
    1725             :  * hb_buffer_normalize_glyphs:
    1726             :  * @buffer: an #hb_buffer_t.
    1727             :  *
    1728             :  * Reorders a glyph buffer to have canonical in-cluster glyph order / position.
    1729             :  * The resulting clusters should behave identical to pre-reordering clusters.
    1730             :  *
    1731             :  * <note>This has nothing to do with Unicode normalization.</note>
    1732             :  *
    1733             :  * Since: 0.9.2
    1734             :  **/
    1735             : void
    1736           0 : hb_buffer_normalize_glyphs (hb_buffer_t *buffer)
    1737             : {
    1738           0 :   assert (buffer->have_positions);
    1739           0 :   assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
    1740             : 
    1741           0 :   bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
    1742             : 
    1743           0 :   unsigned int count = buffer->len;
    1744           0 :   if (unlikely (!count)) return;
    1745           0 :   hb_glyph_info_t *info = buffer->info;
    1746             : 
    1747           0 :   unsigned int start = 0;
    1748             :   unsigned int end;
    1749           0 :   for (end = start + 1; end < count; end++)
    1750           0 :     if (info[start].cluster != info[end].cluster) {
    1751           0 :       normalize_glyphs_cluster (buffer, start, end, backward);
    1752           0 :       start = end;
    1753             :     }
    1754           0 :   normalize_glyphs_cluster (buffer, start, end, backward);
    1755             : }
    1756             : 
    1757             : void
    1758           0 : hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *))
    1759             : {
    1760           0 :   assert (!have_positions);
    1761           0 :   for (unsigned int i = start + 1; i < end; i++)
    1762             :   {
    1763           0 :     unsigned int j = i;
    1764           0 :     while (j > start && compar (&info[j - 1], &info[i]) > 0)
    1765           0 :       j--;
    1766           0 :     if (i == j)
    1767           0 :       continue;
    1768             :     /* Move item i to occupy place for item j, shift what's in between. */
    1769           0 :     merge_clusters (j, i + 1);
    1770             :     {
    1771           0 :       hb_glyph_info_t t = info[i];
    1772           0 :       memmove (&info[j + 1], &info[j], (i - j) * sizeof (hb_glyph_info_t));
    1773           0 :       info[j] = t;
    1774             :     }
    1775             :   }
    1776           0 : }
    1777             : 
    1778             : /*
    1779             :  * Debugging.
    1780             :  */
    1781             : 
    1782             : /**
    1783             :  * hb_buffer_set_message_func:
    1784             :  * @buffer: an #hb_buffer_t.
    1785             :  * @func: (closure user_data) (destroy destroy) (scope notified):
    1786             :  * @user_data:
    1787             :  * @destroy:
    1788             :  *
    1789             :  * 
    1790             :  *
    1791             :  * Since: 1.1.3
    1792             :  **/
    1793             : void
    1794           0 : hb_buffer_set_message_func (hb_buffer_t *buffer,
    1795             :                             hb_buffer_message_func_t func,
    1796             :                             void *user_data, hb_destroy_func_t destroy)
    1797             : {
    1798           0 :   if (buffer->message_destroy)
    1799           0 :     buffer->message_destroy (buffer->message_data);
    1800             : 
    1801           0 :   if (func) {
    1802           0 :     buffer->message_func = func;
    1803           0 :     buffer->message_data = user_data;
    1804           0 :     buffer->message_destroy = destroy;
    1805             :   } else {
    1806           0 :     buffer->message_func = NULL;
    1807           0 :     buffer->message_data = NULL;
    1808           0 :     buffer->message_destroy = NULL;
    1809             :   }
    1810           0 : }
    1811             : 
    1812             : bool
    1813           0 : hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap)
    1814             : {
    1815             :   char buf[100];
    1816           0 :   vsnprintf (buf, sizeof (buf),  fmt, ap);
    1817           0 :   return (bool) this->message_func (this, font, buf, this->message_data);
    1818             : }

Generated by: LCOV version 1.13