hb-buffer.cc revision 3a81b1db89beba91fb91791918b9fdd9f8fc9fa0
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
373a81b1db89beba91fb91791918b9fdd9f8fc9fa0Behdad 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.
60468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod * In that case, swap_buffers() 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.
66468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod * This should all remain transparent to the user.  swap_buffers() then
67910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * switches info and out_info.
68a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod */
69a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
70c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod
71468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
72468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod/* Internal API */
73468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
74468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodbool
75468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::enlarge (unsigned int size)
763567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod{
77468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (in_error))
783567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    return FALSE;
793567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
80468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  unsigned int new_allocated = allocated;
81e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  hb_glyph_position_t *new_pos = NULL;
82e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  hb_glyph_info_t *new_info = NULL;
83468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  bool separate_out = out_info != info;
843567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
85468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
86e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    goto done;
873567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
883567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  while (size > new_allocated)
8965e0063eae2f3adb25315b8bd7b0e7757aa960f3Behdad Esfahbod    new_allocated += (new_allocated >> 1) + 32;
903567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
91468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0]));
92468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0]))))
93e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    goto done;
94e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
95468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0]));
96468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0]));
973567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
98e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahboddone:
993567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (unlikely (!new_pos || !new_info))
100468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    in_error = TRUE;
1013567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
1023567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (likely (new_pos))
103468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    pos = new_pos;
1043567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
1053567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (likely (new_info))
106468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    info = new_info;
107468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
108468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info = separate_out ? (hb_glyph_info_t *) pos : info;
109468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (likely (!in_error))
110468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    allocated = new_allocated;
111468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
112468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  return likely (!in_error);
113468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
114468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
115468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodbool
116468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::make_room_for (unsigned int num_in,
117468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod			    unsigned int num_out)
118468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
119468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (!ensure (out_len + num_out))) return FALSE;
120468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
121468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (out_info == info &&
122468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      out_len + num_out > idx + num_in)
123468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  {
124468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    assert (have_output);
125468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
126468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    out_info = (hb_glyph_info_t *) pos;
127468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    memcpy (out_info, info, out_len * sizeof (out_info[0]));
128468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
129468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
130468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  return TRUE;
131468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
132468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
133468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
134468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod/* HarfBuzz-Internal API */
135468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
136468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
137468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::reset (void)
138468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
139468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (hb_object_is_inert (this)))
140468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
141468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
142468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  hb_unicode_funcs_destroy (unicode);
1433a81b1db89beba91fb91791918b9fdd9f8fc9fa0Behdad Esfahbod  unicode = _hb_buffer_nil.unicode;
144468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
1453a81b1db89beba91fb91791918b9fdd9f8fc9fa0Behdad Esfahbod  props = _hb_buffer_nil.props;
146468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
147468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  in_error = FALSE;
148468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  have_output = FALSE;
149468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  have_positions = FALSE;
1503567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
151468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  idx = 0;
152468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  len = 0;
153468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_len = 0;
1543567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
155468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  serial = 0;
156f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  memset (allocated_var_bytes, 0, sizeof allocated_var_bytes);
157f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  memset (allocated_var_owner, 0, sizeof allocated_var_owner);
158468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
159468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info = info;
1603567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod}
1613567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
162468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
163468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::add (hb_codepoint_t  codepoint,
164468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod		  hb_mask_t       mask,
165468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod		  unsigned int    cluster)
1663567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod{
167468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  hb_glyph_info_t *glyph;
168468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
169468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (!ensure (len + 1))) return;
170468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
171468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  glyph = &info[len];
172468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
173468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  memset (glyph, 0, sizeof (*glyph));
174468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  glyph->codepoint = codepoint;
175468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  glyph->mask = mask;
176468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  glyph->cluster = cluster;
177468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
178468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  len++;
1793567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod}
1806b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
181468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
182468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::clear_output (void)
183c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod{
184468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (hb_object_is_inert (this)))
185468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
186468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
187468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  have_output = TRUE;
188468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  have_positions = FALSE;
189a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod
190468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_len = 0;
191468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info = info;
192468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
193468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
194468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
195468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::clear_positions (void)
196468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
197468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (hb_object_is_inert (this)))
198468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
199468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
200468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  have_output = FALSE;
201468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  have_positions = TRUE;
202468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
203468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  memset (pos, 0, sizeof (pos[0]) * len);
204468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
205468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
206468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
207468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::swap_buffers (void)
208468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
209468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (in_error)) return;
210468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
211468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  assert (have_output);
212468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
213468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (out_info != info)
214e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  {
215468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    hb_glyph_info_t *tmp_string;
216468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    tmp_string = info;
217468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    info = out_info;
218468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    out_info = tmp_string;
219468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    pos = (hb_glyph_position_t *) out_info;
220468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
221468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
222468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  unsigned int tmp;
223468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  tmp = len;
224468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  len = out_len;
225468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_len = tmp;
226468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
227468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  idx = 0;
228468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
229e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod
230468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
231468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::replace_glyphs_be16 (unsigned int num_in,
232468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod				  unsigned int num_out,
233468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod				  const uint16_t *glyph_data_be)
234468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
235468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (!make_room_for (num_in, num_out)) return;
236468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
237468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  hb_glyph_info_t orig_info = info[idx];
238468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  for (unsigned int i = 1; i < num_in; i++)
239468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  {
240468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    hb_glyph_info_t *inf = &info[idx + i];
241468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    orig_info.cluster = MIN (orig_info.cluster, inf->cluster);
242e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
243a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod
244468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  hb_glyph_info_t *pinfo = &out_info[out_len];
245468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  for (unsigned int i = 0; i < num_out; i++)
246468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  {
247468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    *pinfo = orig_info;
248468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    pinfo->codepoint = hb_be_uint16 (glyph_data_be[i]);
249468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    pinfo++;
250468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
251468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
252468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  idx  += num_in;
253468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_len += num_out;
254468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
255468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
256468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
257468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
258468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
259468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (!make_room_for (0, 1)) return;
260468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
261468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info[out_len] = info[idx];
262468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info[out_len].codepoint = glyph_index;
263468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
264468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_len++;
265468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
266468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
267468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
268468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::copy_glyph (void)
269468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
270468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (!make_room_for (0, 1)) return;
271468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
272468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info[out_len] = info[idx];
273468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
274468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_len++;
275468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
276468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
277468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
278468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
279468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
280468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info[out_len] = info[idx];
281468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info[out_len].codepoint = glyph_index;
282468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
283468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  idx++;
284468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_len++;
285468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
286468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
287468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
288468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::next_glyph (void)
289468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
290468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (have_output)
291468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  {
292468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    if (out_info != info)
293468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    {
294468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      if (unlikely (!ensure (out_len + 1))) return;
295468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      out_info[out_len] = info[idx];
296468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    }
297468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    else if (out_len != idx)
298468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      out_info[out_len] = info[idx];
299468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
300468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    out_len++;
301468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
302468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
303468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  idx++;
304468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
305468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
306468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
307468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::set_masks (hb_mask_t    value,
308468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod			hb_mask_t    mask,
309468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod			unsigned int cluster_start,
310468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod			unsigned int cluster_end)
311468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
312468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  hb_mask_t not_mask = ~mask;
313468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  value &= mask;
314468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
315468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (!mask)
316468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
317468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
318468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
319468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    unsigned int count = len;
320468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
321468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      info[i].mask = (info[i].mask & not_mask) | value;
322468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
323468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
324468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
325468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  unsigned int count = len;
326468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
327468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end)
328468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      info[i].mask = (info[i].mask & not_mask) | value;
329468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
330468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
331468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
332468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::reverse_range (unsigned int start,
333468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod			    unsigned int end)
334468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
335468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  unsigned int i, j;
336468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
337468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (start == end - 1)
338468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
339468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
340468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  for (i = start, j = end - 1; i < j; i++, j--) {
341468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    hb_glyph_info_t t;
342468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
343468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    t = info[i];
344468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    info[i] = info[j];
345468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    info[j] = t;
346468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
347468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
348468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (pos) {
349468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    for (i = start, j = end - 1; i < j; i++, j--) {
350468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      hb_glyph_position_t t;
351468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
352468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      t = pos[i];
353468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      pos[i] = pos[j];
354468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      pos[j] = t;
355468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    }
356468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
357468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
358468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
359468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
360468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::reverse (void)
361468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
362468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (!len))
363468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
364468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
365468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  reverse_range (0, len);
366468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
367468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
368468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
369468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::reverse_clusters (void)
370468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
371468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  unsigned int i, start, count, last_cluster;
372468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
373468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (!len))
374468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
375468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
376468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  reverse ();
377468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
378468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  count = len;
379468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  start = 0;
380468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  last_cluster = info[0].cluster;
381468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  for (i = 1; i < count; i++) {
382468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    if (last_cluster != info[i].cluster) {
383468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      reverse_range (start, i);
384468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      start = i;
385468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      last_cluster = info[i].cluster;
386468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    }
387468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
388468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  reverse_range (start, i);
389a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod}
390a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
3913567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
392f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbodvoid hb_buffer_t::allocate_var (unsigned int byte_i, unsigned int count, const char *owner)
393f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod{
394f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  assert (byte_i < 8 && byte_i + count < 8);
395f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  for (unsigned int i = byte_i; i < byte_i + count; i++) {
396f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod    assert (!allocated_var_bytes[i]);
397f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod    allocated_var_bytes[i]++;
398f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod    allocated_var_owner[i] = owner;
399f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  }
400f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod}
401f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod
402f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbodvoid hb_buffer_t::deallocate_var (unsigned int byte_i, unsigned int count, const char *owner)
403f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod{
404f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  assert (byte_i < 8 && byte_i + count < 8);
405f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  for (unsigned int i = byte_i; i < byte_i + count; i++) {
406f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod    assert (allocated_var_bytes[i] && allocated_var_owner[i] == owner);
407f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod    allocated_var_bytes[i]--;
408f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  }
409f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod}
410f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod
411f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod
4126b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod/* Public API */
4136b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
414b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbodhb_buffer_t *
41511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_create (unsigned int pre_alloc_size)
4169f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod{
417b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  hb_buffer_t *buffer;
418b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod
41947e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod  if (!(buffer = hb_object_create<hb_buffer_t> ()))
4203a81b1db89beba91fb91791918b9fdd9f8fc9fa0Behdad Esfahbod    return &_hb_buffer_nil;
4219f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
422468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  buffer->reset ();
4235ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
424468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (pre_alloc_size && !buffer->ensure (pre_alloc_size)) {
425e87867cb88280e3f3a38d829e359cb686168b2cbBehdad Esfahbod    hb_buffer_destroy (buffer);
4263a81b1db89beba91fb91791918b9fdd9f8fc9fa0Behdad Esfahbod    return &_hb_buffer_nil;
427e87867cb88280e3f3a38d829e359cb686168b2cbBehdad Esfahbod  }
428e87867cb88280e3f3a38d829e359cb686168b2cbBehdad Esfahbod
42911fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod  return buffer;
43011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
4317a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
43211fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_t *
43380a6833b032bc63b4e8c3da6489d3767af1168f3Behdad Esfahbodhb_buffer_get_empty (void)
43480a6833b032bc63b4e8c3da6489d3767af1168f3Behdad Esfahbod{
4353a81b1db89beba91fb91791918b9fdd9f8fc9fa0Behdad Esfahbod  return &_hb_buffer_nil;
43680a6833b032bc63b4e8c3da6489d3767af1168f3Behdad Esfahbod}
43780a6833b032bc63b4e8c3da6489d3767af1168f3Behdad Esfahbod
43880a6833b032bc63b4e8c3da6489d3767af1168f3Behdad Esfahbodhb_buffer_t *
43911fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_reference (hb_buffer_t *buffer)
44011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
44147e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod  return hb_object_reference (buffer);
44211fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
443f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
4447a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbodvoid
44511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_destroy (hb_buffer_t *buffer)
4467a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod{
44747e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod  if (!hb_object_destroy (buffer)) return;
44811fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
4495ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  hb_unicode_funcs_destroy (buffer->unicode);
4505ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
4517e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod  free (buffer->info);
4521b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod  free (buffer->pos);
45311fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
454b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  free (buffer);
4557a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod}
4567a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
4575fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_bool_t
4585fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_buffer_set_user_data (hb_buffer_t        *buffer,
4595fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod			 hb_user_data_key_t *key,
4605fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod			 void *              data,
4615fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod			 hb_destroy_func_t   destroy)
4625fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod{
4635fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod  return hb_object_set_user_data (buffer, key, data, destroy);
4645fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod}
4655fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod
4665fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodvoid *
4675fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_buffer_get_user_data (hb_buffer_t        *buffer,
4685fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod			 hb_user_data_key_t *key)
4695fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod{
4705fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod  return hb_object_get_user_data (buffer, key);
4715fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod}
4725fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod
4735ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
4745ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodvoid
4755ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
4765ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod			     hb_unicode_funcs_t *unicode)
4775ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
478e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
479e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
480e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
4810465e69832393cc1ed36508ec5d597fbab64877aBehdad Esfahbod  if (!unicode)
4823a81b1db89beba91fb91791918b9fdd9f8fc9fa0Behdad Esfahbod    unicode = _hb_buffer_nil.unicode;
4830465e69832393cc1ed36508ec5d597fbab64877aBehdad Esfahbod
4845ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  hb_unicode_funcs_reference (unicode);
4855ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  hb_unicode_funcs_destroy (buffer->unicode);
4865ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  buffer->unicode = unicode;
4875ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
4885ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
4895ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_unicode_funcs_t *
4905ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_get_unicode_funcs (hb_buffer_t        *buffer)
4915ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
4925ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  return buffer->unicode;
4935ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
4945ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
4955ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodvoid
4965ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_set_direction (hb_buffer_t    *buffer,
4975ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod			 hb_direction_t  direction)
4985ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
4995ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
500e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
501e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
502e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
5034e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  buffer->props.direction = direction;
5045ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
5055ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
5065ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_direction_t
5075ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_get_direction (hb_buffer_t    *buffer)
5085ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
5094e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  return buffer->props.direction;
5105ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
5115ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
512ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodvoid
513ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_set_script (hb_buffer_t *buffer,
514ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod		      hb_script_t  script)
515ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
516e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
517e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
518e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
5194e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  buffer->props.script = script;
520ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
521ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
522ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_script_t
523ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_get_script (hb_buffer_t *buffer)
524ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
5254e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  return buffer->props.script;
526ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
527ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
528ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodvoid
529ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_set_language (hb_buffer_t   *buffer,
530ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod			hb_language_t  language)
531ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
532e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
533e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
534e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
5354e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  buffer->props.language = language;
536ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
537ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
538ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_language_t
539ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_get_language (hb_buffer_t *buffer)
540ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
5414e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  return buffer->props.language;
542ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
543ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
5445ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
5457a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbodvoid
546c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbodhb_buffer_reset (hb_buffer_t *buffer)
547c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod{
548468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  buffer->reset ();
5497a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod}
5507a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
551a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbodhb_bool_t
55202a534b23f2d1e7475109563b9f61221ed020e8bRyan Lortiehb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
553f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod{
554468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  return buffer->ensure (size);
555f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod}
556f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
557aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbodhb_bool_t
558aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbodhb_buffer_allocation_successful (hb_buffer_t  *buffer)
559aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbod{
560aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbod  return !buffer->in_error;
561aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbod}
562aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbod
563f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbodvoid
564f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbodhb_buffer_add (hb_buffer_t    *buffer,
565f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbod	       hb_codepoint_t  codepoint,
566f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbod	       hb_mask_t       mask,
567f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbod	       unsigned int    cluster)
5686b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod{
569468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  buffer->add (codepoint, mask, cluster);
5709111b21ef99d5e53348176f683261b0101eb427fBehdad Esfahbod}
5719111b21ef99d5e53348176f683261b0101eb427fBehdad Esfahbod
572c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbodhb_bool_t
573c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbodhb_buffer_set_length (hb_buffer_t  *buffer,
574c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod		      unsigned int  length)
575c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod{
576468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (!buffer->ensure (length))
577c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod    return FALSE;
578c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod
579c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  /* Wipe the new space */
580c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  if (length > buffer->len) {
581c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod    memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
582c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod    if (buffer->have_positions)
583c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod      memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
584c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  }
585c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod
586c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  buffer->len = length;
587c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  return TRUE;
588c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod}
589c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod
59011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodunsigned int
5913d14528b8b2e7da425a9df7057fc9fb326d8298cBehdad Esfahbodhb_buffer_get_length (hb_buffer_t *buffer)
59211fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
5936960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  return buffer->len;
59411fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
59511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
59611fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod/* Return value valid as long as buffer not modified */
59711fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_glyph_info_t *
59870566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortiehb_buffer_get_glyph_infos (hb_buffer_t  *buffer,
59970566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie                           unsigned int *length)
60011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
60170566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie  if (length)
60270566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie    *length = buffer->len;
60370566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie
6047e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod  return (hb_glyph_info_t *) buffer->info;
60511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
60611fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
60711fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod/* Return value valid as long as buffer not modified */
60811fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_glyph_position_t *
60970566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortiehb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
61070566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie                               unsigned int *length)
61111fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
612314905d7548d5be58354546d660754b807b6efb2Behdad Esfahbod  if (!buffer->have_positions)
613468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    buffer->clear_positions ();
61411fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
61570566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie  if (length)
61670566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie    *length = buffer->len;
61770566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie
6181b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod  return (hb_glyph_position_t *) buffer->pos;
61911fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
620fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod
621ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodvoid
622ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodhb_buffer_reverse (hb_buffer_t *buffer)
623ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod{
624468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  buffer->reverse ();
625ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod}
626ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
627ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodvoid
628ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodhb_buffer_reverse_clusters (hb_buffer_t *buffer)
629ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod{
630468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  buffer->reverse_clusters ();
631ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod}
632ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
633299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define ADD_UTF(T) \
634299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	HB_STMT_START { \
635299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  const T *next = (const T *) text + item_offset; \
636299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  const T *end = next + item_length; \
637299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  while (next < end) { \
638299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    hb_codepoint_t u; \
639299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    const T *old_next = next; \
640299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    next = UTF_NEXT (next, end, u); \
641f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbod	    hb_buffer_add (buffer, u, 1,  old_next - (const T *) text); \
642299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  } \
643299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	} HB_STMT_END
644299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
645299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
646299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF8_COMPUTE(Char, Mask, Len) \
647299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  if (Char < 128) { Len = 1; Mask = 0x7f; } \
648299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \
649299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \
650299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \
651299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else Len = 0;
652299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
653299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodstatic inline const uint8_t *
654299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_utf8_next (const uint8_t *text,
655299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	      const uint8_t *end,
656299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	      hb_codepoint_t *unicode)
657299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
658299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  uint8_t c = *text;
659299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  unsigned int mask, len;
660299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
661243673d601588a6f704ceafbff5dd5cdf66c47b7Behdad Esfahbod  /* TODO check for overlong sequences? */
6622163afbf35044f59dbf449254e65b8c9feb6cdebBehdad Esfahbod
663299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  UTF8_COMPUTE (c, mask, len);
66464d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod  if (unlikely (!len || (unsigned int) (end - text) < len)) {
665299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    *unicode = -1;
666299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    return text + 1;
667299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  } else {
668299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    hb_codepoint_t result;
669299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    unsigned int i;
670299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    result = c & mask;
671299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    for (i = 1; i < len; i++)
672299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      {
67364d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod	if (unlikely ((text[i] & 0xc0) != 0x80))
674299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  {
675299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    *unicode = -1;
676299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    return text + 1;
677299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  }
678299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	result <<= 6;
679299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	result |= (text[i] & 0x3f);
680299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      }
681299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    *unicode = result;
682299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    return text + len;
683299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  }
684299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
685299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
686299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodvoid
687299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_buffer_add_utf8 (hb_buffer_t  *buffer,
688299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		    const char   *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_utf8_next (S, E, &(U))
694299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  ADD_UTF (uint8_t);
695299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#undef UTF_NEXT
696299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
697299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
698299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodstatic inline const uint16_t *
699299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_utf16_next (const uint16_t *text,
700299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	       const uint16_t *end,
701299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	       hb_codepoint_t *unicode)
702299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
703299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  uint16_t c = *text++;
704299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
70564d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod  if (unlikely (c >= 0xd800 && c < 0xdc00)) {
706299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    /* high surrogate */
707299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    uint16_t l;
70869ea23cb5d47dd1cfd3129f68375021ef79bf63bBehdad Esfahbod    if (text < end && ((l = *text), likely (l >= 0xdc00 && l < 0xe000))) {
709299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      /* low surrogate */
710299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      *unicode = ((hb_codepoint_t) ((c) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000);
711299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod       text++;
712299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    } else
713299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      *unicode = -1;
714299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  } else
715299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    *unicode = c;
716299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
717299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  return text;
718299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
719299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
720299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodvoid
721299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_buffer_add_utf16 (hb_buffer_t    *buffer,
722299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     const uint16_t *text,
72333d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod		     unsigned int    text_length HB_UNUSED,
724299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_offset,
725299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_length)
726299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
727299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF_NEXT(S, E, U)	hb_utf16_next (S, E, &(U))
728299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  ADD_UTF (uint16_t);
729299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#undef UTF_NEXT
730299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
731299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
732299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodvoid
733299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_buffer_add_utf32 (hb_buffer_t    *buffer,
734299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     const uint32_t *text,
73533d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod		     unsigned int    text_length HB_UNUSED,
736299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_offset,
737299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_length)
738299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
739299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF_NEXT(S, E, U)	((U) = *(S), (S)+1)
740299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  ADD_UTF (uint32_t);
741299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#undef UTF_NEXT
742299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
743acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
744acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
745acdba3f90b232fc12fcb200dca2584481b339118Behdad EsfahbodHB_END_DECLS
746