hb-buffer.cc revision bd7378b2ef9793de4e7f57b920f29f48ac9d0c25
1a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod/*
2a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * Copyright (C) 1998-2004  David Turner and Werner Lemberg
322da7fd94d6318c52df69d70470a85464ffc533dBehdad Esfahbod * Copyright (C) 2004,2007,2009,2010  Red Hat, Inc.
49f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod *
5c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod * This is part of HarfBuzz, a text shaping library.
69f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod *
7a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * Permission is hereby granted, without written agreement and without
8a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
9a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * software and its documentation for any purpose, provided that the
10a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
11a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * all copies of this software.
12a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod *
13a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * DAMAGE.
18a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod *
19a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod *
25a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
269f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod */
279f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
2822da7fd94d6318c52df69d70470a85464ffc533dBehdad Esfahbod#include "hb-buffer-private.hh"
299f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
3088a5f5a49b6809d88560791f9cf6b8f78f22a4adBehdad Esfahbod#include <string.h>
3188a5f5a49b6809d88560791f9cf6b8f78f22a4adBehdad Esfahbod
32acdba3f90b232fc12fcb200dca2584481b339118Behdad EsfahbodHB_BEGIN_DECLS
33acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
34f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod
3511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodstatic hb_buffer_t _hb_buffer_nil = {
365ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  HB_REFERENCE_COUNT_INVALID, /* ref_count */
375ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
385ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  &_hb_unicode_funcs_nil  /* unicode */
3911fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod};
4011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
41a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod/* Here is how the buffer works internally:
42a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod *
43910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * There are two info pointers: info and out_info.  They always have
44910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * the same allocated size, but different lengths.
45a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod *
469d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod * As an optimization, both info and out_info may point to the
477e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod * same piece of memory, which is owned by info.  This remains the
4829427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod * case as long as out_len doesn't exceed len at any time.
49910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * In that case, swap() is no-op and the glyph operations operate
50910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * mostly in-place.
51a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod *
529d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod * As soon as out_info gets longer than info, out_info is moved over
53910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * to an alternate buffer (which we reuse the pos buffer for!), and its
54910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * current contents (out_len entries) are copied to the new place.
55910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * This should all remain transparent to the user.  swap() then
56910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * switches info and out_info.
57a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod */
58a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
59c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod
603567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbodstatic hb_bool_t
613567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod_hb_buffer_enlarge (hb_buffer_t *buffer, unsigned int size)
623567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod{
633567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (unlikely (buffer->in_error))
643567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    return FALSE;
653567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
663567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  unsigned int new_allocated = buffer->allocated;
673567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  hb_internal_glyph_position_t *new_pos;
683567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  hb_internal_glyph_info_t *new_info;
693567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  bool separate_out;
703567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
713567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  separate_out = buffer->out_info != buffer->info;
723567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
733567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  while (size > new_allocated)
743567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    new_allocated += (new_allocated >> 1) + 8;
753567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
763567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  new_pos = (hb_internal_glyph_position_t *) realloc (buffer->pos, new_allocated * sizeof (buffer->pos[0]));
773567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  new_info = (hb_internal_glyph_info_t *) realloc (buffer->info, new_allocated * sizeof (buffer->info[0]));
783567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
793567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (unlikely (!new_pos || !new_info))
803567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    buffer->in_error = TRUE;
813567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
823567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (likely (new_pos))
833567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    buffer->pos = new_pos;
843567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
853567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (likely (new_info))
863567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    buffer->info = new_info;
873567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
883567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  buffer->out_info = separate_out ? (hb_internal_glyph_info_t *) buffer->pos : buffer->info;
893567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (likely (!buffer->in_error))
903567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    buffer->allocated = new_allocated;
913567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
923567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  return likely (!buffer->in_error);
933567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod}
943567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
953567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbodstatic inline hb_bool_t
963567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod_hb_buffer_ensure (hb_buffer_t *buffer, unsigned int size)
973567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod{
983567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  return likely (size <= buffer->allocated) ? TRUE : _hb_buffer_enlarge (buffer, size);
993567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod}
1006b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
101acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbodstatic inline hb_bool_t
1023567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod_hb_buffer_ensure_separate (hb_buffer_t *buffer, unsigned int size)
103c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod{
1043567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (unlikely (!_hb_buffer_ensure (buffer, size))) return FALSE;
105a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod
1069d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod  if (buffer->out_info == buffer->info)
107e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  {
108e4679d9fae43f3219c476c5b9e411d1f5d0d5baeBehdad Esfahbod    assert (buffer->have_output);
109e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod
1101b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod    buffer->out_info = (hb_internal_glyph_info_t *) buffer->pos;
11129427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod    memcpy (buffer->out_info, buffer->info, buffer->out_len * sizeof (buffer->out_info[0]));
112e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
113a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod
114a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod  return TRUE;
115a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod}
116a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
1173567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
1186b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod/* Public API */
1196b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
120b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbodhb_buffer_t *
12111fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_create (unsigned int pre_alloc_size)
1229f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod{
123b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  hb_buffer_t *buffer;
124b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod
1255fc22e647c8a2bf6d3cb59185e351ac625e7e322Behdad Esfahbod  if (!HB_OBJECT_DO_CREATE (hb_buffer_t, buffer))
12611fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod    return &_hb_buffer_nil;
1279f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
12811fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod  if (pre_alloc_size)
1293567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    _hb_buffer_ensure (buffer, pre_alloc_size);
1309f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
1315ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  buffer->unicode = &_hb_unicode_funcs_nil;
1325ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
13311fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod  return buffer;
13411fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
1357a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
13611fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_t *
13711fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_reference (hb_buffer_t *buffer)
13811fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
13911fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod  HB_OBJECT_DO_REFERENCE (buffer);
14011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
141f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
14211fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodunsigned int
14311fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_get_reference_count (hb_buffer_t *buffer)
14411fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
14511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod  HB_OBJECT_DO_GET_REFERENCE_COUNT (buffer);
146a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod}
1479f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
1487a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbodvoid
14911fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_destroy (hb_buffer_t *buffer)
1507a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod{
15111fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod  HB_OBJECT_DO_DESTROY (buffer);
15211fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
1535ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  hb_unicode_funcs_destroy (buffer->unicode);
1545ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
1557e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod  free (buffer->info);
1561b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod  free (buffer->pos);
15711fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
158b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  free (buffer);
1597a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod}
1607a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
1615ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
1625ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodvoid
1635ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
1645ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod			     hb_unicode_funcs_t *unicode)
1655ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
1660465e69832393cc1ed36508ec5d597fbab64877aBehdad Esfahbod  if (!unicode)
1670465e69832393cc1ed36508ec5d597fbab64877aBehdad Esfahbod    unicode = &_hb_unicode_funcs_nil;
1680465e69832393cc1ed36508ec5d597fbab64877aBehdad Esfahbod
1695ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  hb_unicode_funcs_reference (unicode);
1705ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  hb_unicode_funcs_destroy (buffer->unicode);
1715ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  buffer->unicode = unicode;
1725ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
1735ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
1745ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_unicode_funcs_t *
1755ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_get_unicode_funcs (hb_buffer_t        *buffer)
1765ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
1775ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  return buffer->unicode;
1785ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
1795ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
1805ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodvoid
1815ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_set_direction (hb_buffer_t    *buffer,
1825ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod			 hb_direction_t  direction)
1835ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
1845ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
1854e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  buffer->props.direction = direction;
1865ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
1875ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
1885ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_direction_t
1895ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_get_direction (hb_buffer_t    *buffer)
1905ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
1914e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  return buffer->props.direction;
1925ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
1935ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
194ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodvoid
195ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_set_script (hb_buffer_t *buffer,
196ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod		      hb_script_t  script)
197ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
1984e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  buffer->props.script = script;
199ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
200ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
201ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_script_t
202ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_get_script (hb_buffer_t *buffer)
203ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
2044e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  return buffer->props.script;
205ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
206ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
207ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodvoid
208ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_set_language (hb_buffer_t   *buffer,
209ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod			hb_language_t  language)
210ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
2114e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  buffer->props.language = language;
212ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
213ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
214ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_language_t
215ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_get_language (hb_buffer_t *buffer)
216ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
2174e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  return buffer->props.language;
218ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
219ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
2205ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
2217a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbodvoid
222c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbodhb_buffer_clear (hb_buffer_t *buffer)
2237a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod{
224e4679d9fae43f3219c476c5b9e411d1f5d0d5baeBehdad Esfahbod  buffer->have_output = FALSE;
225314905d7548d5be58354546d660754b807b6efb2Behdad Esfahbod  buffer->have_positions = FALSE;
226a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod  buffer->in_error = FALSE;
2276960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  buffer->len = 0;
22829427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod  buffer->out_len = 0;
22936b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  buffer->i = 0;
2309d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod  buffer->out_info = buffer->info;
231c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  buffer->max_lig_id = 0;
2327a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod}
2337a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
234a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbodhb_bool_t
235f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbodhb_buffer_ensure (hb_buffer_t *buffer, unsigned int size)
236f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod{
2373567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  return _hb_buffer_ensure (buffer, size);
238f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod}
239f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
240f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbodvoid
2413015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbodhb_buffer_add_glyph (hb_buffer_t    *buffer,
242f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod		     hb_codepoint_t  codepoint,
243468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod		     hb_mask_t       mask,
2443015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod		     unsigned int    cluster)
2456b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod{
246f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  hb_internal_glyph_info_t *glyph;
2475c0adce1ccc739415c4b26ff13ffd2d77ea4bc6cBehdad Esfahbod
2483567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (unlikely (!_hb_buffer_ensure (buffer, buffer->len + 1))) return;
2496b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
2506960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  glyph = &buffer->info[buffer->len];
251f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  glyph->codepoint = codepoint;
252468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod  glyph->mask = mask;
2536b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod  glyph->cluster = cluster;
2546b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod  glyph->component = 0;
255f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  glyph->lig_id = 0;
256f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  glyph->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
2576b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
2586960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  buffer->len++;
2596b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod}
2606b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
26111fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodvoid
26211fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_clear_positions (hb_buffer_t *buffer)
26306003908ccf2473366816935dd1b144cde587be9Behdad Esfahbod{
26415c3e75b39797a153b6bc0598f87b27c4a487228Behdad Esfahbod  _hb_buffer_clear_output (buffer);
265e4679d9fae43f3219c476c5b9e411d1f5d0d5baeBehdad Esfahbod  buffer->have_output = FALSE;
266314905d7548d5be58354546d660754b807b6efb2Behdad Esfahbod  buffer->have_positions = TRUE;
26715c3e75b39797a153b6bc0598f87b27c4a487228Behdad Esfahbod
2681b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod  if (unlikely (!buffer->pos))
269c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  {
2701b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod    buffer->pos = (hb_internal_glyph_position_t *) calloc (buffer->allocated, sizeof (buffer->pos[0]));
271c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    return;
272c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  }
27306003908ccf2473366816935dd1b144cde587be9Behdad Esfahbod
2746960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  memset (buffer->pos, 0, sizeof (buffer->pos[0]) * buffer->len);
27506003908ccf2473366816935dd1b144cde587be9Behdad Esfahbod}
27606003908ccf2473366816935dd1b144cde587be9Behdad Esfahbod
2773567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod/* HarfBuzz-Internal API */
2783567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
2793567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbodvoid
2803567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod_hb_buffer_clear_output (hb_buffer_t *buffer)
2813567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod{
2823567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  buffer->have_output = TRUE;
2833567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  buffer->have_positions = FALSE;
2843567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  buffer->out_len = 0;
2853567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  buffer->out_info = buffer->info;
2863567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod}
2873567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
288081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodvoid
289c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod_hb_buffer_swap (hb_buffer_t *buffer)
2909f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod{
291c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  unsigned int tmp;
2929f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
293e4679d9fae43f3219c476c5b9e411d1f5d0d5baeBehdad Esfahbod  assert (buffer->have_output);
294e4679d9fae43f3219c476c5b9e411d1f5d0d5baeBehdad Esfahbod
295a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod  if (unlikely (buffer->in_error)) return;
296a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod
2979d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod  if (buffer->out_info != buffer->info)
298e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  {
299f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod    hb_internal_glyph_info_t *tmp_string;
3007e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod    tmp_string = buffer->info;
3019d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod    buffer->info = buffer->out_info;
3029d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod    buffer->out_info = tmp_string;
3031b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod    buffer->pos = (hb_internal_glyph_position_t *) buffer->out_info;
304e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
3059f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
3066960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  tmp = buffer->len;
30729427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod  buffer->len = buffer->out_len;
30829427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod  buffer->out_len = tmp;
3099f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
31036b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  buffer->i = 0;
3119f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod}
3129f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
3139f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod/* The following function copies `num_out' elements from `glyph_data'
3149d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod   to `buffer->out_info', advancing the in array pointer in the structure
3159f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   by `num_in' elements, and the out array pointer by `num_out' elements.
3169f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   Finally, it sets the `length' field of `out' equal to
3179f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   `pos' of the `out' structure.
3189f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
31936b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod   If `component' is 0xFFFF, the component value from buffer->i
3209f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   will copied `num_out' times, otherwise `component' itself will
3219f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   be used to fill the `component' fields.
3229f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
32336b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod   If `lig_id' is 0xFFFF, the lig_id value from buffer->i
324f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod   will copied `num_out' times, otherwise `lig_id' itself will
325f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod   be used to fill the `lig_id' fields.
3269f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
327468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod   The mask for all replacement glyphs are taken
32836b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod   from the glyph at position `buffer->i'.
3299f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
33036b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod   The cluster value for the glyph at position buffer->i is used
3319f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   for all replacement glyphs */
33225e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod
333081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodvoid
3343015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod_hb_buffer_add_output_glyphs (hb_buffer_t *buffer,
3353015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod			      unsigned int num_in,
3363015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod			      unsigned int num_out,
33725e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod			      const hb_codepoint_t *glyph_data,
3383015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod			      unsigned short component,
339f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod			      unsigned short lig_id)
3409f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod{
3413015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod  unsigned int i;
342468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod  unsigned int mask;
3433015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod  unsigned int cluster;
3449f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
3459d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod  if (buffer->out_info != buffer->info ||
34636b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod      buffer->out_len + num_out > buffer->i + num_in)
347e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  {
3483567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    if (unlikely (!_hb_buffer_ensure_separate (buffer, buffer->out_len + num_out)))
349a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod      return;
350e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
351a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
35236b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  mask = buffer->info[buffer->i].mask;
35336b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  cluster = buffer->info[buffer->i].cluster;
354c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  if (component == 0xFFFF)
35536b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod    component = buffer->info[buffer->i].component;
356f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  if (lig_id == 0xFFFF)
35736b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod    lig_id = buffer->info[buffer->i].lig_id;
3589f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
359c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  for (i = 0; i < num_out; i++)
3609f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod  {
36129427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod    hb_internal_glyph_info_t *info = &buffer->out_info[buffer->out_len + i];
36225e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod    info->codepoint = glyph_data[i];
363468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod    info->mask = mask;
364c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    info->cluster = cluster;
365c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    info->component = component;
366f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod    info->lig_id = lig_id;
367f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod    info->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
3689f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod  }
3699f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
37036b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  buffer->i  += num_in;
37129427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod  buffer->out_len += num_out;
3729f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod}
3739f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
37425e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbodvoid
37525e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod_hb_buffer_add_output_glyphs_be16 (hb_buffer_t *buffer,
37625e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod				   unsigned int num_in,
37725e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod				   unsigned int num_out,
37825e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod				   const uint16_t *glyph_data_be,
37925e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod				   unsigned short component,
38025e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod				   unsigned short lig_id)
38125e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod{
38225e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod  unsigned int i;
38325e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod  unsigned int mask;
38425e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod  unsigned int cluster;
38525e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod
3869d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod  if (buffer->out_info != buffer->info ||
38736b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod      buffer->out_len + num_out > buffer->i + num_in)
38825e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod  {
3893567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    if (unlikely (!_hb_buffer_ensure_separate (buffer, buffer->out_len + num_out)))
390a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod      return;
39125e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod  }
39225e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod
39336b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  mask = buffer->info[buffer->i].mask;
39436b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  cluster = buffer->info[buffer->i].cluster;
39525e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod  if (component == 0xFFFF)
39636b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod    component = buffer->info[buffer->i].component;
39725e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod  if (lig_id == 0xFFFF)
39836b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod    lig_id = buffer->info[buffer->i].lig_id;
39925e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod
40025e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod  for (i = 0; i < num_out; i++)
40125e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod  {
40229427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod    hb_internal_glyph_info_t *info = &buffer->out_info[buffer->out_len + i];
40325e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod    info->codepoint = hb_be_uint16 (glyph_data_be[i]);
40425e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod    info->mask = mask;
40525e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod    info->cluster = cluster;
40625e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod    info->component = component;
40725e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod    info->lig_id = lig_id;
40825e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod    info->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
40925e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod  }
41025e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod
41136b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  buffer->i  += num_in;
41229427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod  buffer->out_len += num_out;
41325e7ef704633447f109b148620336c42d6fb310eBehdad Esfahbod}
41488a5f5a49b6809d88560791f9cf6b8f78f22a4adBehdad Esfahbod
415081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodvoid
4163015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod_hb_buffer_add_output_glyph (hb_buffer_t *buffer,
4173015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod			     hb_codepoint_t glyph_index,
4183015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod			     unsigned short component,
419f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod			     unsigned short lig_id)
4209f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod{
421f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  hb_internal_glyph_info_t *info;
422c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod
4239d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod  if (buffer->out_info != buffer->info)
424e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  {
4253567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    if (unlikely (!_hb_buffer_ensure (buffer, buffer->out_len + 1))) return;
42636b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod    buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
427e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
42836b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  else if (buffer->out_len != buffer->i)
42936b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod    buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
4309f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
43129427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod  info = &buffer->out_info[buffer->out_len];
432f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  info->codepoint = glyph_index;
433c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  if (component != 0xFFFF)
434c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    info->component = component;
435f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  if (lig_id != 0xFFFF)
436f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod    info->lig_id = lig_id;
437f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  info->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
438c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod
43936b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  buffer->i++;
44029427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod  buffer->out_len++;
4419f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod}
4429f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
443081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodvoid
444c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod_hb_buffer_next_glyph (hb_buffer_t *buffer)
44515c3e75b39797a153b6bc0598f87b27c4a487228Behdad Esfahbod{
446314905d7548d5be58354546d660754b807b6efb2Behdad Esfahbod  if (buffer->have_output)
447e4679d9fae43f3219c476c5b9e411d1f5d0d5baeBehdad Esfahbod  {
4489d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod    if (buffer->out_info != buffer->info)
449314905d7548d5be58354546d660754b807b6efb2Behdad Esfahbod    {
4503567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod      if (unlikely (!_hb_buffer_ensure (buffer, buffer->out_len + 1))) return;
45136b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod      buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
452314905d7548d5be58354546d660754b807b6efb2Behdad Esfahbod    }
45336b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod    else if (buffer->out_len != buffer->i)
45436b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod      buffer->out_info[buffer->out_len] = buffer->info[buffer->i];
455e4679d9fae43f3219c476c5b9e411d1f5d0d5baeBehdad Esfahbod
45629427c5c51ac70aca53ed523fa5ddb3de4355fb0Behdad Esfahbod    buffer->out_len++;
457e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
458a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
45936b73c80df91e96492357c6da945e081e9046a93Behdad Esfahbod  buffer->i++;
460a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod}
461a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
4621ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbodvoid
46357ac0ecb7843533b2e6e6d6c8a12b2a44437cc1cBehdad Esfahbod_hb_buffer_reset_masks (hb_buffer_t *buffer,
46457ac0ecb7843533b2e6e6d6c8a12b2a44437cc1cBehdad Esfahbod			hb_mask_t    mask)
4651ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod{
4661ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  unsigned int count = buffer->len;
4671ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
468961f9baa7bc3556f1e4e7135859cebe1351f73a4Behdad Esfahbod    buffer->info[i].mask = mask;
4691ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod}
4701ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod
4711ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbodvoid
47257ac0ecb7843533b2e6e6d6c8a12b2a44437cc1cBehdad Esfahbod_hb_buffer_add_masks (hb_buffer_t *buffer,
473bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod		      hb_mask_t    mask)
474bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod{
475bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod  unsigned int count = buffer->len;
476bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
477bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod    buffer->info[i].mask |= mask;
478bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod}
479bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod
480bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbodvoid
481bd7378b2ef9793de4e7f57b920f29f48ac9d0c25Behdad Esfahbod_hb_buffer_set_masks (hb_buffer_t *buffer,
48281c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod		      hb_mask_t    value,
48381c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod		      hb_mask_t    mask,
48481c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod		      unsigned int cluster_start,
48581c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod		      unsigned int cluster_end)
4861ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod{
48781c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod  hb_mask_t not_mask = ~mask;
4885c1c8c9c50ddbe66ea595afb245a208b7775b27cBehdad Esfahbod  value &= mask;
48981c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod
4903506b2e78db27e7835bd2c09c053a9807c9cac40Behdad Esfahbod  if (!mask)
4913506b2e78db27e7835bd2c09c053a9807c9cac40Behdad Esfahbod    return;
4923506b2e78db27e7835bd2c09c053a9807c9cac40Behdad Esfahbod
4931ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
4941ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod    unsigned int count = buffer->len;
4951ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
49681c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod      buffer->info[i].mask = (buffer->info[i].mask & not_mask) | value;
4971ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod    return;
4981ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  }
4991ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod
50034db6f031d7ac009f554386ef990bad44886b9eeBehdad Esfahbod  /* XXX can't bsearch since .cluster may not be sorted. */
5011ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  /* Binary search to find the start position and go from there. */
5021ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  unsigned int min = 0, max = buffer->len;
5031ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  while (min < max)
5041ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  {
5051ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod    unsigned int mid = min + ((max - min) / 2);
5061ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod    if (buffer->info[mid].cluster < cluster_start)
5071ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod      min = mid + 1;
5081ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod    else
5091ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod      max = mid;
5101ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  }
5111ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  unsigned int count = buffer->len;
5121ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod  for (unsigned int i = min; i < count && buffer->info[i].cluster < cluster_end; i++)
51381c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6Behdad Esfahbod    buffer->info[i].mask = (buffer->info[i].mask & not_mask) | value;
5141ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod}
5151ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64Behdad Esfahbod
51611fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
5173567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod/* Public API again */
5183567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
51911fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodunsigned int
5203d14528b8b2e7da425a9df7057fc9fb326d8298cBehdad Esfahbodhb_buffer_get_length (hb_buffer_t *buffer)
52111fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
5226960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  return buffer->len;
52311fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
52411fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
52511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod/* Return value valid as long as buffer not modified */
52611fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_glyph_info_t *
52711fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_get_glyph_infos (hb_buffer_t *buffer)
52811fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
5297e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod  return (hb_glyph_info_t *) buffer->info;
53011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
53111fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
53211fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod/* Return value valid as long as buffer not modified */
53311fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_glyph_position_t *
53411fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_get_glyph_positions (hb_buffer_t *buffer)
53511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
536314905d7548d5be58354546d660754b807b6efb2Behdad Esfahbod  if (!buffer->have_positions)
53711fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod    hb_buffer_clear_positions (buffer);
53811fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
5391b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod  return (hb_glyph_position_t *) buffer->pos;
54011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
541fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod
542fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod
543ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodstatic void
544ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodreverse_range (hb_buffer_t *buffer,
545ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod	       unsigned int start,
546ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod	       unsigned int end)
547fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod{
548fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod  unsigned int i, j;
549fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod
550ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod  for (i = start, j = end - 1; i < j; i++, j--) {
551fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod    hb_internal_glyph_info_t t;
552fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod
5537e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod    t = buffer->info[i];
5547e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod    buffer->info[i] = buffer->info[j];
5557e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod    buffer->info[j] = t;
556fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod  }
557fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod
5581b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod  if (buffer->pos) {
559ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod    for (i = 0, j = end - 1; i < j; i++, j--) {
560fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod      hb_internal_glyph_position_t t;
561fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod
5621b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod      t = buffer->pos[i];
5631b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod      buffer->pos[i] = buffer->pos[j];
5641b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod      buffer->pos[j] = t;
565fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod    }
566fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod  }
567fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod}
568299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
569ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodvoid
570ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodhb_buffer_reverse (hb_buffer_t *buffer)
571ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod{
5726960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  if (unlikely (!buffer->len))
573ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod    return;
574ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
5756960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  reverse_range (buffer, 0, buffer->len);
576ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod}
577ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
578ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodvoid
579ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodhb_buffer_reverse_clusters (hb_buffer_t *buffer)
580ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod{
581ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod  unsigned int i, start, count, last_cluster;
582ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
5836960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  if (unlikely (!buffer->len))
584ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod    return;
585ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
586ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod  hb_buffer_reverse (buffer);
587ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
5886960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  count = buffer->len;
589ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod  start = 0;
5907e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod  last_cluster = buffer->info[0].cluster;
591ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod  for (i = 1; i < count; i++) {
5927e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod    if (last_cluster != buffer->info[i].cluster) {
593ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod      reverse_range (buffer, start, i);
594ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod      start = i;
5957e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod      last_cluster = buffer->info[i].cluster;
596ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod    }
597ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod  }
598ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod  reverse_range (buffer, start, i);
599ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod}
600ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
601299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
602299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define ADD_UTF(T) \
603299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	HB_STMT_START { \
604299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  const T *next = (const T *) text + item_offset; \
605299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  const T *end = next + item_length; \
606299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  while (next < end) { \
607299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    hb_codepoint_t u; \
608299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    const T *old_next = next; \
609299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    next = UTF_NEXT (next, end, u); \
610009aad567863c05ee2ec4a3ee76fe0ee79c767bbBehdad Esfahbod	    hb_buffer_add_glyph (buffer, u, 1,  old_next - (const T *) text); \
611299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  } \
612299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	} HB_STMT_END
613299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
614299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
615299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF8_COMPUTE(Char, Mask, Len) \
616299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  if (Char < 128) { Len = 1; Mask = 0x7f; } \
617299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \
618299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \
619299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \
620299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else Len = 0;
621299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
622299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodstatic inline const uint8_t *
623299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_utf8_next (const uint8_t *text,
624299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	      const uint8_t *end,
625299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	      hb_codepoint_t *unicode)
626299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
627299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  uint8_t c = *text;
628299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  unsigned int mask, len;
629299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
6302163afbf35044f59dbf449254e65b8c9feb6cdebBehdad Esfahbod  /* TODO check for overlong sequences?  also: optimize? */
6312163afbf35044f59dbf449254e65b8c9feb6cdebBehdad Esfahbod
632299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  UTF8_COMPUTE (c, mask, len);
63364d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod  if (unlikely (!len || (unsigned int) (end - text) < len)) {
634299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    *unicode = -1;
635299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    return text + 1;
636299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  } else {
637299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    hb_codepoint_t result;
638299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    unsigned int i;
639299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    result = c & mask;
640299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    for (i = 1; i < len; i++)
641299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      {
64264d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod	if (unlikely ((text[i] & 0xc0) != 0x80))
643299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  {
644299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    *unicode = -1;
645299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    return text + 1;
646299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  }
647299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	result <<= 6;
648299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	result |= (text[i] & 0x3f);
649299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      }
650299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    *unicode = result;
651299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    return text + len;
652299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  }
653299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
654299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
655299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodvoid
656299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_buffer_add_utf8 (hb_buffer_t  *buffer,
657299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		    const char   *text,
65833d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod		    unsigned int  text_length HB_UNUSED,
659299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		    unsigned int  item_offset,
660299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		    unsigned int  item_length)
661299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
662299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF_NEXT(S, E, U)	hb_utf8_next (S, E, &(U))
663299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  ADD_UTF (uint8_t);
664299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#undef UTF_NEXT
665299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
666299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
667299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodstatic inline const uint16_t *
668299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_utf16_next (const uint16_t *text,
669299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	       const uint16_t *end,
670299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	       hb_codepoint_t *unicode)
671299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
672299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  uint16_t c = *text++;
673299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
67464d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod  if (unlikely (c >= 0xd800 && c < 0xdc00)) {
675299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    /* high surrogate */
676299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    uint16_t l;
67764d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (text < end && ((l = *text), unlikely (l >= 0xdc00 && l < 0xe000))) {
678299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      /* low surrogate */
679299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      *unicode = ((hb_codepoint_t) ((c) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000);
680299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod       text++;
681299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    } else
682299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      *unicode = -1;
683299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  } else
684299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    *unicode = c;
685299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
686299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  return text;
687299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
688299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
689299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodvoid
690299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_buffer_add_utf16 (hb_buffer_t    *buffer,
691299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     const uint16_t *text,
69233d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod		     unsigned int    text_length HB_UNUSED,
693299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_offset,
694299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_length)
695299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
696299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF_NEXT(S, E, U)	hb_utf16_next (S, E, &(U))
697299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  ADD_UTF (uint16_t);
698299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#undef UTF_NEXT
699299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
700299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
701299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodvoid
702299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_buffer_add_utf32 (hb_buffer_t    *buffer,
703299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     const uint32_t *text,
70433d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod		     unsigned int    text_length HB_UNUSED,
705299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_offset,
706299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_length)
707299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
708299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF_NEXT(S, E, U)	((U) = *(S), (S)+1)
709299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  ADD_UTF (uint32_t);
710299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#undef UTF_NEXT
711299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
712acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
713acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
714acdba3f90b232fc12fcb200dca2584481b339118Behdad EsfahbodHB_END_DECLS
715