hb-buffer.cc revision 243673d601588a6f704ceafbff5dd5cdf66c47b7
1a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod/*
22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 1998-2004  David Turner and Werner Lemberg
32409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2004,2007,2009,2010  Red Hat, Inc.
42409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2011  Google, Inc.
59f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod *
68f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
79f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod *
8a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * Permission is hereby granted, without written agreement and without
9a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
10a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * software and its documentation for any purpose, provided that the
11a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
12a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * all copies of this software.
13a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod *
14a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
15a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
17a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * DAMAGE.
19a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod *
20a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
21a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
23a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
24a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod *
26a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
27c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod * Google Author(s): Behdad Esfahbod
289f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod */
299f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
3022da7fd94d6318c52df69d70470a85464ffc533dBehdad Esfahbod#include "hb-buffer-private.hh"
319f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
3288a5f5a49b6809d88560791f9cf6b8f78f22a4adBehdad Esfahbod#include <string.h>
3388a5f5a49b6809d88560791f9cf6b8f78f22a4adBehdad Esfahbod
34acdba3f90b232fc12fcb200dca2584481b339118Behdad EsfahbodHB_BEGIN_DECLS
35acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
36f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod
3711fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodstatic hb_buffer_t _hb_buffer_nil = {
38fca368c4682624346a0aaee690e1ad6ed4c0b337Behdad Esfahbod  HB_OBJECT_HEADER_STATIC,
395ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
40d4bee9f813bb299b1c4aab7c33d588be2a7d354bBehdad Esfahbod  &_hb_unicode_funcs_default,
41c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod  {
42c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod    HB_DIRECTION_INVALID,
43c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod    HB_SCRIPT_INVALID,
44c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod    NULL,
45c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod  },
46e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
47e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  TRUE, /* in_error */
48e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  TRUE, /* have_output */
49e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  TRUE  /* have_positions */
5011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod};
5111fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
52a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod/* Here is how the buffer works internally:
53a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod *
54910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * There are two info pointers: info and out_info.  They always have
55910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * the same allocated size, but different lengths.
56a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod *
579d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod * As an optimization, both info and out_info may point to the
587e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod * same piece of memory, which is owned by info.  This remains the
59cc1a8a938b4c13e76b58825a9e1951c4134e634aBehdad Esfahbod * case as long as out_len doesn't exceed i at any time.
60910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * In that case, swap() is no-op and the glyph operations operate
61910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * mostly in-place.
62a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod *
639d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod * As soon as out_info gets longer than info, out_info is moved over
64910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * to an alternate buffer (which we reuse the pos buffer for!), and its
65910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * current contents (out_len entries) are copied to the new place.
66910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * This should all remain transparent to the user.  swap() then
67910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * switches info and out_info.
68a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod */
69a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
70c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod
713567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbodstatic hb_bool_t
723567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod_hb_buffer_enlarge (hb_buffer_t *buffer, unsigned int size)
733567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod{
743567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (unlikely (buffer->in_error))
753567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    return FALSE;
763567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
773567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  unsigned int new_allocated = buffer->allocated;
78e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  hb_glyph_position_t *new_pos = NULL;
79e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  hb_glyph_info_t *new_info = NULL;
80e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  bool separate_out = buffer->out_info != buffer->info;
813567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
82080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod  if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (buffer->info[0]))))
83e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    goto done;
843567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
853567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  while (size > new_allocated)
8665e0063eae2f3adb25315b8bd7b0e7757aa960f3Behdad Esfahbod    new_allocated += (new_allocated >> 1) + 32;
873567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
88b5dd44e24669cd35affcd92788d39ff56cac94dbBehdad Esfahbod  ASSERT_STATIC (sizeof (buffer->info[0]) == sizeof (buffer->pos[0]));
89080a0eb7d82d7195be72c16ece6e0a3ffed636b6Behdad Esfahbod  if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (buffer->info[0]))))
90e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    goto done;
91e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
92e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  new_pos = (hb_glyph_position_t *) realloc (buffer->pos, new_allocated * sizeof (buffer->pos[0]));
93e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  new_info = (hb_glyph_info_t *) realloc (buffer->info, new_allocated * sizeof (buffer->info[0]));
943567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
95e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahboddone:
963567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (unlikely (!new_pos || !new_info))
973567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    buffer->in_error = TRUE;
983567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
993567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (likely (new_pos))
1003567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    buffer->pos = new_pos;
1013567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
1023567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (likely (new_info))
1033567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    buffer->info = new_info;
1043567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
10588474c6fdaf35c56368694a5b164f4988a004d49Behdad Esfahbod  buffer->out_info = separate_out ? (hb_glyph_info_t *) buffer->pos : buffer->info;
1063567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (likely (!buffer->in_error))
1073567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    buffer->allocated = new_allocated;
1083567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
1093567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  return likely (!buffer->in_error);
1103567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod}
1113567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
1123567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbodstatic inline hb_bool_t
1133567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod_hb_buffer_ensure (hb_buffer_t *buffer, unsigned int size)
1143567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod{
1153567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  return likely (size <= buffer->allocated) ? TRUE : _hb_buffer_enlarge (buffer, size);
1163567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod}
1176b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
118acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbodstatic inline hb_bool_t
1193567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod_hb_buffer_ensure_separate (hb_buffer_t *buffer, unsigned int size)
120c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod{
121e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (!size || !_hb_buffer_ensure (buffer, size))) return FALSE;
122a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod
1239d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod  if (buffer->out_info == buffer->info)
124e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  {
125e4679d9fae43f3219c476c5b9e411d1f5d0d5baeBehdad Esfahbod    assert (buffer->have_output);
126e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod
12788474c6fdaf35c56368694a5b164f4988a004d49Behdad Esfahbod    buffer->out_info = (hb_glyph_info_t *) buffer->pos;
12829427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod    memcpy (buffer->out_info, buffer->info, buffer->out_len * sizeof (buffer->out_info[0]));
129e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
130a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod
131a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod  return TRUE;
132a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod}
133a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
1343567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
1356b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod/* Public API */
1366b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
137b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbodhb_buffer_t *
13811fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_create (unsigned int pre_alloc_size)
1399f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod{
140b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  hb_buffer_t *buffer;
141b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod
14247e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod  if (!(buffer = hb_object_create<hb_buffer_t> ()))
14311fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod    return &_hb_buffer_nil;
1449f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
14511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod  if (pre_alloc_size)
1463567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    _hb_buffer_ensure (buffer, pre_alloc_size);
1479f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
148c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod  hb_buffer_reset (buffer);
1495ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
15011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod  return buffer;
15111fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
1527a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
15311fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_t *
15411fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_reference (hb_buffer_t *buffer)
15511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
15647e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod  return hb_object_reference (buffer);
15711fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
158f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
1597a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbodvoid
16011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_destroy (hb_buffer_t *buffer)
1617a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod{
16247e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod  if (!hb_object_destroy (buffer)) return;
16311fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
1645ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  hb_unicode_funcs_destroy (buffer->unicode);
1655ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
1667e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod  free (buffer->info);
1671b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod  free (buffer->pos);
16811fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
169b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  free (buffer);
1707a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod}
1717a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
1725fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_bool_t
1735fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_buffer_set_user_data (hb_buffer_t        *buffer,
1745fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod			 hb_user_data_key_t *key,
1755fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod			 void *              data,
1765fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod			 hb_destroy_func_t   destroy)
1775fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod{
1785fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod  return hb_object_set_user_data (buffer, key, data, destroy);
1795fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod}
1805fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod
1815fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodvoid *
1825fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_buffer_get_user_data (hb_buffer_t        *buffer,
1835fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod			 hb_user_data_key_t *key)
1845fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod{
1855fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod  return hb_object_get_user_data (buffer, key);
1865fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod}
1875fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod
1885ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
1895ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodvoid
1905ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
1915ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod			     hb_unicode_funcs_t *unicode)
1925ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
193e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
194e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
195e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
1960465e69832393cc1ed36508ec5d597fbab64877aBehdad Esfahbod  if (!unicode)
197e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    unicode = _hb_buffer_nil.unicode;
1980465e69832393cc1ed36508ec5d597fbab64877aBehdad Esfahbod
1995ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  hb_unicode_funcs_reference (unicode);
2005ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  hb_unicode_funcs_destroy (buffer->unicode);
2015ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  buffer->unicode = unicode;
2025ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
2035ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
2045ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_unicode_funcs_t *
2055ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_get_unicode_funcs (hb_buffer_t        *buffer)
2065ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
2075ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  return buffer->unicode;
2085ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
2095ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
2105ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodvoid
2115ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_set_direction (hb_buffer_t    *buffer,
2125ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod			 hb_direction_t  direction)
2135ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
2145ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
215e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
216e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
217e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
2184e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  buffer->props.direction = direction;
2195ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
2205ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
2215ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_direction_t
2225ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_get_direction (hb_buffer_t    *buffer)
2235ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
2244e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  return buffer->props.direction;
2255ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
2265ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
227ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodvoid
228ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_set_script (hb_buffer_t *buffer,
229ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod		      hb_script_t  script)
230ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
231e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
232e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
233e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
2344e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  buffer->props.script = script;
235ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
236ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
237ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_script_t
238ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_get_script (hb_buffer_t *buffer)
239ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
2404e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  return buffer->props.script;
241ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
242ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
243ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodvoid
244ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_set_language (hb_buffer_t   *buffer,
245ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod			hb_language_t  language)
246ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
247e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
248e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
249e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
2504e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  buffer->props.language = language;
251ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
252ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
253ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_language_t
254ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_get_language (hb_buffer_t *buffer)
255ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
2564e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  return buffer->props.language;
257ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
258ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
2595ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
2607a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbodvoid
261c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbodhb_buffer_reset (hb_buffer_t *buffer)
262c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod{
263e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
264e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
265e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
266c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod  hb_unicode_funcs_destroy (buffer->unicode);
267c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod  buffer->unicode = _hb_buffer_nil.unicode;
268c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod
269c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod  buffer->props = _hb_buffer_nil.props;
270c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod
271e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  buffer->in_error = FALSE;
272e4679d9fae43f3219c476c5b9e411d1f5d0d5baeBehdad Esfahbod  buffer->have_output = FALSE;
273314905d7548d5be58354546d660754b807b6efb2Behdad Esfahbod  buffer->have_positions = FALSE;
274c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod
275c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod  buffer->i = 0;
2766960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  buffer->len = 0;
27729427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod  buffer->out_len = 0;
2782fc56edff6d64f190271454ccb1b5fd347d4f172Behdad Esfahbod
279c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod  buffer->serial = 0;
2802fc56edff6d64f190271454ccb1b5fd347d4f172Behdad Esfahbod
281c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod  buffer->out_info = buffer->info;
2827a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod}
2837a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
284a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbodhb_bool_t
28502a534b23f2d1e7475109563b9f61221ed020e8bRyan Lortiehb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
286f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod{
2873567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  return _hb_buffer_ensure (buffer, size);
288f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod}
289f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
290aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbodhb_bool_t
291aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbodhb_buffer_allocation_successful (hb_buffer_t  *buffer)
292aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbod{
293aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbod  return !buffer->in_error;
294aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbod}
295aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbod
296f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbodvoid
297f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbodhb_buffer_add (hb_buffer_t    *buffer,
298f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbod	       hb_codepoint_t  codepoint,
299f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbod	       hb_mask_t       mask,
300f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbod	       unsigned int    cluster)
3016b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod{
30288474c6fdaf35c56368694a5b164f4988a004d49Behdad Esfahbod  hb_glyph_info_t *glyph;
3035c0adce1ccc739415c4b26ff13ffd2d77ea4bc6cBehdad Esfahbod
3043567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (unlikely (!_hb_buffer_ensure (buffer, buffer->len + 1))) return;
3056b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
3066960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  glyph = &buffer->info[buffer->len];
307f6a23a0b9171958f76c1d0473b09fc08d2b3a0d0Behdad Esfahbod
308f6a23a0b9171958f76c1d0473b09fc08d2b3a0d0Behdad Esfahbod  memset (glyph, 0, sizeof (*glyph));
309f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  glyph->codepoint = codepoint;
310468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod  glyph->mask = mask;
3116b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod  glyph->cluster = cluster;
3126b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
3136960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  buffer->len++;
3146b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod}
3156b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
3163567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod/* HarfBuzz-Internal API */
3173567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
3183567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbodvoid
3193567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod_hb_buffer_clear_output (hb_buffer_t *buffer)
3203567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod{
321e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
322e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
323e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
3243567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  buffer->have_output = TRUE;
3253567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  buffer->have_positions = FALSE;
3268f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod
3273567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  buffer->out_len = 0;
3283567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  buffer->out_info = buffer->info;
3293567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod}
3303567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
331081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodvoid
3328f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod_hb_buffer_clear_positions (hb_buffer_t *buffer)
3338f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod{
334e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
335e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
336e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
3378f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod  buffer->have_output = FALSE;
3388f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod  buffer->have_positions = TRUE;
3398f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod
3408f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod  memset (buffer->pos, 0, sizeof (buffer->pos[0]) * buffer->len);
3418f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod}
3428f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod
3438f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbodvoid
344c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod_hb_buffer_swap (hb_buffer_t *buffer)
3459f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod{
346e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (buffer->in_error)) return;
3479f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
348e4679d9fae43f3219c476c5b9e411d1f5d0d5baeBehdad Esfahbod  assert (buffer->have_output);
349e4679d9fae43f3219c476c5b9e411d1f5d0d5baeBehdad Esfahbod
3509d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod  if (buffer->out_info != buffer->info)
351e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  {
35288474c6fdaf35c56368694a5b164f4988a004d49Behdad Esfahbod    hb_glyph_info_t *tmp_string;
3537e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod    tmp_string = buffer->info;
3549d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod    buffer->info = buffer->out_info;
3559d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod    buffer->out_info = tmp_string;
35688474c6fdaf35c56368694a5b164f4988a004d49Behdad Esfahbod    buffer->pos = (hb_glyph_position_t *) buffer->out_info;
357e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
3589f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
359e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  unsigned int tmp;
3606960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  tmp = buffer->len;
36129427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod  buffer->len = buffer->out_len;
36229427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod  buffer->out_len = tmp;
3639f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
36436b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  buffer->i = 0;
3659f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod}
3669f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
367081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodvoid
368dd2ffd282c059194fd87fb1664e2e0cdb56a87a0Behdad Esfahbod_hb_buffer_replace_glyphs_be16 (hb_buffer_t *buffer,
369dd2ffd282c059194fd87fb1664e2e0cdb56a87a0Behdad Esfahbod				unsigned int num_in,
370dd2ffd282c059194fd87fb1664e2e0cdb56a87a0Behdad Esfahbod				unsigned int num_out,
371dd2ffd282c059194fd87fb1664e2e0cdb56a87a0Behdad Esfahbod				const uint16_t *glyph_data_be)
37225e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod{
3739d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod  if (buffer->out_info != buffer->info ||
37436b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod      buffer->out_len + num_out > buffer->i + num_in)
37525e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod  {
3763567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    if (unlikely (!_hb_buffer_ensure_separate (buffer, buffer->out_len + num_out)))
377a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod      return;
37825e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod  }
37925e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod
380fe263272a2b26204bc39829a94d90ab537517f3fBehdad Esfahbod  hb_glyph_info_t orig_info = buffer->info[buffer->i];
38125e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod
382fe263272a2b26204bc39829a94d90ab537517f3fBehdad Esfahbod  for (unsigned int i = 0; i < num_out; i++)
38325e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod  {
38488474c6fdaf35c56368694a5b164f4988a004d49Behdad Esfahbod    hb_glyph_info_t *info = &buffer->out_info[buffer->out_len + i];
385fe263272a2b26204bc39829a94d90ab537517f3fBehdad Esfahbod    *info = orig_info;
38625e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod    info->codepoint = hb_be_uint16 (glyph_data_be[i]);
38725e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod  }
38825e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod
38936b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  buffer->i  += num_in;
39029427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod  buffer->out_len += num_out;
39125e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod}
39288a5f5a49b6809d88560791f9cf6b8f78f22a4adBehdad Esfahbod
393081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodvoid
394dd2ffd282c059194fd87fb1664e2e0cdb56a87a0Behdad Esfahbod_hb_buffer_replace_glyph (hb_buffer_t *buffer,
395dd2ffd282c059194fd87fb1664e2e0cdb56a87a0Behdad Esfahbod			  hb_codepoint_t glyph_index)
3969f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod{
39788474c6fdaf35c56368694a5b164f4988a004d49Behdad Esfahbod  hb_glyph_info_t *info;
398c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod
3999d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod  if (buffer->out_info != buffer->info)
400e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  {
4013567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    if (unlikely (!_hb_buffer_ensure (buffer, buffer->out_len + 1))) return;
40236b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod    buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
403e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
40436b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  else if (buffer->out_len != buffer->i)
40536b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod    buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
4069f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
40729427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod  info = &buffer->out_info[buffer->out_len];
408f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  info->codepoint = glyph_index;
409c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod
41036b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  buffer->i++;
41129427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod  buffer->out_len++;
4129f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod}
4139f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
414081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodvoid
415c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod_hb_buffer_next_glyph (hb_buffer_t *buffer)
41615c3e75b39797a153b6bc0598f87b27c4a487228Behdad Esfahbod{
417314905d7548d5be58354546d660754b807b6efb2Behdad Esfahbod  if (buffer->have_output)
418e4679d9fae43f3219c476c5b9e411d1f5d0d5baeBehdad Esfahbod  {
4199d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod    if (buffer->out_info != buffer->info)
420314905d7548d5be58354546d660754b807b6efb2Behdad Esfahbod    {
4213567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod      if (unlikely (!_hb_buffer_ensure (buffer, buffer->out_len + 1))) return;
42236b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod      buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
423314905d7548d5be58354546d660754b807b6efb2Behdad Esfahbod    }
42436b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod    else if (buffer->out_len != buffer->i)
42536b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod      buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
426e4679d9fae43f3219c476c5b9e411d1f5d0d5baeBehdad Esfahbod
42729427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod    buffer->out_len++;
428e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
429a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
43036b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  buffer->i++;
431a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod}
432a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
4331ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbodvoid
43457ac0ecb7843533b2e6e6d6c8a12b2a44437cc1cBehdad Esfahbod_hb_buffer_reset_masks (hb_buffer_t *buffer,
43557ac0ecb7843533b2e6e6d6c8a12b2a44437cc1cBehdad Esfahbod			hb_mask_t    mask)
4361ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod{
4371ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  unsigned int count = buffer->len;
4381ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
439961f9baa7bc3556f1e4e7135859cebe1351f73a4Behdad Esfahbod    buffer->info[i].mask = mask;
4401ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod}
4411ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod
4421ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbodvoid
44357ac0ecb7843533b2e6e6d6c8a12b2a44437cc1cBehdad Esfahbod_hb_buffer_add_masks (hb_buffer_t *buffer,
444bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod		      hb_mask_t    mask)
445bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod{
446bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod  unsigned int count = buffer->len;
447bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
448bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod    buffer->info[i].mask |= mask;
449bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod}
450bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod
451bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbodvoid
452bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod_hb_buffer_set_masks (hb_buffer_t *buffer,
45381c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod		      hb_mask_t    value,
45481c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod		      hb_mask_t    mask,
45581c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod		      unsigned int cluster_start,
45681c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod		      unsigned int cluster_end)
4571ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod{
45881c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod  hb_mask_t not_mask = ~mask;
4595c1c8c9c50ddbe66ea595afb245a208b7775b27cBehdad Esfahbod  value &= mask;
46081c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod
4613506b2e78db27e7835bd2c09c053a9807c9cac40Behdad Esfahbod  if (!mask)
4623506b2e78db27e7835bd2c09c053a9807c9cac40Behdad Esfahbod    return;
4633506b2e78db27e7835bd2c09c053a9807c9cac40Behdad Esfahbod
4641ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
4651ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod    unsigned int count = buffer->len;
4661ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
46781c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod      buffer->info[i].mask = (buffer->info[i].mask & not_mask) | value;
4681ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod    return;
4691ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  }
4701ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod
47134db6f031d7ac009f554386ef990bad44886b9eeBehdad Esfahbod  /* XXX can't bsearch since .cluster may not be sorted. */
4721ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  /* Binary search to find the start position and go from there. */
4731ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  unsigned int min = 0, max = buffer->len;
4741ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  while (min < max)
4751ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  {
4761ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod    unsigned int mid = min + ((max - min) / 2);
4771ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod    if (buffer->info[mid].cluster < cluster_start)
4781ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod      min = mid + 1;
4791ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod    else
4801ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod      max = mid;
4811ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  }
4821ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  unsigned int count = buffer->len;
4831ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  for (unsigned int i = min; i < count && buffer->info[i].cluster < cluster_end; i++)
48481c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod    buffer->info[i].mask = (buffer->info[i].mask & not_mask) | value;
4851ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod}
4861ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod
48711fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
4883567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod/* Public API again */
4893567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
490c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbodhb_bool_t
491c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbodhb_buffer_set_length (hb_buffer_t  *buffer,
492c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod		      unsigned int  length)
493c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod{
49402a534b23f2d1e7475109563b9f61221ed020e8bRyan Lortie  if (!_hb_buffer_ensure (buffer, length))
495c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod    return FALSE;
496c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod
497c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  /* Wipe the new space */
498c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  if (length > buffer->len) {
499c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod    memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
500c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod    if (buffer->have_positions)
501c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod      memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
502c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  }
503c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod
504c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  buffer->len = length;
505c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  return TRUE;
506c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod}
507c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod
50811fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodunsigned int
5093d14528b8b2e7da425a9df7057fc9fb326d8298cBehdad Esfahbodhb_buffer_get_length (hb_buffer_t *buffer)
51011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
5116960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  return buffer->len;
51211fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
51311fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
51411fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod/* Return value valid as long as buffer not modified */
51511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_glyph_info_t *
51670566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortiehb_buffer_get_glyph_infos (hb_buffer_t  *buffer,
51770566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie                           unsigned int *length)
51811fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
51970566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie  if (length)
52070566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie    *length = buffer->len;
52170566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie
5227e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod  return (hb_glyph_info_t *) buffer->info;
52311fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
52411fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
52511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod/* Return value valid as long as buffer not modified */
52611fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_glyph_position_t *
52770566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortiehb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
52870566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie                               unsigned int *length)
52911fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
530314905d7548d5be58354546d660754b807b6efb2Behdad Esfahbod  if (!buffer->have_positions)
5318f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod    _hb_buffer_clear_positions (buffer);
53211fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
53370566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie  if (length)
53470566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie    *length = buffer->len;
53570566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie
5361b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod  return (hb_glyph_position_t *) buffer->pos;
53711fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
538fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod
539fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod
540ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodstatic void
541ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodreverse_range (hb_buffer_t *buffer,
542ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod	       unsigned int start,
543ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod	       unsigned int end)
544fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod{
545fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod  unsigned int i, j;
546fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod
547ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod  for (i = start, j = end - 1; i < j; i++, j--) {
54888474c6fdaf35c56368694a5b164f4988a004d49Behdad Esfahbod    hb_glyph_info_t t;
549fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod
5507e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod    t = buffer->info[i];
5517e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod    buffer->info[i] = buffer->info[j];
5527e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod    buffer->info[j] = t;
553fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod  }
554fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod
5551b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod  if (buffer->pos) {
556ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod    for (i = 0, j = end - 1; i < j; i++, j--) {
55788474c6fdaf35c56368694a5b164f4988a004d49Behdad Esfahbod      hb_glyph_position_t t;
558fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod
5591b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod      t = buffer->pos[i];
5601b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod      buffer->pos[i] = buffer->pos[j];
5611b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod      buffer->pos[j] = t;
562fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod    }
563fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod  }
564fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod}
565299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
566ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodvoid
567ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodhb_buffer_reverse (hb_buffer_t *buffer)
568ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod{
5696960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  if (unlikely (!buffer->len))
570ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod    return;
571ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
5726960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  reverse_range (buffer, 0, buffer->len);
573ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod}
574ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
575ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodvoid
576ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodhb_buffer_reverse_clusters (hb_buffer_t *buffer)
577ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod{
578ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod  unsigned int i, start, count, last_cluster;
579ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
5806960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  if (unlikely (!buffer->len))
581ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod    return;
582ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
583ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod  hb_buffer_reverse (buffer);
584ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
5856960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  count = buffer->len;
586ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod  start = 0;
5877e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod  last_cluster = buffer->info[0].cluster;
588ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod  for (i = 1; i < count; i++) {
5897e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod    if (last_cluster != buffer->info[i].cluster) {
590ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod      reverse_range (buffer, start, i);
591ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod      start = i;
5927e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod      last_cluster = buffer->info[i].cluster;
593ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod    }
594ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod  }
595ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod  reverse_range (buffer, start, i);
596ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod}
597ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
598299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
599299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define ADD_UTF(T) \
600299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	HB_STMT_START { \
601299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  const T *next = (const T *) text + item_offset; \
602299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  const T *end = next + item_length; \
603299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  while (next < end) { \
604299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    hb_codepoint_t u; \
605299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    const T *old_next = next; \
606299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    next = UTF_NEXT (next, end, u); \
607f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbod	    hb_buffer_add (buffer, u, 1,  old_next - (const T *) text); \
608299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  } \
609299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	} HB_STMT_END
610299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
611299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
612299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF8_COMPUTE(Char, Mask, Len) \
613299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  if (Char < 128) { Len = 1; Mask = 0x7f; } \
614299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \
615299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \
616299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \
617299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else Len = 0;
618299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
619299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodstatic inline const uint8_t *
620299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_utf8_next (const uint8_t *text,
621299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	      const uint8_t *end,
622299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	      hb_codepoint_t *unicode)
623299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
624299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  uint8_t c = *text;
625299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  unsigned int mask, len;
626299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
627243673d601588a6f704ceafbff5dd5cdf66c47b7Behdad Esfahbod  /* TODO check for overlong sequences? */
6282163afbf35044f59dbf449254e65b8c9feb6cdebBehdad Esfahbod
629299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  UTF8_COMPUTE (c, mask, len);
63064d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod  if (unlikely (!len || (unsigned int) (end - text) < len)) {
631299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    *unicode = -1;
632299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    return text + 1;
633299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  } else {
634299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    hb_codepoint_t result;
635299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    unsigned int i;
636299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    result = c & mask;
637299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    for (i = 1; i < len; i++)
638299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      {
63964d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod	if (unlikely ((text[i] & 0xc0) != 0x80))
640299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  {
641299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    *unicode = -1;
642299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    return text + 1;
643299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  }
644299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	result <<= 6;
645299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	result |= (text[i] & 0x3f);
646299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      }
647299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    *unicode = result;
648299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    return text + len;
649299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  }
650299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
651299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
652299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodvoid
653299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_buffer_add_utf8 (hb_buffer_t  *buffer,
654299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		    const char   *text,
65533d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod		    unsigned int  text_length HB_UNUSED,
656299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		    unsigned int  item_offset,
657299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		    unsigned int  item_length)
658299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
659299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF_NEXT(S, E, U)	hb_utf8_next (S, E, &(U))
660299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  ADD_UTF (uint8_t);
661299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#undef UTF_NEXT
662299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
663299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
664299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodstatic inline const uint16_t *
665299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_utf16_next (const uint16_t *text,
666299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	       const uint16_t *end,
667299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	       hb_codepoint_t *unicode)
668299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
669299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  uint16_t c = *text++;
670299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
67164d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod  if (unlikely (c >= 0xd800 && c < 0xdc00)) {
672299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    /* high surrogate */
673299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    uint16_t l;
67469ea23cb5d47dd1cfd3129f68375021ef79bf63bBehdad Esfahbod    if (text < end && ((l = *text), likely (l >= 0xdc00 && l < 0xe000))) {
675299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      /* low surrogate */
676299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      *unicode = ((hb_codepoint_t) ((c) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000);
677299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod       text++;
678299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    } else
679299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      *unicode = -1;
680299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  } else
681299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    *unicode = c;
682299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
683299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  return text;
684299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
685299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
686299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodvoid
687299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_buffer_add_utf16 (hb_buffer_t    *buffer,
688299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     const uint16_t *text,
68933d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod		     unsigned int    text_length HB_UNUSED,
690299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_offset,
691299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_length)
692299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
693299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF_NEXT(S, E, U)	hb_utf16_next (S, E, &(U))
694299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  ADD_UTF (uint16_t);
695299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#undef UTF_NEXT
696299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
697299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
698299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodvoid
699299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_buffer_add_utf32 (hb_buffer_t    *buffer,
700299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     const uint32_t *text,
70133d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod		     unsigned int    text_length HB_UNUSED,
702299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_offset,
703299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_length)
704299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
705299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF_NEXT(S, E, U)	((U) = *(S), (S)+1)
706299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  ADD_UTF (uint32_t);
707299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#undef UTF_NEXT
708299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
709acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
710acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
711acdba3f90b232fc12fcb200dca2584481b339118Behdad EsfahbodHB_END_DECLS
712