hb-buffer.cc revision a9ad3d3460ba863a8d8f3766ccbeab288c3c6822
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
37a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod#ifndef HB_DEBUG_BUFFER
38a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod#define HB_DEBUG_BUFFER (HB_DEBUG+0)
39a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod#endif
40a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod
41a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod
423a81b1db89beba91fb91791918b9fdd9f8fc9fa0Behdad Esfahbodstatic hb_buffer_t _hb_buffer_nil = {
43fca368c4682624346a0aaee690e1ad6ed4c0b337Behdad Esfahbod  HB_OBJECT_HEADER_STATIC,
445ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
45d4bee9f813bb299b1c4aab7c33d588be2a7d354bBehdad Esfahbod  &_hb_unicode_funcs_default,
46c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod  {
47c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod    HB_DIRECTION_INVALID,
48c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod    HB_SCRIPT_INVALID,
49c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod    NULL,
50c0af193c8e25c4f11d23b8893e9ce1c2d2615bb2Behdad Esfahbod  },
51e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
52e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  TRUE, /* in_error */
53e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  TRUE, /* have_output */
54e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  TRUE  /* have_positions */
5511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod};
5611fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
57a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod/* Here is how the buffer works internally:
58a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod *
59910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * There are two info pointers: info and out_info.  They always have
60910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * the same allocated size, but different lengths.
61a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod *
629d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod * As an optimization, both info and out_info may point to the
637e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod * same piece of memory, which is owned by info.  This remains the
64cc1a8a938b4c13e76b58825a9e1951c4134e634aBehdad Esfahbod * case as long as out_len doesn't exceed i at any time.
65468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod * In that case, swap_buffers() is no-op and the glyph operations operate
66910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * mostly in-place.
67a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod *
689d5e26df0877aa5b187764ba09bd7bf221e92968Behdad Esfahbod * As soon as out_info gets longer than info, out_info is moved over
69910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * to an alternate buffer (which we reuse the pos buffer for!), and its
70910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * current contents (out_len entries) are copied to the new place.
71468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod * This should all remain transparent to the user.  swap_buffers() then
72910a33fe8457a8e13f7eb77fc92fa59c31f5e8fdBehdad Esfahbod * switches info and out_info.
73a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod */
74a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
75c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod
76468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
77468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod/* Internal API */
78468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
79468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodbool
80468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::enlarge (unsigned int size)
813567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod{
82468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (in_error))
833567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod    return FALSE;
843567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
85468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  unsigned int new_allocated = allocated;
86e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  hb_glyph_position_t *new_pos = NULL;
87e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  hb_glyph_info_t *new_info = NULL;
88468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  bool separate_out = out_info != info;
893567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
90468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
91e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    goto done;
923567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
933567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  while (size > new_allocated)
9465e0063eae2f3adb25315b8bd7b0e7757aa960f3Behdad Esfahbod    new_allocated += (new_allocated >> 1) + 32;
953567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
96468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0]));
97468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0]))))
98e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    goto done;
99e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
100468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0]));
101468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0]));
1023567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
103e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahboddone:
1043567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (unlikely (!new_pos || !new_info))
105468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    in_error = TRUE;
1063567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
1073567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (likely (new_pos))
108468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    pos = new_pos;
1093567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
1103567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod  if (likely (new_info))
111468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    info = new_info;
112468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
113468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info = separate_out ? (hb_glyph_info_t *) pos : info;
114468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (likely (!in_error))
115468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    allocated = new_allocated;
116468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
117468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  return likely (!in_error);
118468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
119468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
120468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodbool
121468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::make_room_for (unsigned int num_in,
122468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod			    unsigned int num_out)
123468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
124468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (!ensure (out_len + num_out))) return FALSE;
125468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
126468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (out_info == info &&
127468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      out_len + num_out > idx + num_in)
128468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  {
129468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    assert (have_output);
130468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
131468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    out_info = (hb_glyph_info_t *) pos;
132468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    memcpy (out_info, info, out_len * sizeof (out_info[0]));
133468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
134468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
135468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  return TRUE;
136468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
137468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
138468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
139468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod/* HarfBuzz-Internal API */
140468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
141468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
142468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::reset (void)
143468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
144468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (hb_object_is_inert (this)))
145468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
146468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
147468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  hb_unicode_funcs_destroy (unicode);
1483a81b1db89beba91fb91791918b9fdd9f8fc9fa0Behdad Esfahbod  unicode = _hb_buffer_nil.unicode;
149468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
1503a81b1db89beba91fb91791918b9fdd9f8fc9fa0Behdad Esfahbod  props = _hb_buffer_nil.props;
151468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
152468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  in_error = FALSE;
153468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  have_output = FALSE;
154468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  have_positions = FALSE;
1553567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
156468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  idx = 0;
157468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  len = 0;
158468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_len = 0;
1593567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
160468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  serial = 0;
161f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  memset (allocated_var_bytes, 0, sizeof allocated_var_bytes);
162f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  memset (allocated_var_owner, 0, sizeof allocated_var_owner);
163468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
164468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info = info;
1653567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod}
1663567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
167468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
168468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::add (hb_codepoint_t  codepoint,
169468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod		  hb_mask_t       mask,
170468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod		  unsigned int    cluster)
1713567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod{
172468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  hb_glyph_info_t *glyph;
173468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
174468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (!ensure (len + 1))) return;
175468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
176468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  glyph = &info[len];
177468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
178468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  memset (glyph, 0, sizeof (*glyph));
179468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  glyph->codepoint = codepoint;
180468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  glyph->mask = mask;
181468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  glyph->cluster = cluster;
182468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
183468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  len++;
1843567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod}
1856b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
186468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
187468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::clear_output (void)
188c968fc2dc87cf85b53f60a40db59d5ee7b992edfBehdad Esfahbod{
189468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (hb_object_is_inert (this)))
190468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
191468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
192468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  have_output = TRUE;
193468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  have_positions = FALSE;
194a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod
195468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_len = 0;
196468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info = info;
197468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
198468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
199468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
200468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::clear_positions (void)
201468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
202468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (hb_object_is_inert (this)))
203468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
204468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
205468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  have_output = FALSE;
206468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  have_positions = TRUE;
207468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
208468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  memset (pos, 0, sizeof (pos[0]) * len);
209468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
210468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
211468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
212468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::swap_buffers (void)
213468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
214468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (in_error)) return;
215468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
216468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  assert (have_output);
217468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
218468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (out_info != info)
219e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  {
220468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    hb_glyph_info_t *tmp_string;
221468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    tmp_string = info;
222468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    info = out_info;
223468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    out_info = tmp_string;
224468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    pos = (hb_glyph_position_t *) out_info;
225468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
226468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
227468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  unsigned int tmp;
228468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  tmp = len;
229468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  len = out_len;
230468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_len = tmp;
231468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
232468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  idx = 0;
233468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
234e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod
235468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
236468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::replace_glyphs_be16 (unsigned int num_in,
237468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod				  unsigned int num_out,
238468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod				  const uint16_t *glyph_data_be)
239468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
240468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (!make_room_for (num_in, num_out)) return;
241468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
242468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  hb_glyph_info_t orig_info = info[idx];
243468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  for (unsigned int i = 1; i < num_in; i++)
244468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  {
245468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    hb_glyph_info_t *inf = &info[idx + i];
246468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    orig_info.cluster = MIN (orig_info.cluster, inf->cluster);
247e35bbd570a5d914f86f1ea83941ee4328f268059Behdad Esfahbod  }
248a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbod
249468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  hb_glyph_info_t *pinfo = &out_info[out_len];
250468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  for (unsigned int i = 0; i < num_out; i++)
251468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  {
252468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    *pinfo = orig_info;
253468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    pinfo->codepoint = hb_be_uint16 (glyph_data_be[i]);
254468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    pinfo++;
255468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
256468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
257468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  idx  += num_in;
258468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_len += num_out;
259468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
260468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
261468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
262468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
263468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
264468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (!make_room_for (0, 1)) return;
265468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
266468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info[out_len] = info[idx];
267468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info[out_len].codepoint = glyph_index;
268468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
269468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_len++;
270468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
271468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
272468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
273468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::copy_glyph (void)
274468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
275468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (!make_room_for (0, 1)) return;
276468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
277468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info[out_len] = info[idx];
278468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
279468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_len++;
280468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
281468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
282468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
283468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
284468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
285468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info[out_len] = info[idx];
286468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_info[out_len].codepoint = glyph_index;
287468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
288468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  idx++;
289468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  out_len++;
290468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
291468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
292468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
293468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::next_glyph (void)
294468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
295468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (have_output)
296468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  {
297468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    if (out_info != info)
298468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    {
299468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      if (unlikely (!ensure (out_len + 1))) return;
300468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      out_info[out_len] = info[idx];
301468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    }
302468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    else if (out_len != idx)
303468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      out_info[out_len] = info[idx];
304468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
305468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    out_len++;
306468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
307468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
308468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  idx++;
309468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
310468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
311468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
312468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::set_masks (hb_mask_t    value,
313468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod			hb_mask_t    mask,
314468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod			unsigned int cluster_start,
315468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod			unsigned int cluster_end)
316468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
317468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  hb_mask_t not_mask = ~mask;
318468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  value &= mask;
319468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
320468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (!mask)
321468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
322468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
323468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
324468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    unsigned int count = len;
325468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
326468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      info[i].mask = (info[i].mask & not_mask) | value;
327468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
328468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
329468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
330468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  unsigned int count = len;
331468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
332468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end)
333468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      info[i].mask = (info[i].mask & not_mask) | value;
334468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
335468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
336468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
337468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::reverse_range (unsigned int start,
338468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod			    unsigned int end)
339468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
340468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  unsigned int i, j;
341468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
342468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (start == end - 1)
343468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
344468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
345468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  for (i = start, j = end - 1; i < j; i++, j--) {
346468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    hb_glyph_info_t t;
347468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
348468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    t = info[i];
349468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    info[i] = info[j];
350468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    info[j] = t;
351468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
352468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
353468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (pos) {
354468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    for (i = start, j = end - 1; i < j; i++, j--) {
355468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      hb_glyph_position_t t;
356468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
357468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      t = pos[i];
358468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      pos[i] = pos[j];
359468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      pos[j] = t;
360468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    }
361468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
362468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
363468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
364468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
365468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::reverse (void)
366468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
367468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (!len))
368468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
369468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
370468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  reverse_range (0, len);
371468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod}
372468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
373468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodvoid
374468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbodhb_buffer_t::reverse_clusters (void)
375468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod{
376468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  unsigned int i, start, count, last_cluster;
377468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
378468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (unlikely (!len))
379468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    return;
380468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
381468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  reverse ();
382468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod
383468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  count = len;
384468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  start = 0;
385468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  last_cluster = info[0].cluster;
386468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  for (i = 1; i < count; i++) {
387468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    if (last_cluster != info[i].cluster) {
388468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      reverse_range (start, i);
389468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      start = i;
390468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod      last_cluster = info[i].cluster;
391468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    }
392468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  }
393468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  reverse_range (start, i);
394a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod}
395a8abb8b994c3cd89808e8f7128a0c04b23eb3edeBehdad Esfahbod
396a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbodstatic inline void
397a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahboddump_var_allocation (const hb_buffer_t *buffer)
398a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod{
399a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod  char buf[80];
400a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod  for (unsigned int i = 0; i < 8; i++)
401a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod    buf[i] = '0' + buffer->allocated_var_bytes[i];
402a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod  buf[8] = '\0';
403a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod  DEBUG_MSG (BUFFER, buffer,
404a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod	     "Current var allocation: %s",
405a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod	     buf);
406a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod}
4073567b87cce541dfb0af7caf024ec67c9d3c09214Behdad Esfahbod
408f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbodvoid hb_buffer_t::allocate_var (unsigned int byte_i, unsigned int count, const char *owner)
409f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod{
410f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  assert (byte_i < 8 && byte_i + count < 8);
411a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod
412a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod  if (DEBUG (BUFFER))
413a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod    dump_var_allocation (this);
414a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod  DEBUG_MSG (BUFFER, this,
415a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod	     "Allocating var bytes %d..%d for %s",
416a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod	     byte_i, byte_i + count - 1, owner);
417a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod
418f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  for (unsigned int i = byte_i; i < byte_i + count; i++) {
419f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod    assert (!allocated_var_bytes[i]);
420f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod    allocated_var_bytes[i]++;
421f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod    allocated_var_owner[i] = owner;
422f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  }
423f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod}
424f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod
425f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbodvoid hb_buffer_t::deallocate_var (unsigned int byte_i, unsigned int count, const char *owner)
426f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod{
427a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod  DEBUG_MSG (BUFFER, this,
428a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod	     "Deallocating var bytes %d..%d for %s",
429a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod	     byte_i, byte_i + count - 1, owner);
430a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod
431f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  assert (byte_i < 8 && byte_i + count < 8);
432f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  for (unsigned int i = byte_i; i < byte_i + count; i++) {
433f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod    assert (allocated_var_bytes[i] && allocated_var_owner[i] == owner);
434f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod    allocated_var_bytes[i]--;
435f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod  }
436a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod
437a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod  if (DEBUG (BUFFER))
438a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod    dump_var_allocation (this);
439f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod}
440f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod
441a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbodvoid hb_buffer_t::deallocate_var_all (void)
442a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod{
443a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod  memset (allocated_var_bytes, 0, sizeof (allocated_var_bytes));
444a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod  memset (allocated_var_owner, 0, sizeof (allocated_var_owner));
445a9ad3d3460ba863a8d8f3766ccbeab288c3c6822Behdad Esfahbod}
446f4a579bc42fb811ff5c391a0e97b7d8656ef59b1Behdad Esfahbod
4476b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod/* Public API */
4486b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod
449b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbodhb_buffer_t *
45011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_create (unsigned int pre_alloc_size)
4519f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod{
452b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  hb_buffer_t *buffer;
453b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod
45447e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod  if (!(buffer = hb_object_create<hb_buffer_t> ()))
4553a81b1db89beba91fb91791918b9fdd9f8fc9fa0Behdad Esfahbod    return &_hb_buffer_nil;
4569f8da38cd108590514b71756b752d98952a9221fBehdad Esfahbod
457468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  buffer->reset ();
4585ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
459468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (pre_alloc_size && !buffer->ensure (pre_alloc_size)) {
460e87867cb88280e3f3a38d829e359cb686168b2cbBehdad Esfahbod    hb_buffer_destroy (buffer);
4613a81b1db89beba91fb91791918b9fdd9f8fc9fa0Behdad Esfahbod    return &_hb_buffer_nil;
462e87867cb88280e3f3a38d829e359cb686168b2cbBehdad Esfahbod  }
463e87867cb88280e3f3a38d829e359cb686168b2cbBehdad Esfahbod
46411fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod  return buffer;
46511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
4667a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
46711fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_t *
46880a6833b032bc63b4e8c3da6489d3767af1168f3Behdad Esfahbodhb_buffer_get_empty (void)
46980a6833b032bc63b4e8c3da6489d3767af1168f3Behdad Esfahbod{
4703a81b1db89beba91fb91791918b9fdd9f8fc9fa0Behdad Esfahbod  return &_hb_buffer_nil;
47180a6833b032bc63b4e8c3da6489d3767af1168f3Behdad Esfahbod}
47280a6833b032bc63b4e8c3da6489d3767af1168f3Behdad Esfahbod
47380a6833b032bc63b4e8c3da6489d3767af1168f3Behdad Esfahbodhb_buffer_t *
47411fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_reference (hb_buffer_t *buffer)
47511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
47647e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod  return hb_object_reference (buffer);
47711fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
478f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
4797a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbodvoid
48011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_buffer_destroy (hb_buffer_t *buffer)
4817a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod{
48247e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod  if (!hb_object_destroy (buffer)) return;
48311fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
4845ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  hb_unicode_funcs_destroy (buffer->unicode);
4855ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
4867e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod  free (buffer->info);
4871b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod  free (buffer->pos);
48811fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
489b857b49c82782d29d6d189f1a9f4a84d39cd84eaBehdad Esfahbod  free (buffer);
4907a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod}
4917a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
4925fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_bool_t
4935fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_buffer_set_user_data (hb_buffer_t        *buffer,
4945fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod			 hb_user_data_key_t *key,
4955fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod			 void *              data,
4965fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod			 hb_destroy_func_t   destroy)
4975fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod{
4985fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod  return hb_object_set_user_data (buffer, key, data, destroy);
4995fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod}
5005fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod
5015fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodvoid *
5025fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_buffer_get_user_data (hb_buffer_t        *buffer,
5035fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod			 hb_user_data_key_t *key)
5045fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod{
5055fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod  return hb_object_get_user_data (buffer, key);
5065fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod}
5075fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod
5085ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
5095ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodvoid
5105ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
5115ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod			     hb_unicode_funcs_t *unicode)
5125ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
513e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
514e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
515e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
5160465e69832393cc1ed36508ec5d597fbab64877aBehdad Esfahbod  if (!unicode)
5173a81b1db89beba91fb91791918b9fdd9f8fc9fa0Behdad Esfahbod    unicode = _hb_buffer_nil.unicode;
5180465e69832393cc1ed36508ec5d597fbab64877aBehdad Esfahbod
5195ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  hb_unicode_funcs_reference (unicode);
5205ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  hb_unicode_funcs_destroy (buffer->unicode);
5215ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  buffer->unicode = unicode;
5225ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
5235ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
5245ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_unicode_funcs_t *
5255ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_get_unicode_funcs (hb_buffer_t        *buffer)
5265ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
5275ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod  return buffer->unicode;
5285ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
5295ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
5305ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodvoid
5315ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_set_direction (hb_buffer_t    *buffer,
5325ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod			 hb_direction_t  direction)
5335ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
5345ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
535e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
536e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
537e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
5384e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  buffer->props.direction = direction;
5395ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
5405ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
5415ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_direction_t
5425ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbodhb_buffer_get_direction (hb_buffer_t    *buffer)
5435ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod{
5444e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  return buffer->props.direction;
5455ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod}
5465ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
547ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodvoid
548ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_set_script (hb_buffer_t *buffer,
549ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod		      hb_script_t  script)
550ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
551e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
552e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
553e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
5544e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  buffer->props.script = script;
555ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
556ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
557ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_script_t
558ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_get_script (hb_buffer_t *buffer)
559ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
5604e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  return buffer->props.script;
561ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
562ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
563ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodvoid
564ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_set_language (hb_buffer_t   *buffer,
565ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod			hb_language_t  language)
566ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
567e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod  if (unlikely (hb_object_is_inert (buffer)))
568e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod    return;
569e0db4b868f9fdd8e680890f87dd4e13a1c27b7a1Behdad Esfahbod
5704e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  buffer->props.language = language;
571ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
572ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
573ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_language_t
574ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbodhb_buffer_get_language (hb_buffer_t *buffer)
575ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod{
5764e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod  return buffer->props.language;
577ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod}
578ae070b7d39d03bd8bc1244f687b24db505f4af3fBehdad Esfahbod
5795ebabecef382c3e8b0a2a5657b2c01f7ff37d796Behdad Esfahbod
5807a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbodvoid
581c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbodhb_buffer_reset (hb_buffer_t *buffer)
582c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod{
583468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  buffer->reset ();
5847a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod}
5857a26864308bd1ca8d5f47d798411cac7239b7d38Behdad Esfahbod
586a6a79df5fe2ed2cd307e7a991346faee164e70d9Behdad Esfahbodhb_bool_t
58702a534b23f2d1e7475109563b9f61221ed020e8bRyan Lortiehb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
588f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod{
589468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  return buffer->ensure (size);
590f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod}
591f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
592aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbodhb_bool_t
593aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbodhb_buffer_allocation_successful (hb_buffer_t  *buffer)
594aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbod{
595aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbod  return !buffer->in_error;
596aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbod}
597aab0de50e23727b69fa8c3d4e05c50c114c62835Behdad Esfahbod
598f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbodvoid
599f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbodhb_buffer_add (hb_buffer_t    *buffer,
600f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbod	       hb_codepoint_t  codepoint,
601f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbod	       hb_mask_t       mask,
602f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbod	       unsigned int    cluster)
6036b347138b597c41af24453f630336ba2fc033dc5Behdad Esfahbod{
604468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  buffer->add (codepoint, mask, cluster);
6059111b21ef99d5e53348176f683261b0101eb427fBehdad Esfahbod}
6069111b21ef99d5e53348176f683261b0101eb427fBehdad Esfahbod
607c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbodhb_bool_t
608c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbodhb_buffer_set_length (hb_buffer_t  *buffer,
609c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod		      unsigned int  length)
610c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod{
611468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  if (!buffer->ensure (length))
612c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod    return FALSE;
613c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod
614c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  /* Wipe the new space */
615c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  if (length > buffer->len) {
616c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod    memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
617c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod    if (buffer->have_positions)
618c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod      memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
619c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  }
620c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod
621c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  buffer->len = length;
622c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod  return TRUE;
623c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod}
624c910bec863215f918c659f58debbc7fe5264d7b6Behdad Esfahbod
62511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodunsigned int
6263d14528b8b2e7da425a9df7057fc9fb326d8298cBehdad Esfahbodhb_buffer_get_length (hb_buffer_t *buffer)
62711fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
6286960350be97f24e97140391025b56369c393a3dfBehdad Esfahbod  return buffer->len;
62911fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
63011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
63111fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod/* Return value valid as long as buffer not modified */
63211fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_glyph_info_t *
63370566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortiehb_buffer_get_glyph_infos (hb_buffer_t  *buffer,
63470566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie                           unsigned int *length)
63511fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
63670566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie  if (length)
63770566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie    *length = buffer->len;
63870566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie
6397e7007a1c9bf2c07a8369752126ece8fa6164248Behdad Esfahbod  return (hb_glyph_info_t *) buffer->info;
64011fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
64111fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
64211fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod/* Return value valid as long as buffer not modified */
64311fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbodhb_glyph_position_t *
64470566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortiehb_buffer_get_glyph_positions (hb_buffer_t  *buffer,
64570566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie                               unsigned int *length)
64611fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod{
647314905d7548d5be58354546d660754b807b6efb2Behdad Esfahbod  if (!buffer->have_positions)
648468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod    buffer->clear_positions ();
64911fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod
65070566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie  if (length)
65170566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie    *length = buffer->len;
65270566befc59cfa8b9c43ac682749c40ea783b1ddRyan Lortie
6531b621823f3e31b48c80cc8b0691dfa873ba086cdBehdad Esfahbod  return (hb_glyph_position_t *) buffer->pos;
65411fbb5487d9900a019440ef8235f35c9f525decbBehdad Esfahbod}
655fbaf8ffa098bd2b6fb4f4bc2d04b360a319c4af5Behdad Esfahbod
656ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodvoid
657ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodhb_buffer_reverse (hb_buffer_t *buffer)
658ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod{
659468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  buffer->reverse ();
660ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod}
661ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
662ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodvoid
663ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbodhb_buffer_reverse_clusters (hb_buffer_t *buffer)
664ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod{
665468e9cb25c9bc14781b7013e447d763f93bf76a3Behdad Esfahbod  buffer->reverse_clusters ();
666ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod}
667ff44f88df2c46920f3ec2384ef321a4c7bb0f6efBehdad Esfahbod
668299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define ADD_UTF(T) \
669299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	HB_STMT_START { \
670299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  const T *next = (const T *) text + item_offset; \
671299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  const T *end = next + item_length; \
672299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  while (next < end) { \
673299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    hb_codepoint_t u; \
674299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    const T *old_next = next; \
675299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    next = UTF_NEXT (next, end, u); \
676f85faee9b3cb841ea977403945e2c877ab32b97aBehdad Esfahbod	    hb_buffer_add (buffer, u, 1,  old_next - (const T *) text); \
677299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  } \
678299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	} HB_STMT_END
679299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
680299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
681299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF8_COMPUTE(Char, Mask, Len) \
682299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  if (Char < 128) { Len = 1; Mask = 0x7f; } \
683299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else if ((Char & 0xe0) == 0xc0) { Len = 2; Mask = 0x1f; } \
684299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else if ((Char & 0xf0) == 0xe0) { Len = 3; Mask = 0x0f; } \
685299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else if ((Char & 0xf8) == 0xf0) { Len = 4; Mask = 0x07; } \
686299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  else Len = 0;
687299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
688299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodstatic inline const uint8_t *
689299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_utf8_next (const uint8_t *text,
690299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	      const uint8_t *end,
691299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	      hb_codepoint_t *unicode)
692299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
693299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  uint8_t c = *text;
694299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  unsigned int mask, len;
695299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
696243673d601588a6f704ceafbff5dd5cdf66c47b7Behdad Esfahbod  /* TODO check for overlong sequences? */
6972163afbf35044f59dbf449254e65b8c9feb6cdebBehdad Esfahbod
698299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  UTF8_COMPUTE (c, mask, len);
69964d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod  if (unlikely (!len || (unsigned int) (end - text) < len)) {
700299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    *unicode = -1;
701299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    return text + 1;
702299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  } else {
703299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    hb_codepoint_t result;
704299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    unsigned int i;
705299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    result = c & mask;
706299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    for (i = 1; i < len; i++)
707299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      {
70864d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod	if (unlikely ((text[i] & 0xc0) != 0x80))
709299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  {
710299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    *unicode = -1;
711299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	    return text + 1;
712299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	  }
713299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	result <<= 6;
714299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	result |= (text[i] & 0x3f);
715299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      }
716299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    *unicode = result;
717299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    return text + len;
718299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  }
719299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
720299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
721299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodvoid
722299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_buffer_add_utf8 (hb_buffer_t  *buffer,
723299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		    const char   *text,
72433d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod		    unsigned int  text_length HB_UNUSED,
725299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		    unsigned int  item_offset,
726299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		    unsigned int  item_length)
727299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
728299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF_NEXT(S, E, U)	hb_utf8_next (S, E, &(U))
729299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  ADD_UTF (uint8_t);
730299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#undef UTF_NEXT
731299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
732299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
733299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodstatic inline const uint16_t *
734299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_utf16_next (const uint16_t *text,
735299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	       const uint16_t *end,
736299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod	       hb_codepoint_t *unicode)
737299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
738299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  uint16_t c = *text++;
739299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
74064d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod  if (unlikely (c >= 0xd800 && c < 0xdc00)) {
741299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    /* high surrogate */
742299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    uint16_t l;
74369ea23cb5d47dd1cfd3129f68375021ef79bf63bBehdad Esfahbod    if (text < end && ((l = *text), likely (l >= 0xdc00 && l < 0xe000))) {
744299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      /* low surrogate */
745299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      *unicode = ((hb_codepoint_t) ((c) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000);
746299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod       text++;
747299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    } else
748299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod      *unicode = -1;
749299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  } else
750299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod    *unicode = c;
751299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
752299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  return text;
753299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
754299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
755299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodvoid
756299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_buffer_add_utf16 (hb_buffer_t    *buffer,
757299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     const uint16_t *text,
75833d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod		     unsigned int    text_length HB_UNUSED,
759299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_offset,
760299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_length)
761299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
762299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF_NEXT(S, E, U)	hb_utf16_next (S, E, &(U))
763299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  ADD_UTF (uint16_t);
764299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#undef UTF_NEXT
765299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
766299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod
767299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodvoid
768299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbodhb_buffer_add_utf32 (hb_buffer_t    *buffer,
769299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     const uint32_t *text,
77033d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod		     unsigned int    text_length HB_UNUSED,
771299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_offset,
772299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod		     unsigned int    item_length)
773299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod{
774299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#define UTF_NEXT(S, E, U)	((U) = *(S), (S)+1)
775299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod  ADD_UTF (uint32_t);
776299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod#undef UTF_NEXT
777299f08961ffcea27e8def4f0743d0c86ef8dadf1Behdad Esfahbod}
778acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
779acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
780acdba3f90b232fc12fcb200dca2584481b339118Behdad EsfahbodHB_END_DECLS
781