hb-buffer.cc revision f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cab
1a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod/*
2a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * Copyright (C) 1998-2004  David Turner and Werner Lemberg
3a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * Copyright (C) 2004,2007  Red Hat, Inc.
49f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod *
5a2a9a023f6472ba262f89e5327318996b8258d25Behdad Esfahbod * This is part of HarfBuzz, an OpenType Layout engine 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
285c0adce1ccc739415c4b26ff13ffd2d77ea4bc6cBehdad Esfahbod#include "hb-buffer-private.h"
299f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
3088a5f5a49b6809d88560791f9cf6b8f78f22a4adBehdad Esfahbod#include <string.h>
3188a5f5a49b6809d88560791f9cf6b8f78f22a4adBehdad Esfahbod
32a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod/* Here is how the buffer works internally:
33a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod *
34a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod * There are two string pointers: in_string and out_string.  They
35a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod * always have same allocated size, but different length and positions.
36a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod *
37a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod * As an optimization, both in_string and out_string may point to the
38a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod * same piece of memory, which is owned by in_string.  This remains the
39e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod * case as long as out_length doesn't exceed in_length at any time.
40e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod * In that case, swap() is no-op and the glyph operations operate mostly
41e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod * in-place.
42a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod *
43e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod * As soon as out_string gets longer than in_string, out_string is moved over
44e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod * to an alternate buffer (alt_string), and its current contents (out_length
45e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod * entries) are copied to the alt buffer.  This should all remain transparent
46e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod * to the user.  swap() then switches in_string and alt_string.  alt_string is
47e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod * not allocated until its needed, but after that it's grown with in_string
48e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod * unconditionally.
49a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod */
50a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
51c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod/* XXX err handling */
52c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod
536b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod/* Internal API */
546b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
5588a5f5a49b6809d88560791f9cf6b8f78f22a4adBehdad Esfahbodstatic void
56c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbodhb_buffer_ensure_separate (hb_buffer_t *buffer, unsigned int size)
57c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod{
58c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  hb_buffer_ensure (buffer, size);
59e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  if (buffer->out_string == buffer->in_string)
60e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  {
61e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    if (!buffer->alt_string)
62e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod      buffer->alt_string = malloc (buffer->allocated * sizeof (buffer->alt_string[0]));
63e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod
64e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    buffer->out_string = buffer->alt_string;
65e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    memcpy (buffer->out_string, buffer->in_string, buffer->out_length * sizeof (buffer->out_string[0]));
66e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
67a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod}
68a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
696b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod/* Public API */
706b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
71b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbodhb_buffer_t *
72f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbodhb_buffer_new (unsigned int allocation_size)
739f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod{
74b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  hb_buffer_t *buffer;
75b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod
76b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  buffer = malloc (sizeof (hb_buffer_t));
77b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  if (HB_UNLIKELY (!buffer))
78b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod    return NULL;
799f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
807a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod  buffer->allocated = 0;
817a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod  buffer->in_string = NULL;
827a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod  buffer->alt_string = NULL;
837a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod  buffer->positions = NULL;
849f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
85b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  hb_buffer_clear (buffer);
867a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
87f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod  if (allocation_size)
88f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod    hb_buffer_ensure(buffer, allocation_size);
89f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
90b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  return buffer;
91a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod}
929f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
937a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbodvoid
94c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbodhb_buffer_free (hb_buffer_t *buffer)
957a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod{
96b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  free (buffer->in_string);
97b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  free (buffer->alt_string);
98b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  free (buffer->positions);
99b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  free (buffer);
1007a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod}
1017a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
1027a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbodvoid
103c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbodhb_buffer_clear (hb_buffer_t *buffer)
1047a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod{
1057a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod  buffer->in_length = 0;
1067a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod  buffer->out_length = 0;
1077a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod  buffer->in_pos = 0;
1087a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod  buffer->out_pos = 0;
1097a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod  buffer->out_string = buffer->in_string;
110c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  buffer->max_lig_id = 0;
1117a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod}
1127a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
113b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbodvoid
114f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbodhb_buffer_ensure (hb_buffer_t *buffer, unsigned int size)
115f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod{
116f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod  unsigned int new_allocated = buffer->allocated;
117f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
118f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod  if (size > new_allocated)
119f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod  {
120f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod    while (size > new_allocated)
121f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod      new_allocated += (new_allocated >> 1) + 8;
122f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
123f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod    if (buffer->positions)
124f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod      buffer->positions = realloc (buffer->positions, new_allocated * sizeof (buffer->positions[0]));
125f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
126f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod    if (buffer->out_string != buffer->in_string)
127f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod    {
128f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod      buffer->in_string = realloc (buffer->in_string, new_allocated * sizeof (buffer->in_string[0]));
129f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod      buffer->alt_string = realloc (buffer->alt_string, new_allocated * sizeof (buffer->alt_string[0]));
130f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod      buffer->out_string = buffer->alt_string;
131f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod    }
132f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod    else
133f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod    {
134f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod      buffer->in_string = realloc (buffer->in_string, new_allocated * sizeof (buffer->in_string[0]));
135f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod      buffer->out_string = buffer->in_string;
136f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
137f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod      if (buffer->alt_string)
138f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod      {
139f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod	free (buffer->alt_string);
140f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod	buffer->alt_string = NULL;
141f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod      }
142f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod    }
143f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
144f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod    buffer->allocated = new_allocated;
145f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod  }
146f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod}
147f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
148f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbodvoid
1493015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbodhb_buffer_add_glyph (hb_buffer_t    *buffer,
1503015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod		     hb_codepoint_t  glyph_index,
1513015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod		     unsigned int    properties,
1523015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod		     unsigned int    cluster)
1536b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod{
154c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  hb_glyph_info_t *glyph;
1555c0adce1ccc739415c4b26ff13ffd2d77ea4bc6cBehdad Esfahbod
156b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  hb_buffer_ensure (buffer, buffer->in_length + 1);
1576b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
1586b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod  glyph = &buffer->in_string[buffer->in_length];
1596b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod  glyph->gindex = glyph_index;
1606b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod  glyph->properties = properties;
1616b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod  glyph->cluster = cluster;
1626b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod  glyph->component = 0;
1636b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod  glyph->ligID = 0;
164c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  glyph->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
1656b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
166b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  buffer->in_length++;
1676b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod}
1686b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
1696b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod/* HarfBuzz-Internal API */
1706b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
1716b347138b597c41af24453f630336ba2fc033dc5Behdad EsfahbodHB_INTERNAL void
172c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod_hb_buffer_clear_output (hb_buffer_t *buffer)
1737a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod{
1747a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod  buffer->out_length = 0;
1757a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod  buffer->out_pos = 0;
1767a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod  buffer->out_string = buffer->in_string;
1777a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod}
1787a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
179c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad EsfahbodHB_INTERNAL void
180c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod_hb_buffer_clear_positions (hb_buffer_t *buffer)
18106003908ccf2473366816935dd1b144cde587be9Behdad Esfahbod{
18215c3e75b39797a153b6bc0598f87b27c4a487228Behdad Esfahbod  _hb_buffer_clear_output (buffer);
18315c3e75b39797a153b6bc0598f87b27c4a487228Behdad Esfahbod
184c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  if (HB_UNLIKELY (!buffer->positions))
185c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  {
186c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    buffer->positions = calloc (buffer->allocated, sizeof (buffer->positions[0]));
187c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    return;
188c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  }
18906003908ccf2473366816935dd1b144cde587be9Behdad Esfahbod
19006003908ccf2473366816935dd1b144cde587be9Behdad Esfahbod  memset (buffer->positions, 0, sizeof (buffer->positions[0]) * buffer->in_length);
19106003908ccf2473366816935dd1b144cde587be9Behdad Esfahbod}
19206003908ccf2473366816935dd1b144cde587be9Behdad Esfahbod
1936b347138b597c41af24453f630336ba2fc033dc5Behdad EsfahbodHB_INTERNAL void
194c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod_hb_buffer_swap (hb_buffer_t *buffer)
1959f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod{
196c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  unsigned int tmp;
1979f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
198e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  if (buffer->out_string != buffer->in_string)
199e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  {
200e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    hb_glyph_info_t *tmp_string;
201e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    tmp_string = buffer->in_string;
202e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    buffer->in_string = buffer->out_string;
203e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    buffer->out_string = tmp_string;
204e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    buffer->alt_string = buffer->out_string;
205e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
2069f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
207c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  tmp = buffer->in_length;
2089f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod  buffer->in_length = buffer->out_length;
209c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  buffer->out_length = tmp;
2109f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
211c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  tmp = buffer->in_pos;
212a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod  buffer->in_pos = buffer->out_pos;
213c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  buffer->out_pos = tmp;
2149f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod}
2159f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
2169f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod/* The following function copies `num_out' elements from `glyph_data'
2179f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   to `buffer->out_string', advancing the in array pointer in the structure
2189f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   by `num_in' elements, and the out array pointer by `num_out' elements.
2199f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   Finally, it sets the `length' field of `out' equal to
2209f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   `pos' of the `out' structure.
2219f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
2229f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   If `component' is 0xFFFF, the component value from buffer->in_pos
2239f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   will copied `num_out' times, otherwise `component' itself will
2249f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   be used to fill the `component' fields.
2259f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
2269f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   If `ligID' is 0xFFFF, the ligID value from buffer->in_pos
2279f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   will copied `num_out' times, otherwise `ligID' itself will
2289f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   be used to fill the `ligID' fields.
2299f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
2309f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   The properties for all replacement glyphs are taken
2319f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   from the glyph at position `buffer->in_pos'.
2329f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
2339f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   The cluster value for the glyph at position buffer->in_pos is used
2349f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod   for all replacement glyphs */
235c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad EsfahbodHB_INTERNAL void
2363015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod_hb_buffer_add_output_glyphs (hb_buffer_t *buffer,
2373015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod			      unsigned int num_in,
2383015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod			      unsigned int num_out,
23988a5f5a49b6809d88560791f9cf6b8f78f22a4adBehdad Esfahbod			      const uint16_t *glyph_data_be,
2403015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod			      unsigned short component,
2413015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod			      unsigned short ligID)
2429f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod{
2433015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod  unsigned int i;
2443015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod  unsigned int properties;
2453015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod  unsigned int cluster;
2469f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
247e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  if (buffer->out_string == buffer->in_string &&
248e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod      buffer->out_pos + num_out > buffer->in_pos + num_in)
249e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  {
250e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    hb_buffer_ensure_separate (buffer, buffer->out_pos + num_out);
251e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
252a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
2539f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod  properties = buffer->in_string[buffer->in_pos].properties;
2549f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod  cluster = buffer->in_string[buffer->in_pos].cluster;
255c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  if (component == 0xFFFF)
2569f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod    component = buffer->in_string[buffer->in_pos].component;
257c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  if (ligID == 0xFFFF)
2589f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod    ligID = buffer->in_string[buffer->in_pos].ligID;
2599f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
260c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  for (i = 0; i < num_out; i++)
2619f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod  {
262c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    hb_glyph_info_t *info = &buffer->out_string[buffer->out_pos + i];
263c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    info->gindex = hb_be_uint16_t (glyph_data_be[i]);
264c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    info->properties = properties;
265c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    info->cluster = cluster;
266c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    info->component = component;
267c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    info->ligID = ligID;
268c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    info->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
2699f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod  }
2709f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
2719f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod  buffer->in_pos  += num_in;
2729f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod  buffer->out_pos += num_out;
2739f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod  buffer->out_length = buffer->out_pos;
2749f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod}
2759f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
27688a5f5a49b6809d88560791f9cf6b8f78f22a4adBehdad Esfahbod
277c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad EsfahbodHB_INTERNAL void
2783015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod_hb_buffer_add_output_glyph (hb_buffer_t *buffer,
2793015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod			     hb_codepoint_t glyph_index,
2803015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod			     unsigned short component,
2813015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod			     unsigned short ligID)
2829f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod{
283c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  hb_glyph_info_t *info;
284c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod
285e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  if (buffer->out_string != buffer->in_string)
286e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  {
287e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    hb_buffer_ensure (buffer, buffer->out_pos + 1);
288e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
289e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
290e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  else if (buffer->out_pos != buffer->in_pos)
291e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
2929f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
293c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  info = &buffer->out_string[buffer->out_pos];
294c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  info->gindex = glyph_index;
295c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  if (component != 0xFFFF)
296c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    info->component = component;
297c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  if (ligID != 0xFFFF)
298c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod    info->ligID = ligID;
299c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  info->gproperty = HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN;
300c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod
301c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  buffer->in_pos++;
302c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  buffer->out_pos++;
303c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  buffer->out_length = buffer->out_pos;
3049f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod}
3059f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
306c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad EsfahbodHB_INTERNAL void
307c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod_hb_buffer_next_glyph (hb_buffer_t *buffer)
30815c3e75b39797a153b6bc0598f87b27c4a487228Behdad Esfahbod{
309e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  if (buffer->out_string != buffer->in_string)
310e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  {
311e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    hb_buffer_ensure (buffer, buffer->out_pos + 1);
312e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
313e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
314e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  else if (buffer->out_pos != buffer->in_pos)
315e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod    buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
316a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
317a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod  buffer->in_pos++;
318a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod  buffer->out_pos++;
3199f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod  buffer->out_length = buffer->out_pos;
320a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod}
321a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
322c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad EsfahbodHB_INTERNAL void
3233015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod_hb_buffer_replace_glyph (hb_buffer_t *buffer,
3243015c4175179a1816aad2a4950da9a3b8baf2578Behdad Esfahbod			  hb_codepoint_t glyph_index)
325a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod{
326e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  _hb_buffer_add_output_glyph (buffer, glyph_index, 0xFFFF, 0xFFFF);
3279f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod}
3289f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
3293015c4175179a1816aad2a4950da9a3b8baf2578Behdad EsfahbodHB_INTERNAL unsigned short
330c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod_hb_buffer_allocate_lig_id (hb_buffer_t *buffer)
3319f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod{
332c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod  return ++buffer->max_lig_id;
3339f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod}
334