blob: 3940a3dbf8ecd122f86c3fbb2472b21ecfea0afa [file] [log] [blame]
Behdad Esfahboda2a9a022008-01-15 22:46:32 +00001/*
Behdad Esfahbod2409d5f2011-04-21 17:14:28 -04002 * Copyright © 1998-2004 David Turner and Werner Lemberg
3 * Copyright © 2004,2007,2009,2010 Red Hat, Inc.
Behdad Esfahbod05207a72012-09-25 17:44:53 -04004 * Copyright © 2011,2012 Google, Inc.
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005 *
Behdad Esfahbod8f0d7e02011-04-15 18:59:56 -04006 * This is part of HarfBuzz, a text shaping library.
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00007 *
Behdad Esfahboda2a9a022008-01-15 22:46:32 +00008 * Permission is hereby granted, without written agreement and without
9 * license or royalty fees, to use, copy, modify, and distribute this
10 * software and its documentation for any purpose, provided that the
11 * above copyright notice and the following two paragraphs appear in
12 * all copies of this software.
13 *
14 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
15 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
17 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18 * DAMAGE.
19 *
20 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
21 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
23 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
24 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25 *
26 * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
Behdad Esfahbodc910bec2011-04-13 15:49:06 -040027 * Google Author(s): Behdad Esfahbod
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000028 */
29
Behdad Esfahbod22da7fd2010-05-12 18:23:21 -040030#include "hb-buffer-private.hh"
Behdad Esfahbod7f19ae72012-09-25 11:22:28 -040031#include "hb-utf-private.hh"
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000032
Behdad Esfahbodf1322e52009-08-01 22:53:04 -040033
Behdad Esfahboda9ad3d32011-07-28 15:42:18 -040034#ifndef HB_DEBUG_BUFFER
35#define HB_DEBUG_BUFFER (HB_DEBUG+0)
36#endif
37
Khaled Hosnyf18d2222015-12-29 15:21:20 +040038/**
39 * SECTION: hb-buffer
40 * @title: Buffers
41 * @short_description: Input and output buffers
42 * @include: hb.h
43 *
44 * Buffers serve dual role in HarfBuzz; they hold the input characters that are
45 * passed hb_shape(), and after shaping they hold the output glyphs.
46 **/
Behdad Esfahbodf3064102012-11-15 18:39:46 -080047
Sascha Brawer01c3a882015-06-01 13:22:01 +020048/**
Behdad Esfahbod35d18582015-11-26 19:30:37 -050049 * hb_segment_properties_equal:
Khaled Hosny9ab9f972016-01-01 20:38:21 +040050 * @a: first #hb_segment_properties_t to compare.
51 * @b: second #hb_segment_properties_t to compare.
52 *
53 * Checks the equality of two #hb_segment_properties_t's.
54 *
Behdad Esfahbod70e72e52016-06-28 21:00:37 -070055 * Return value:
Khaled Hosny9ab9f972016-01-01 20:38:21 +040056 * %true if all properties of @a equal those of @b, false otherwise.
Behdad Esfahbod35d18582015-11-26 19:30:37 -050057 *
Sascha Brawer01c3a882015-06-01 13:22:01 +020058 * Since: 0.9.7
59 **/
Behdad Esfahbodf3064102012-11-15 18:39:46 -080060hb_bool_t
61hb_segment_properties_equal (const hb_segment_properties_t *a,
62 const hb_segment_properties_t *b)
63{
64 return a->direction == b->direction &&
65 a->script == b->script &&
66 a->language == b->language &&
67 a->reserved1 == b->reserved1 &&
68 a->reserved2 == b->reserved2;
69
70}
71
Sascha Brawer01c3a882015-06-01 13:22:01 +020072/**
Behdad Esfahbod35d18582015-11-26 19:30:37 -050073 * hb_segment_properties_hash:
Khaled Hosny9ab9f972016-01-01 20:38:21 +040074 * @p: #hb_segment_properties_t to hash.
75 *
76 * Creates a hash representing @p.
77 *
78 * Return value:
79 * A hash of @p.
Behdad Esfahbod35d18582015-11-26 19:30:37 -050080 *
Sascha Brawer01c3a882015-06-01 13:22:01 +020081 * Since: 0.9.7
82 **/
Behdad Esfahbodf3064102012-11-15 18:39:46 -080083unsigned int
84hb_segment_properties_hash (const hb_segment_properties_t *p)
85{
86 return (unsigned int) p->direction ^
87 (unsigned int) p->script ^
88 (intptr_t) (p->language);
89}
90
91
92
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +000093/* Here is how the buffer works internally:
94 *
Behdad Esfahbod910a33f2010-05-14 22:13:38 -040095 * There are two info pointers: info and out_info. They always have
96 * the same allocated size, but different lengths.
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +000097 *
Behdad Esfahbod9d5e26d2010-05-14 22:03:11 -040098 * As an optimization, both info and out_info may point to the
Behdad Esfahbod7e7007a2010-05-14 22:02:37 -040099 * same piece of memory, which is owned by info. This remains the
Behdad Esfahbodcc1a8a92011-01-06 14:58:52 -0500100 * case as long as out_len doesn't exceed i at any time.
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400101 * In that case, swap_buffers() is no-op and the glyph operations operate
Behdad Esfahbod910a33f2010-05-14 22:13:38 -0400102 * mostly in-place.
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000103 *
Behdad Esfahbod9d5e26d2010-05-14 22:03:11 -0400104 * As soon as out_info gets longer than info, out_info is moved over
Behdad Esfahbod910a33f2010-05-14 22:13:38 -0400105 * to an alternate buffer (which we reuse the pos buffer for!), and its
106 * current contents (out_len entries) are copied to the new place.
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400107 * This should all remain transparent to the user. swap_buffers() then
Behdad Esfahbod910a33f2010-05-14 22:13:38 -0400108 * switches info and out_info.
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000109 */
110
Behdad Esfahbodc968fc22009-05-25 04:04:24 -0400111
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400112
113/* Internal API */
114
115bool
116hb_buffer_t::enlarge (unsigned int size)
Behdad Esfahbod3567b872010-05-14 23:28:44 -0400117{
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400118 if (unlikely (in_error))
Behdad Esfahbod0594a242012-06-05 20:35:40 -0400119 return false;
Behdad Esfahbod43017032015-11-05 23:44:59 -0800120 if (unlikely (size > max_len))
121 {
122 in_error = true;
123 return false;
124 }
Behdad Esfahbod3567b872010-05-14 23:28:44 -0400125
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400126 unsigned int new_allocated = allocated;
Behdad Esfahbode0db4b82011-04-28 12:56:49 -0400127 hb_glyph_position_t *new_pos = NULL;
128 hb_glyph_info_t *new_info = NULL;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400129 bool separate_out = out_info != info;
Behdad Esfahbod3567b872010-05-14 23:28:44 -0400130
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400131 if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
Behdad Esfahbode0db4b82011-04-28 12:56:49 -0400132 goto done;
Behdad Esfahbod3567b872010-05-14 23:28:44 -0400133
Behdad Esfahbod38b015e2012-10-28 20:11:47 -0700134 while (size >= new_allocated)
Behdad Esfahbod65e00632011-04-27 09:33:58 -0400135 new_allocated += (new_allocated >> 1) + 32;
Behdad Esfahbod3567b872010-05-14 23:28:44 -0400136
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400137 ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0]));
138 if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0]))))
Behdad Esfahbode0db4b82011-04-28 12:56:49 -0400139 goto done;
Behdad Esfahbodb5dd44e2011-02-28 10:13:52 -0800140
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400141 new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0]));
142 new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0]));
Behdad Esfahbod3567b872010-05-14 23:28:44 -0400143
Behdad Esfahbode0db4b82011-04-28 12:56:49 -0400144done:
Behdad Esfahbod3567b872010-05-14 23:28:44 -0400145 if (unlikely (!new_pos || !new_info))
Behdad Esfahbod0594a242012-06-05 20:35:40 -0400146 in_error = true;
Behdad Esfahbod3567b872010-05-14 23:28:44 -0400147
148 if (likely (new_pos))
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400149 pos = new_pos;
Behdad Esfahbod3567b872010-05-14 23:28:44 -0400150
151 if (likely (new_info))
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400152 info = new_info;
Behdad Esfahbod3567b872010-05-14 23:28:44 -0400153
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400154 out_info = separate_out ? (hb_glyph_info_t *) pos : info;
155 if (likely (!in_error))
156 allocated = new_allocated;
Behdad Esfahbod3567b872010-05-14 23:28:44 -0400157
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400158 return likely (!in_error);
Behdad Esfahbod3567b872010-05-14 23:28:44 -0400159}
160
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400161bool
162hb_buffer_t::make_room_for (unsigned int num_in,
163 unsigned int num_out)
Behdad Esfahbod3567b872010-05-14 23:28:44 -0400164{
Behdad Esfahbod0594a242012-06-05 20:35:40 -0400165 if (unlikely (!ensure (out_len + num_out))) return false;
Behdad Esfahbod6b347132007-10-11 08:30:50 +0000166
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400167 if (out_info == info &&
168 out_len + num_out > idx + num_in)
Behdad Esfahbode35bbd52009-05-30 12:02:46 -0400169 {
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400170 assert (have_output);
Behdad Esfahbode35bbd52009-05-30 12:02:46 -0400171
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400172 out_info = (hb_glyph_info_t *) pos;
173 memcpy (out_info, info, out_len * sizeof (out_info[0]));
Behdad Esfahbode35bbd52009-05-30 12:02:46 -0400174 }
Behdad Esfahboda6a79df2010-05-14 23:20:16 -0400175
Behdad Esfahbod0594a242012-06-05 20:35:40 -0400176 return true;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000177}
178
Behdad Esfahbod6b65a762013-10-14 18:51:39 +0200179bool
180hb_buffer_t::shift_forward (unsigned int count)
181{
182 assert (have_output);
183 if (unlikely (!ensure (len + count))) return false;
184
185 memmove (info + idx + count, info + idx, (len - idx) * sizeof (info[0]));
Behdad Esfahbod6363d7d2016-07-20 01:43:56 -0700186 if (idx + count > len)
187 {
188 /* Under memory failure we might expose this area. At least
189 * clean it up. Oh well... */
190 memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
191 }
Behdad Esfahbod6b65a762013-10-14 18:51:39 +0200192 len += count;
193 idx += count;
194
195 return true;
196}
197
Behdad Esfahbod68c372e2013-11-13 14:44:01 -0500198hb_buffer_t::scratch_buffer_t *
199hb_buffer_t::get_scratch_buffer (unsigned int *size)
Behdad Esfahbode62df432011-08-03 17:38:54 -0400200{
Behdad Esfahbod0594a242012-06-05 20:35:40 -0400201 have_output = false;
202 have_positions = false;
Behdad Esfahbod47ef9312012-07-19 20:52:44 -0400203
Behdad Esfahbode62df432011-08-03 17:38:54 -0400204 out_len = 0;
Behdad Esfahbod47ef9312012-07-19 20:52:44 -0400205 out_info = info;
206
Behdad Esfahbod061cb462013-11-13 14:50:25 -0500207 assert ((uintptr_t) pos % sizeof (scratch_buffer_t) == 0);
Behdad Esfahbod68c372e2013-11-13 14:44:01 -0500208 *size = allocated * sizeof (pos[0]) / sizeof (scratch_buffer_t);
Behdad Esfahbod061cb462013-11-13 14:50:25 -0500209 return (scratch_buffer_t *) (void *) pos;
Behdad Esfahbode62df432011-08-03 17:38:54 -0400210}
211
Behdad Esfahbod3567b872010-05-14 23:28:44 -0400212
Behdad Esfahbod69cc4922012-07-31 14:51:36 -0400213
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400214/* HarfBuzz-Internal API */
215
216void
217hb_buffer_t::reset (void)
218{
219 if (unlikely (hb_object_is_inert (this)))
220 return;
221
222 hb_unicode_funcs_destroy (unicode);
Behdad Esfahbodd5045a52012-08-11 21:26:25 -0400223 unicode = hb_unicode_funcs_get_default ();
Behdad Esfahbodb5fbc3b2014-08-11 18:40:01 -0400224 flags = HB_BUFFER_FLAG_DEFAULT;
Behdad Esfahbod976c8f42014-07-16 15:34:20 -0400225 replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400226
Behdad Esfahbod82ecaff2012-11-13 13:57:52 -0800227 clear ();
228}
229
230void
231hb_buffer_t::clear (void)
232{
233 if (unlikely (hb_object_is_inert (this)))
234 return;
235
Behdad Esfahbodf3064102012-11-15 18:39:46 -0800236 hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
Behdad Esfahbodf06ab8a2012-06-05 12:31:51 -0400237 props = default_props;
Behdad Esfahbod49ef6302015-11-04 17:27:07 -0800238 scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400239
Behdad Esfahbod96fdc042012-09-06 22:26:16 -0400240 content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
Behdad Esfahbod0594a242012-06-05 20:35:40 -0400241 in_error = false;
242 have_output = false;
243 have_positions = false;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400244
245 idx = 0;
246 len = 0;
247 out_len = 0;
Behdad Esfahbod47ef9312012-07-19 20:52:44 -0400248 out_info = info;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400249
250 serial = 0;
Behdad Esfahbod05207a72012-09-25 17:44:53 -0400251
252 memset (context, 0, sizeof context);
253 memset (context_len, 0, sizeof context_len);
Behdad Esfahbod98816502016-02-25 12:23:02 +0900254
255 deallocate_var_all ();
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400256}
257
258void
259hb_buffer_t::add (hb_codepoint_t codepoint,
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400260 unsigned int cluster)
261{
262 hb_glyph_info_t *glyph;
263
264 if (unlikely (!ensure (len + 1))) return;
265
266 glyph = &info[len];
267
268 memset (glyph, 0, sizeof (*glyph));
269 glyph->codepoint = codepoint;
Behdad Esfahbod66ac2ff2012-11-13 16:26:32 -0800270 glyph->mask = 1;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400271 glyph->cluster = cluster;
272
273 len++;
274}
275
276void
Behdad Esfahbod847794e2013-02-27 17:59:28 -0500277hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info)
278{
279 if (unlikely (!ensure (len + 1))) return;
280
281 info[len] = glyph_info;
282
283 len++;
284}
285
286
287void
Behdad Esfahbod0bc7a382012-10-29 22:02:45 -0700288hb_buffer_t::remove_output (void)
289{
290 if (unlikely (hb_object_is_inert (this)))
291 return;
292
293 have_output = false;
294 have_positions = false;
295
296 out_len = 0;
297 out_info = info;
298}
299
300void
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400301hb_buffer_t::clear_output (void)
302{
303 if (unlikely (hb_object_is_inert (this)))
304 return;
305
Behdad Esfahbod0594a242012-06-05 20:35:40 -0400306 have_output = true;
307 have_positions = false;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400308
309 out_len = 0;
310 out_info = info;
311}
312
313void
314hb_buffer_t::clear_positions (void)
315{
316 if (unlikely (hb_object_is_inert (this)))
317 return;
318
Behdad Esfahbod0594a242012-06-05 20:35:40 -0400319 have_output = false;
320 have_positions = true;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400321
Behdad Esfahbod47ef9312012-07-19 20:52:44 -0400322 out_len = 0;
323 out_info = info;
324
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400325 memset (pos, 0, sizeof (pos[0]) * len);
326}
327
328void
329hb_buffer_t::swap_buffers (void)
330{
331 if (unlikely (in_error)) return;
332
333 assert (have_output);
Behdad Esfahbod0594a242012-06-05 20:35:40 -0400334 have_output = false;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400335
336 if (out_info != info)
337 {
338 hb_glyph_info_t *tmp_string;
339 tmp_string = info;
340 info = out_info;
341 out_info = tmp_string;
342 pos = (hb_glyph_position_t *) out_info;
343 }
344
345 unsigned int tmp;
346 tmp = len;
347 len = out_len;
348 out_len = tmp;
349
350 idx = 0;
351}
352
Behdad Esfahbod69cc4922012-07-31 14:51:36 -0400353
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400354void
Behdad Esfahbod9ebe8c02011-08-26 09:29:42 +0200355hb_buffer_t::replace_glyphs (unsigned int num_in,
356 unsigned int num_out,
Behdad Esfahbod8e3715f2012-04-23 22:18:54 -0400357 const uint32_t *glyph_data)
Behdad Esfahbod9ebe8c02011-08-26 09:29:42 +0200358{
Behdad Esfahbod18e1c6b2015-11-19 11:50:58 -0800359 if (unlikely (!make_room_for (num_in, num_out))) return;
Behdad Esfahbod9ebe8c02011-08-26 09:29:42 +0200360
Behdad Esfahbode88e1442012-06-08 20:55:21 -0400361 merge_clusters (idx, idx + num_in);
Behdad Esfahbod9ebe8c02011-08-26 09:29:42 +0200362
Behdad Esfahbode88e1442012-06-08 20:55:21 -0400363 hb_glyph_info_t orig_info = info[idx];
Behdad Esfahbod9ebe8c02011-08-26 09:29:42 +0200364 hb_glyph_info_t *pinfo = &out_info[out_len];
365 for (unsigned int i = 0; i < num_out; i++)
366 {
367 *pinfo = orig_info;
368 pinfo->codepoint = glyph_data[i];
369 pinfo++;
370 }
371
Behdad Esfahbod68b507a2015-11-06 00:09:26 -0800372 idx += num_in;
Behdad Esfahbod18e1c6b2015-11-19 11:50:58 -0800373 out_len += num_out;
Behdad Esfahbod9ebe8c02011-08-26 09:29:42 +0200374}
375
376void
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400377hb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
378{
Behdad Esfahbod18e1c6b2015-11-19 11:50:58 -0800379 if (unlikely (!make_room_for (0, 1))) return;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400380
381 out_info[out_len] = info[idx];
382 out_info[out_len].codepoint = glyph_index;
383
384 out_len++;
385}
386
387void
Behdad Esfahbod847794e2013-02-27 17:59:28 -0500388hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info)
Behdad Esfahbodb85800f2012-08-31 18:12:01 -0400389{
Behdad Esfahbod18e1c6b2015-11-19 11:50:58 -0800390 if (unlikely (!make_room_for (0, 1))) return;
Behdad Esfahbodb85800f2012-08-31 18:12:01 -0400391
392 out_info[out_len] = glyph_info;
393
394 out_len++;
395}
396
397void
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400398hb_buffer_t::copy_glyph (void)
399{
Behdad Esfahbod18e1c6b2015-11-19 11:50:58 -0800400 if (unlikely (!make_room_for (0, 1))) return;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400401
402 out_info[out_len] = info[idx];
403
404 out_len++;
405}
406
Behdad Esfahbod6b65a762013-10-14 18:51:39 +0200407bool
408hb_buffer_t::move_to (unsigned int i)
409{
410 if (!have_output)
411 {
412 assert (i <= len);
413 idx = i;
Behdad Esfahbodda720422013-10-17 12:01:50 +0200414 return true;
Behdad Esfahbod6b65a762013-10-14 18:51:39 +0200415 }
Behdad Esfahbodb87e36f2016-02-19 14:52:31 +0700416 if (unlikely (in_error))
417 return false;
Behdad Esfahbodda720422013-10-17 12:01:50 +0200418
419 assert (i <= out_len + (len - idx));
420
421 if (out_len < i)
Behdad Esfahbod6b65a762013-10-14 18:51:39 +0200422 {
423 unsigned int count = i - out_len;
Behdad Esfahbod18e1c6b2015-11-19 11:50:58 -0800424 if (unlikely (!make_room_for (count, count))) return false;
Behdad Esfahbod6b65a762013-10-14 18:51:39 +0200425
426 memmove (out_info + out_len, info + idx, count * sizeof (out_info[0]));
427 idx += count;
428 out_len += count;
429 }
430 else if (out_len > i)
431 {
432 /* Tricky part: rewinding... */
433 unsigned int count = out_len - i;
434
Behdad Esfahbod6363d7d2016-07-20 01:43:56 -0700435 /* This will blow in our face if memory allocation fails later
436 * in this same lookup... */
Behdad Esfahbod6b65a762013-10-14 18:51:39 +0200437 if (unlikely (idx < count && !shift_forward (count + 32))) return false;
438
439 assert (idx >= count);
440
441 idx -= count;
442 out_len -= count;
443 memmove (info + idx, out_info + out_len, count * sizeof (out_info[0]));
444 }
Behdad Esfahbodda720422013-10-17 12:01:50 +0200445
Behdad Esfahbod6b65a762013-10-14 18:51:39 +0200446 return true;
447}
448
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400449void
450hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
451{
Behdad Esfahbod69cc4922012-07-31 14:51:36 -0400452 if (unlikely (out_info != info || out_len != idx)) {
Behdad Esfahbod18e1c6b2015-11-19 11:50:58 -0800453 if (unlikely (!make_room_for (1, 1))) return;
Behdad Esfahbod69cc4922012-07-31 14:51:36 -0400454 out_info[out_len] = info[idx];
455 }
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400456 out_info[out_len].codepoint = glyph_index;
457
Behdad Esfahbod68b507a2015-11-06 00:09:26 -0800458 idx++;
Behdad Esfahbod18e1c6b2015-11-19 11:50:58 -0800459 out_len++;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400460}
461
Behdad Esfahbod69cc4922012-07-31 14:51:36 -0400462
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400463void
464hb_buffer_t::set_masks (hb_mask_t value,
465 hb_mask_t mask,
466 unsigned int cluster_start,
467 unsigned int cluster_end)
468{
469 hb_mask_t not_mask = ~mask;
470 value &= mask;
471
472 if (!mask)
473 return;
474
475 if (cluster_start == 0 && cluster_end == (unsigned int)-1) {
476 unsigned int count = len;
477 for (unsigned int i = 0; i < count; i++)
478 info[i].mask = (info[i].mask & not_mask) | value;
479 return;
480 }
481
482 unsigned int count = len;
483 for (unsigned int i = 0; i < count; i++)
484 if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end)
485 info[i].mask = (info[i].mask & not_mask) | value;
486}
487
488void
489hb_buffer_t::reverse_range (unsigned int start,
490 unsigned int end)
491{
492 unsigned int i, j;
493
Behdad Esfahbod9e401f62015-03-20 16:08:38 -0400494 if (end - start < 2)
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400495 return;
496
497 for (i = start, j = end - 1; i < j; i++, j--) {
498 hb_glyph_info_t t;
499
500 t = info[i];
501 info[i] = info[j];
502 info[j] = t;
503 }
504
Behdad Esfahbod8ac345e2015-03-02 16:06:55 -0800505 if (have_positions) {
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400506 for (i = start, j = end - 1; i < j; i++, j--) {
507 hb_glyph_position_t t;
508
509 t = pos[i];
510 pos[i] = pos[j];
511 pos[j] = t;
512 }
513 }
514}
515
516void
517hb_buffer_t::reverse (void)
518{
519 if (unlikely (!len))
520 return;
521
522 reverse_range (0, len);
523}
524
525void
526hb_buffer_t::reverse_clusters (void)
527{
528 unsigned int i, start, count, last_cluster;
529
530 if (unlikely (!len))
531 return;
532
533 reverse ();
534
535 count = len;
536 start = 0;
537 last_cluster = info[0].cluster;
538 for (i = 1; i < count; i++) {
539 if (last_cluster != info[i].cluster) {
540 reverse_range (start, i);
541 start = i;
542 last_cluster = info[i].cluster;
543 }
544 }
545 reverse_range (start, i);
546}
547
Behdad Esfahbod02aeca92011-08-04 22:31:05 -0400548void
Behdad Esfahbod701112d2015-07-22 15:42:20 +0100549hb_buffer_t::merge_clusters_impl (unsigned int start,
550 unsigned int end)
Behdad Esfahbodd4cc4472012-04-07 21:52:28 -0400551{
Behdad Esfahbod376d5872015-07-22 16:51:12 +0100552 if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
553 return;
Behdad Esfahbod66c6a482014-04-14 15:55:42 -0700554
Behdad Esfahbodcafa6f32012-06-08 20:17:10 -0400555 unsigned int cluster = info[start].cluster;
Behdad Esfahbodd4cc4472012-04-07 21:52:28 -0400556
557 for (unsigned int i = start + 1; i < end; i++)
Behdad Esfahbodcafa6f32012-06-08 20:17:10 -0400558 cluster = MIN (cluster, info[i].cluster);
559
560 /* Extend end */
561 while (end < len && info[end - 1].cluster == info[end].cluster)
562 end++;
563
Behdad Esfahbodcd589142012-06-08 20:27:53 -0400564 /* Extend start */
565 while (idx < start && info[start - 1].cluster == info[start].cluster)
566 start--;
567
568 /* If we hit the start of buffer, continue in out-buffer. */
569 if (idx == start)
Behdad Esfahbod5f13bbd2015-06-19 13:31:49 -0700570 for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--)
Behdad Esfahbodcd589142012-06-08 20:27:53 -0400571 out_info[i - 1].cluster = cluster;
572
Behdad Esfahbodd4cc4472012-04-07 21:52:28 -0400573 for (unsigned int i = start; i < end; i++)
Behdad Esfahbodcafa6f32012-06-08 20:17:10 -0400574 info[i].cluster = cluster;
Behdad Esfahbodd4cc4472012-04-07 21:52:28 -0400575}
576void
577hb_buffer_t::merge_out_clusters (unsigned int start,
578 unsigned int end)
579{
Behdad Esfahbod376d5872015-07-22 16:51:12 +0100580 if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
581 return;
Behdad Esfahbod66c6a482014-04-14 15:55:42 -0700582
Behdad Esfahbodfe3dabc2012-06-08 20:56:05 -0400583 if (unlikely (end - start < 2))
Behdad Esfahbod72c0a182012-06-08 20:30:03 -0400584 return;
585
Behdad Esfahbodcafa6f32012-06-08 20:17:10 -0400586 unsigned int cluster = out_info[start].cluster;
Behdad Esfahbodd4cc4472012-04-07 21:52:28 -0400587
588 for (unsigned int i = start + 1; i < end; i++)
Behdad Esfahbodcafa6f32012-06-08 20:17:10 -0400589 cluster = MIN (cluster, out_info[i].cluster);
Behdad Esfahbod72c0a182012-06-08 20:30:03 -0400590
591 /* Extend start */
592 while (start && out_info[start - 1].cluster == out_info[start].cluster)
593 start--;
594
Behdad Esfahbod5ced0122012-06-08 20:31:32 -0400595 /* Extend end */
596 while (end < out_len && out_info[end - 1].cluster == out_info[end].cluster)
597 end++;
598
Behdad Esfahbode51d2b62012-06-08 20:33:27 -0400599 /* If we hit the end of out-buffer, continue in buffer. */
600 if (end == out_len)
Behdad Esfahbod5f13bbd2015-06-19 13:31:49 -0700601 for (unsigned int i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++)
Behdad Esfahbode51d2b62012-06-08 20:33:27 -0400602 info[i].cluster = cluster;
603
Behdad Esfahbodd4cc4472012-04-07 21:52:28 -0400604 for (unsigned int i = start; i < end; i++)
Behdad Esfahbodcafa6f32012-06-08 20:17:10 -0400605 out_info[i].cluster = cluster;
Behdad Esfahbodd4cc4472012-04-07 21:52:28 -0400606}
Behdad Esfahbod5f13bbd2015-06-19 13:31:49 -0700607void
608hb_buffer_t::delete_glyph ()
609{
610 unsigned int cluster = info[idx].cluster;
611 if (idx + 1 < len && cluster == info[idx + 1].cluster)
612 {
613 /* Cluster survives; do nothing. */
614 goto done;
615 }
616
617 if (out_len)
618 {
619 /* Merge cluster backward. */
620 if (cluster < out_info[out_len - 1].cluster)
621 {
622 unsigned int old_cluster = out_info[out_len - 1].cluster;
623 for (unsigned i = out_len; i && out_info[i - 1].cluster == old_cluster; i--)
624 out_info[i - 1].cluster = cluster;
625 }
626 goto done;
627 }
628
629 if (idx + 1 < len)
630 {
631 /* Merge cluster forward. */
632 merge_clusters (idx, idx + 2);
633 goto done;
634 }
635
636done:
637 skip_glyph ();
638}
Behdad Esfahbodd4cc4472012-04-07 21:52:28 -0400639
640void
Behdad Esfahbod3f82f8f2012-11-15 18:45:31 -0800641hb_buffer_t::guess_segment_properties (void)
Behdad Esfahbod02aeca92011-08-04 22:31:05 -0400642{
Behdad Esfahbod8465a052012-11-30 08:46:43 +0200643 assert (content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
644 (!len && content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
Behdad Esfahbod96fdc042012-09-06 22:26:16 -0400645
Behdad Esfahbod02aeca92011-08-04 22:31:05 -0400646 /* If script is set to INVALID, guess from buffer contents */
647 if (props.script == HB_SCRIPT_INVALID) {
648 for (unsigned int i = 0; i < len; i++) {
Behdad Esfahbod208f70f2012-08-01 17:13:10 -0400649 hb_script_t script = unicode->script (info[i].codepoint);
Behdad Esfahbod02aeca92011-08-04 22:31:05 -0400650 if (likely (script != HB_SCRIPT_COMMON &&
651 script != HB_SCRIPT_INHERITED &&
652 script != HB_SCRIPT_UNKNOWN)) {
653 props.script = script;
654 break;
655 }
656 }
657 }
658
659 /* If direction is set to INVALID, guess from script */
660 if (props.direction == HB_DIRECTION_INVALID) {
661 props.direction = hb_script_get_horizontal_direction (props.script);
662 }
663
664 /* If language is not set, use default language from locale */
665 if (props.language == HB_LANGUAGE_INVALID) {
666 /* TODO get_default_for_script? using $LANGUAGE */
667 props.language = hb_language_get_default ();
668 }
669}
670
671
Behdad Esfahbod6b347132007-10-11 08:30:50 +0000672/* Public API */
673
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400674/**
Behdad Esfahbod085d4292013-09-12 17:14:33 -0400675 * hb_buffer_create: (Xconstructor)
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400676 *
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400677 * Creates a new #hb_buffer_t with all properties to defaults.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400678 *
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400679 * Return value: (transfer full):
680 * A newly allocated #hb_buffer_t with a reference count of 1. The initial
Khaled Hosny9cffe322015-12-30 22:50:08 +0400681 * reference count should be released with hb_buffer_destroy() when you are done
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400682 * using the #hb_buffer_t. This function never returns %NULL. If memory cannot
683 * be allocated, a special #hb_buffer_t object will be returned on which
684 * hb_buffer_allocation_successful() returns %false.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400685 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +0430686 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400687 **/
Behdad Esfahbodb857b492009-05-20 05:35:14 -0400688hb_buffer_t *
Behdad Esfahbodc54599a2012-11-15 16:14:23 -0800689hb_buffer_create (void)
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000690{
Behdad Esfahbodb857b492009-05-20 05:35:14 -0400691 hb_buffer_t *buffer;
692
Behdad Esfahbod47e71d92011-04-27 16:38:03 -0400693 if (!(buffer = hb_object_create<hb_buffer_t> ()))
Behdad Esfahbodf06ab8a2012-06-05 12:31:51 -0400694 return hb_buffer_get_empty ();
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000695
Behdad Esfahbod43017032015-11-05 23:44:59 -0800696 buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
697
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400698 buffer->reset ();
Behdad Esfahbod5ebabec2009-11-03 15:15:07 -0500699
Behdad Esfahbodb857b492009-05-20 05:35:14 -0400700 return buffer;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000701}
702
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400703/**
704 * hb_buffer_get_empty:
705 *
706 *
707 *
708 * Return value: (transfer full):
709 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +0430710 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400711 **/
Behdad Esfahbod11fbb542009-08-01 22:19:06 -0400712hb_buffer_t *
Behdad Esfahbod80a68332011-05-11 18:14:44 -0400713hb_buffer_get_empty (void)
714{
Behdad Esfahbodf06ab8a2012-06-05 12:31:51 -0400715 static const hb_buffer_t _hb_buffer_nil = {
716 HB_OBJECT_HEADER_STATIC,
717
Behdad Esfahbodd5045a52012-08-11 21:26:25 -0400718 const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
Behdad Esfahbod4dc798d2013-08-26 20:39:00 -0400719 HB_BUFFER_FLAG_DEFAULT,
Behdad Esfahbod376d5872015-07-22 16:51:12 +0100720 HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
Behdad Esfahbod976c8f42014-07-16 15:34:20 -0400721 HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
Behdad Esfahbod49ef6302015-11-04 17:27:07 -0800722 HB_BUFFER_SCRATCH_FLAG_DEFAULT,
Behdad Esfahbod43017032015-11-05 23:44:59 -0800723 HB_BUFFER_MAX_LEN_DEFAULT,
Behdad Esfahbodf06ab8a2012-06-05 12:31:51 -0400724
Behdad Esfahbod96fdc042012-09-06 22:26:16 -0400725 HB_BUFFER_CONTENT_TYPE_INVALID,
Behdad Esfahbodb5fbc3b2014-08-11 18:40:01 -0400726 HB_SEGMENT_PROPERTIES_DEFAULT,
Behdad Esfahbod0594a242012-06-05 20:35:40 -0400727 true, /* in_error */
728 true, /* have_output */
729 true /* have_positions */
Behdad Esfahbod05207a72012-09-25 17:44:53 -0400730
731 /* Zero is good enough for everything else. */
Behdad Esfahbodf06ab8a2012-06-05 12:31:51 -0400732 };
733
734 return const_cast<hb_buffer_t *> (&_hb_buffer_nil);
Behdad Esfahbod80a68332011-05-11 18:14:44 -0400735}
736
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400737/**
738 * hb_buffer_reference: (skip)
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400739 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400740 *
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400741 * Increases the reference count on @buffer by one. This prevents @buffer from
742 * being destroyed until a matching call to hb_buffer_destroy() is made.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400743 *
744 * Return value: (transfer full):
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400745 * The referenced #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400746 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +0430747 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400748 **/
Behdad Esfahbod80a68332011-05-11 18:14:44 -0400749hb_buffer_t *
Behdad Esfahbod11fbb542009-08-01 22:19:06 -0400750hb_buffer_reference (hb_buffer_t *buffer)
Behdad Esfahbod7a268642007-10-11 07:21:31 +0000751{
Behdad Esfahbod47e71d92011-04-27 16:38:03 -0400752 return hb_object_reference (buffer);
Behdad Esfahbod11fbb542009-08-01 22:19:06 -0400753}
754
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400755/**
756 * hb_buffer_destroy: (skip)
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400757 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400758 *
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400759 * Deallocate the @buffer.
760 * Decreases the reference count on @buffer by one. If the result is zero, then
761 * @buffer and all associated resources are freed. See hb_buffer_reference().
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400762 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +0430763 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400764 **/
Behdad Esfahbod11fbb542009-08-01 22:19:06 -0400765void
766hb_buffer_destroy (hb_buffer_t *buffer)
767{
Behdad Esfahbod47e71d92011-04-27 16:38:03 -0400768 if (!hb_object_destroy (buffer)) return;
Behdad Esfahbod11fbb542009-08-01 22:19:06 -0400769
Behdad Esfahbod5ebabec2009-11-03 15:15:07 -0500770 hb_unicode_funcs_destroy (buffer->unicode);
771
Behdad Esfahbod7e7007a2010-05-14 22:02:37 -0400772 free (buffer->info);
Behdad Esfahbod1b621822010-05-14 22:05:53 -0400773 free (buffer->pos);
Behdad Esfahbod0475ef22015-12-18 18:17:07 +0000774 if (buffer->message_destroy)
775 buffer->message_destroy (buffer->message_data);
Behdad Esfahbod11fbb542009-08-01 22:19:06 -0400776
Behdad Esfahbodb857b492009-05-20 05:35:14 -0400777 free (buffer);
Behdad Esfahbod7a268642007-10-11 07:21:31 +0000778}
779
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400780/**
781 * hb_buffer_set_user_data: (skip)
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400782 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400783 * @key:
784 * @data:
785 * @destroy:
786 * @replace:
787 *
788 *
789 *
790 * Return value:
791 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +0430792 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400793 **/
Behdad Esfahbod5fa849b2011-04-27 21:46:01 -0400794hb_bool_t
795hb_buffer_set_user_data (hb_buffer_t *buffer,
796 hb_user_data_key_t *key,
797 void * data,
Behdad Esfahbod33ccc772011-08-09 00:43:24 +0200798 hb_destroy_func_t destroy,
799 hb_bool_t replace)
Behdad Esfahbod5fa849b2011-04-27 21:46:01 -0400800{
Behdad Esfahbod33ccc772011-08-09 00:43:24 +0200801 return hb_object_set_user_data (buffer, key, data, destroy, replace);
Behdad Esfahbod5fa849b2011-04-27 21:46:01 -0400802}
803
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400804/**
805 * hb_buffer_get_user_data: (skip)
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400806 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400807 * @key:
808 *
809 *
810 *
811 * Return value:
812 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +0430813 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400814 **/
Behdad Esfahbod5fa849b2011-04-27 21:46:01 -0400815void *
816hb_buffer_get_user_data (hb_buffer_t *buffer,
817 hb_user_data_key_t *key)
818{
819 return hb_object_get_user_data (buffer, key);
820}
821
Behdad Esfahbod5ebabec2009-11-03 15:15:07 -0500822
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400823/**
824 * hb_buffer_set_content_type:
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400825 * @buffer: an #hb_buffer_t.
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400826 * @content_type: the type of buffer contents to set
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400827 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400828 * Sets the type of @buffer contents, buffers are either empty, contain
829 * characters (before shaping) or glyphs (the result of shaping).
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400830 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200831 * Since: 0.9.5
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400832 **/
Behdad Esfahbod5ebabec2009-11-03 15:15:07 -0500833void
Behdad Esfahbod96fdc042012-09-06 22:26:16 -0400834hb_buffer_set_content_type (hb_buffer_t *buffer,
835 hb_buffer_content_type_t content_type)
836{
837 buffer->content_type = content_type;
838}
839
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400840/**
841 * hb_buffer_get_content_type:
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400842 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400843 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400844 * see hb_buffer_set_content_type().
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400845 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400846 * Return value:
847 * The type of @buffer contents.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400848 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200849 * Since: 0.9.5
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400850 **/
Behdad Esfahbod96fdc042012-09-06 22:26:16 -0400851hb_buffer_content_type_t
852hb_buffer_get_content_type (hb_buffer_t *buffer)
853{
854 return buffer->content_type;
855}
856
857
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400858/**
859 * hb_buffer_set_unicode_funcs:
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400860 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400861 * @unicode_funcs:
862 *
863 *
864 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +0430865 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400866 **/
Behdad Esfahbod96fdc042012-09-06 22:26:16 -0400867void
Behdad Esfahbod5ebabec2009-11-03 15:15:07 -0500868hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400869 hb_unicode_funcs_t *unicode_funcs)
Behdad Esfahbod5ebabec2009-11-03 15:15:07 -0500870{
Behdad Esfahbode0db4b82011-04-28 12:56:49 -0400871 if (unlikely (hb_object_is_inert (buffer)))
872 return;
873
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400874 if (!unicode_funcs)
875 unicode_funcs = hb_unicode_funcs_get_default ();
Behdad Esfahbodd5045a52012-08-11 21:26:25 -0400876
Behdad Esfahbod0465e692009-12-20 16:25:18 +0100877
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400878 hb_unicode_funcs_reference (unicode_funcs);
Behdad Esfahbod5ebabec2009-11-03 15:15:07 -0500879 hb_unicode_funcs_destroy (buffer->unicode);
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400880 buffer->unicode = unicode_funcs;
Behdad Esfahbod5ebabec2009-11-03 15:15:07 -0500881}
882
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400883/**
884 * hb_buffer_get_unicode_funcs:
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400885 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400886 *
887 *
888 *
889 * Return value:
890 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +0430891 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400892 **/
Behdad Esfahbod5ebabec2009-11-03 15:15:07 -0500893hb_unicode_funcs_t *
894hb_buffer_get_unicode_funcs (hb_buffer_t *buffer)
895{
896 return buffer->unicode;
897}
898
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400899/**
900 * hb_buffer_set_direction:
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400901 * @buffer: an #hb_buffer_t.
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400902 * @direction: the #hb_direction_t of the @buffer
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400903 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400904 * Set the text flow direction of the buffer. No shaping can happen without
905 * setting @buffer direction, and it controls the visual direction for the
906 * output glyphs; for RTL direction the glyphs will be reversed. Many layout
907 * features depend on the proper setting of the direction, for example,
908 * reversing RTL text before shaping, then shaping with LTR direction is not
909 * the same as keeping the text in logical order and shaping with RTL
910 * direction.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400911 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +0430912 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400913 **/
Behdad Esfahbod5ebabec2009-11-03 15:15:07 -0500914void
915hb_buffer_set_direction (hb_buffer_t *buffer,
916 hb_direction_t direction)
917
918{
Behdad Esfahbode0db4b82011-04-28 12:56:49 -0400919 if (unlikely (hb_object_is_inert (buffer)))
920 return;
921
Behdad Esfahbod4e4ef242010-07-23 17:22:11 -0400922 buffer->props.direction = direction;
Behdad Esfahbod5ebabec2009-11-03 15:15:07 -0500923}
924
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400925/**
926 * hb_buffer_get_direction:
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400927 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400928 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400929 * See hb_buffer_set_direction()
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400930 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400931 * Return value:
932 * The direction of the @buffer.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400933 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +0430934 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400935 **/
Behdad Esfahbod5ebabec2009-11-03 15:15:07 -0500936hb_direction_t
937hb_buffer_get_direction (hb_buffer_t *buffer)
938{
Behdad Esfahbod4e4ef242010-07-23 17:22:11 -0400939 return buffer->props.direction;
Behdad Esfahbod5ebabec2009-11-03 15:15:07 -0500940}
941
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400942/**
943 * hb_buffer_set_script:
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400944 * @buffer: an #hb_buffer_t.
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400945 * @script: an #hb_script_t to set.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400946 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400947 * Sets the script of @buffer to @script.
948 *
949 * Script is crucial for choosing the proper shaping behaviour for scripts that
950 * require it (e.g. Arabic) and the which OpenType features defined in the font
951 * to be applied.
952 *
953 * You can pass one of the predefined #hb_script_t values, or use
954 * hb_script_from_string() or hb_script_from_iso15924_tag() to get the
955 * corresponding script from an ISO 15924 script tag.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400956 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +0430957 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400958 **/
Behdad Esfahbodae070b72009-11-04 20:29:54 -0500959void
960hb_buffer_set_script (hb_buffer_t *buffer,
961 hb_script_t script)
962{
Behdad Esfahbode0db4b82011-04-28 12:56:49 -0400963 if (unlikely (hb_object_is_inert (buffer)))
964 return;
965
Behdad Esfahbod4e4ef242010-07-23 17:22:11 -0400966 buffer->props.script = script;
Behdad Esfahbodae070b72009-11-04 20:29:54 -0500967}
968
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400969/**
970 * hb_buffer_get_script:
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400971 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400972 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400973 * See hb_buffer_set_script().
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400974 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400975 * Return value:
976 * The #hb_script_t of the @buffer.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400977 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +0430978 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400979 **/
Behdad Esfahbodae070b72009-11-04 20:29:54 -0500980hb_script_t
981hb_buffer_get_script (hb_buffer_t *buffer)
982{
Behdad Esfahbod4e4ef242010-07-23 17:22:11 -0400983 return buffer->props.script;
Behdad Esfahbodae070b72009-11-04 20:29:54 -0500984}
985
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400986/**
987 * hb_buffer_set_language:
Khaled Hosnyf18d2222015-12-29 15:21:20 +0400988 * @buffer: an #hb_buffer_t.
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400989 * @language: an hb_language_t to set.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400990 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +0400991 * Sets the language of @buffer to @language.
992 *
993 * Languages are crucial for selecting which OpenType feature to apply to the
994 * buffer which can result in applying language-specific behaviour. Languages
995 * are orthogonal to the scripts, and though they are related, they are
996 * different concepts and should not be confused with each other.
997 *
998 * Use hb_language_from_string() to convert from ISO 639 language codes to
999 * #hb_language_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001000 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301001 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001002 **/
Behdad Esfahbodae070b72009-11-04 20:29:54 -05001003void
1004hb_buffer_set_language (hb_buffer_t *buffer,
1005 hb_language_t language)
1006{
Behdad Esfahbode0db4b82011-04-28 12:56:49 -04001007 if (unlikely (hb_object_is_inert (buffer)))
1008 return;
1009
Behdad Esfahbod4e4ef242010-07-23 17:22:11 -04001010 buffer->props.language = language;
Behdad Esfahbodae070b72009-11-04 20:29:54 -05001011}
1012
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001013/**
1014 * hb_buffer_get_language:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001015 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001016 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +04001017 * See hb_buffer_set_language().
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001018 *
Khaled Hosny04f89e82015-04-10 17:49:01 +02001019 * Return value: (transfer none):
Khaled Hosny8ab797c2015-12-29 17:42:16 +04001020 * The #hb_language_t of the buffer. Must not be freed by the caller.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001021 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301022 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001023 **/
Behdad Esfahbodae070b72009-11-04 20:29:54 -05001024hb_language_t
1025hb_buffer_get_language (hb_buffer_t *buffer)
1026{
Behdad Esfahbod4e4ef242010-07-23 17:22:11 -04001027 return buffer->props.language;
Behdad Esfahbodae070b72009-11-04 20:29:54 -05001028}
1029
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001030/**
1031 * hb_buffer_set_segment_properties:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001032 * @buffer: an #hb_buffer_t.
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001033 * @props: an #hb_segment_properties_t to use.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001034 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001035 * Sets the segment properties of the buffer, a shortcut for calling
1036 * hb_buffer_set_direction(), hb_buffer_set_script() and
1037 * hb_buffer_set_language() individually.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001038 *
Sascha Brawer01c3a882015-06-01 13:22:01 +02001039 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001040 **/
Behdad Esfahbod0c7df222012-11-13 14:42:35 -08001041void
Behdad Esfahbodf3064102012-11-15 18:39:46 -08001042hb_buffer_set_segment_properties (hb_buffer_t *buffer,
1043 const hb_segment_properties_t *props)
1044{
1045 if (unlikely (hb_object_is_inert (buffer)))
1046 return;
1047
1048 buffer->props = *props;
1049}
1050
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001051/**
1052 * hb_buffer_get_segment_properties:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001053 * @buffer: an #hb_buffer_t.
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001054 * @props: (out): the output #hb_segment_properties_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001055 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001056 * Sets @props to the #hb_segment_properties_t of @buffer.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001057 *
Sascha Brawer01c3a882015-06-01 13:22:01 +02001058 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001059 **/
Behdad Esfahbodf3064102012-11-15 18:39:46 -08001060void
1061hb_buffer_get_segment_properties (hb_buffer_t *buffer,
1062 hb_segment_properties_t *props)
1063{
1064 *props = buffer->props;
1065}
1066
1067
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001068/**
1069 * hb_buffer_set_flags:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001070 * @buffer: an #hb_buffer_t.
Khaled Hosnyfb192c22015-12-30 15:05:50 +04001071 * @flags: the buffer flags to set.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001072 *
Khaled Hosnyfb192c22015-12-30 15:05:50 +04001073 * Sets @buffer flags to @flags. See #hb_buffer_flags_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001074 *
Sascha Brawer01c3a882015-06-01 13:22:01 +02001075 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001076 **/
Behdad Esfahbodf3064102012-11-15 18:39:46 -08001077void
Behdad Esfahbod0c7df222012-11-13 14:42:35 -08001078hb_buffer_set_flags (hb_buffer_t *buffer,
1079 hb_buffer_flags_t flags)
1080{
1081 if (unlikely (hb_object_is_inert (buffer)))
1082 return;
1083
1084 buffer->flags = flags;
1085}
1086
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001087/**
1088 * hb_buffer_get_flags:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001089 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001090 *
Khaled Hosnyfb192c22015-12-30 15:05:50 +04001091 * See hb_buffer_set_flags().
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001092 *
1093 * Return value:
Khaled Hosnyfb192c22015-12-30 15:05:50 +04001094 * The @buffer flags.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001095 *
Sascha Brawer01c3a882015-06-01 13:22:01 +02001096 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001097 **/
Behdad Esfahbod0c7df222012-11-13 14:42:35 -08001098hb_buffer_flags_t
1099hb_buffer_get_flags (hb_buffer_t *buffer)
1100{
1101 return buffer->flags;
1102}
1103
Behdad Esfahbod376d5872015-07-22 16:51:12 +01001104/**
1105 * hb_buffer_set_cluster_level:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001106 * @buffer: an #hb_buffer_t.
Behdad Esfahbod376d5872015-07-22 16:51:12 +01001107 * @cluster_level:
1108 *
1109 *
1110 *
1111 * Since: 0.9.42
1112 **/
1113void
1114hb_buffer_set_cluster_level (hb_buffer_t *buffer,
1115 hb_buffer_cluster_level_t cluster_level)
1116{
1117 if (unlikely (hb_object_is_inert (buffer)))
1118 return;
1119
1120 buffer->cluster_level = cluster_level;
1121}
1122
1123/**
1124 * hb_buffer_get_cluster_level:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001125 * @buffer: an #hb_buffer_t.
Behdad Esfahbod376d5872015-07-22 16:51:12 +01001126 *
1127 *
1128 *
1129 * Return value:
1130 *
1131 * Since: 0.9.42
1132 **/
1133hb_buffer_cluster_level_t
1134hb_buffer_get_cluster_level (hb_buffer_t *buffer)
1135{
1136 return buffer->cluster_level;
1137}
1138
Behdad Esfahbod5ebabec2009-11-03 15:15:07 -05001139
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001140/**
Behdad Esfahbod976c8f42014-07-16 15:34:20 -04001141 * hb_buffer_set_replacement_codepoint:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001142 * @buffer: an #hb_buffer_t.
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001143 * @replacement: the replacement #hb_codepoint_t
Behdad Esfahbod976c8f42014-07-16 15:34:20 -04001144 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001145 * Sets the #hb_codepoint_t that replaces invalid entries for a given encoding
1146 * when adding text to @buffer.
1147 *
1148 * Default is %HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT.
Behdad Esfahbod976c8f42014-07-16 15:34:20 -04001149 *
Sascha Brawer01c3a882015-06-01 13:22:01 +02001150 * Since: 0.9.31
Behdad Esfahbod976c8f42014-07-16 15:34:20 -04001151 **/
1152void
1153hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
1154 hb_codepoint_t replacement)
1155{
1156 if (unlikely (hb_object_is_inert (buffer)))
1157 return;
1158
1159 buffer->replacement = replacement;
1160}
1161
1162/**
1163 * hb_buffer_get_replacement_codepoint:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001164 * @buffer: an #hb_buffer_t.
Behdad Esfahbod976c8f42014-07-16 15:34:20 -04001165 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001166 * See hb_buffer_set_replacement_codepoint().
Behdad Esfahbod976c8f42014-07-16 15:34:20 -04001167 *
1168 * Return value:
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001169 * The @buffer replacement #hb_codepoint_t.
Behdad Esfahbod976c8f42014-07-16 15:34:20 -04001170 *
Sascha Brawer01c3a882015-06-01 13:22:01 +02001171 * Since: 0.9.31
Behdad Esfahbod976c8f42014-07-16 15:34:20 -04001172 **/
1173hb_codepoint_t
1174hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer)
1175{
1176 return buffer->replacement;
1177}
1178
1179
1180/**
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001181 * hb_buffer_reset:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001182 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001183 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001184 * Resets the buffer to its initial status, as if it was just newly created
1185 * with hb_buffer_create().
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001186 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301187 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001188 **/
Behdad Esfahbod7a268642007-10-11 07:21:31 +00001189void
Behdad Esfahbodc910bec2011-04-13 15:49:06 -04001190hb_buffer_reset (hb_buffer_t *buffer)
1191{
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -04001192 buffer->reset ();
Behdad Esfahbod7a268642007-10-11 07:21:31 +00001193}
1194
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001195/**
1196 * hb_buffer_clear_contents:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001197 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001198 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001199 * Similar to hb_buffer_reset(), but does not clear the Unicode functions and
1200 * the replacement code point.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001201 *
Sascha Brawer01c3a882015-06-01 13:22:01 +02001202 * Since: 0.9.11
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001203 **/
Behdad Esfahbod82ecaff2012-11-13 13:57:52 -08001204void
Behdad Esfahbod1172dc72013-01-07 16:46:37 -06001205hb_buffer_clear_contents (hb_buffer_t *buffer)
Behdad Esfahbod82ecaff2012-11-13 13:57:52 -08001206{
1207 buffer->clear ();
1208}
1209
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001210/**
1211 * hb_buffer_pre_allocate:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001212 * @buffer: an #hb_buffer_t.
Khaled Hosny8ab797c2015-12-29 17:42:16 +04001213 * @size: number of items to pre allocate.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001214 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +04001215 * Pre allocates memory for @buffer to fit at least @size number of items.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001216 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +04001217 * Return value:
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001218 * %true if @buffer memory allocation succeeded, %false otherwise.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001219 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301220 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001221 **/
Behdad Esfahboda6a79df2010-05-14 23:20:16 -04001222hb_bool_t
Ryan Lortie02a534b2011-04-15 18:34:45 -04001223hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
Behdad Esfahbodf9cd1012009-07-28 15:43:34 -04001224{
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -04001225 return buffer->ensure (size);
Behdad Esfahbodf9cd1012009-07-28 15:43:34 -04001226}
1227
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001228/**
1229 * hb_buffer_allocation_successful:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001230 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001231 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +04001232 * Check if allocating memory for the buffer succeeded.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001233 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +04001234 * Return value:
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001235 * %true if @buffer memory allocation succeeded, %false otherwise.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001236 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301237 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001238 **/
Behdad Esfahbodaab0de52011-04-19 00:32:19 -04001239hb_bool_t
1240hb_buffer_allocation_successful (hb_buffer_t *buffer)
1241{
1242 return !buffer->in_error;
1243}
1244
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001245/**
1246 * hb_buffer_add:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001247 * @buffer: an #hb_buffer_t.
1248 * @codepoint: a Unicode code point.
1249 * @cluster: the cluster value of @codepoint.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001250 *
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001251 * Appends a character with the Unicode value of @codepoint to @buffer, and
1252 * gives it the initial cluster value of @cluster. Clusters can be any thing
1253 * the client wants, they are usually used to refer to the index of the
1254 * character in the input text stream and are output in
1255 * #hb_glyph_info_t.cluster field.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001256 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001257 * This function does not check the validity of @codepoint, it is up to the
1258 * caller to ensure it is a valid Unicode code point.
1259 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301260 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001261 **/
Behdad Esfahbodf9cd1012009-07-28 15:43:34 -04001262void
Behdad Esfahbodf85faee2011-04-19 00:38:01 -04001263hb_buffer_add (hb_buffer_t *buffer,
1264 hb_codepoint_t codepoint,
Behdad Esfahbodf85faee2011-04-19 00:38:01 -04001265 unsigned int cluster)
Behdad Esfahbod6b347132007-10-11 08:30:50 +00001266{
Behdad Esfahbod66ac2ff2012-11-13 16:26:32 -08001267 buffer->add (codepoint, cluster);
Behdad Esfahbod05207a72012-09-25 17:44:53 -04001268 buffer->clear_context (1);
Behdad Esfahbod6b347132007-10-11 08:30:50 +00001269}
1270
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001271/**
1272 * hb_buffer_set_length:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001273 * @buffer: an #hb_buffer_t.
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001274 * @length: the new length of @buffer.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001275 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001276 * Similar to hb_buffer_pre_allocate(), but clears any new items added at the
1277 * end.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001278 *
1279 * Return value:
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001280 * %true if @buffer memory allocation succeeded, %false otherwise.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001281 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301282 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001283 **/
Behdad Esfahbodc910bec2011-04-13 15:49:06 -04001284hb_bool_t
1285hb_buffer_set_length (hb_buffer_t *buffer,
1286 unsigned int length)
1287{
Behdad Esfahbode1ac38f2012-06-05 20:31:49 -04001288 if (unlikely (hb_object_is_inert (buffer)))
1289 return length == 0;
1290
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -04001291 if (!buffer->ensure (length))
Behdad Esfahbod0594a242012-06-05 20:35:40 -04001292 return false;
Behdad Esfahbodc910bec2011-04-13 15:49:06 -04001293
1294 /* Wipe the new space */
1295 if (length > buffer->len) {
1296 memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len));
1297 if (buffer->have_positions)
1298 memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len));
1299 }
1300
1301 buffer->len = length;
Behdad Esfahbod05207a72012-09-25 17:44:53 -04001302
1303 if (!length)
Behdad Esfahbod02c6c8c2013-11-15 13:05:38 -05001304 {
1305 buffer->content_type = HB_BUFFER_CONTENT_TYPE_INVALID;
Behdad Esfahbod05207a72012-09-25 17:44:53 -04001306 buffer->clear_context (0);
Behdad Esfahbod02c6c8c2013-11-15 13:05:38 -05001307 }
Behdad Esfahbod05207a72012-09-25 17:44:53 -04001308 buffer->clear_context (1);
1309
Behdad Esfahbod0594a242012-06-05 20:35:40 -04001310 return true;
Behdad Esfahbodc910bec2011-04-13 15:49:06 -04001311}
1312
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001313/**
1314 * hb_buffer_get_length:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001315 * @buffer: an #hb_buffer_t.
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001316 *
1317 * Returns the number of items in the buffer.
1318 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +04001319 * Return value:
1320 * The @buffer length.
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001321 * The value valid as long as buffer has not been modified.
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001322 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301323 * Since: 0.9.2
Behdad Esfahbodc44b8182013-09-06 15:13:16 -04001324 **/
Behdad Esfahbod11fbb542009-08-01 22:19:06 -04001325unsigned int
Behdad Esfahbod3d145282009-11-06 15:13:17 -05001326hb_buffer_get_length (hb_buffer_t *buffer)
Behdad Esfahbod11fbb542009-08-01 22:19:06 -04001327{
Behdad Esfahbod69603502010-05-14 22:07:46 -04001328 return buffer->len;
Behdad Esfahbod11fbb542009-08-01 22:19:06 -04001329}
1330
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001331/**
1332 * hb_buffer_get_glyph_infos:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001333 * @buffer: an #hb_buffer_t.
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001334 * @length: (out): output array length.
1335 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +04001336 * Returns @buffer glyph information array. Returned pointer
1337 * is valid as long as @buffer contents are not modified.
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001338 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +04001339 * Return value: (transfer none) (array length=length):
1340 * The @buffer glyph information array.
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001341 * The value valid as long as buffer has not been modified.
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001342 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301343 * Since: 0.9.2
Behdad Esfahbodc44b8182013-09-06 15:13:16 -04001344 **/
Behdad Esfahbod11fbb542009-08-01 22:19:06 -04001345hb_glyph_info_t *
Ryan Lortie70566be2011-04-15 18:32:36 -04001346hb_buffer_get_glyph_infos (hb_buffer_t *buffer,
1347 unsigned int *length)
Behdad Esfahbod11fbb542009-08-01 22:19:06 -04001348{
Ryan Lortie70566be2011-04-15 18:32:36 -04001349 if (length)
1350 *length = buffer->len;
1351
Behdad Esfahbod7e7007a2010-05-14 22:02:37 -04001352 return (hb_glyph_info_t *) buffer->info;
Behdad Esfahbod11fbb542009-08-01 22:19:06 -04001353}
1354
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001355/**
1356 * hb_buffer_get_glyph_positions:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001357 * @buffer: an #hb_buffer_t.
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001358 * @length: (out): output length.
1359 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +04001360 * Returns @buffer glyph position array. Returned pointer
1361 * is valid as long as @buffer contents are not modified.
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001362 *
Khaled Hosny8ab797c2015-12-29 17:42:16 +04001363 * Return value: (transfer none) (array length=length):
1364 * The @buffer glyph position array.
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001365 * The value valid as long as buffer has not been modified.
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001366 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301367 * Since: 0.9.2
Behdad Esfahbodc44b8182013-09-06 15:13:16 -04001368 **/
Behdad Esfahbod11fbb542009-08-01 22:19:06 -04001369hb_glyph_position_t *
Ryan Lortie70566be2011-04-15 18:32:36 -04001370hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
1371 unsigned int *length)
Behdad Esfahbod11fbb542009-08-01 22:19:06 -04001372{
Behdad Esfahbod314905d2009-12-20 14:50:42 +01001373 if (!buffer->have_positions)
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -04001374 buffer->clear_positions ();
Behdad Esfahbod11fbb542009-08-01 22:19:06 -04001375
Ryan Lortie70566be2011-04-15 18:32:36 -04001376 if (length)
1377 *length = buffer->len;
1378
Behdad Esfahbod1b621822010-05-14 22:05:53 -04001379 return (hb_glyph_position_t *) buffer->pos;
Behdad Esfahbod11fbb542009-08-01 22:19:06 -04001380}
Behdad Esfahbodfbaf8ff2009-08-10 20:59:25 -04001381
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001382/**
1383 * hb_buffer_reverse:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001384 * @buffer: an #hb_buffer_t.
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001385 *
1386 * Reverses buffer contents.
1387 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301388 * Since: 0.9.2
Behdad Esfahbodc44b8182013-09-06 15:13:16 -04001389 **/
Behdad Esfahbodff44f882009-11-06 19:48:16 -05001390void
1391hb_buffer_reverse (hb_buffer_t *buffer)
1392{
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -04001393 buffer->reverse ();
Behdad Esfahbodff44f882009-11-06 19:48:16 -05001394}
1395
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001396/**
Behdad Esfahbod81bedda2015-04-30 13:04:16 -04001397 * hb_buffer_reverse_range:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001398 * @buffer: an #hb_buffer_t.
Behdad Esfahbod81bedda2015-04-30 13:04:16 -04001399 * @start: start index.
1400 * @end: end index.
1401 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301402 * Reverses buffer contents between start to end.
Behdad Esfahbod81bedda2015-04-30 13:04:16 -04001403 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301404 * Since: 0.9.41
Behdad Esfahbod81bedda2015-04-30 13:04:16 -04001405 **/
1406void
1407hb_buffer_reverse_range (hb_buffer_t *buffer,
1408 unsigned int start, unsigned int end)
1409{
1410 buffer->reverse_range (start, end);
1411}
1412
1413/**
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001414 * hb_buffer_reverse_clusters:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001415 * @buffer: an #hb_buffer_t.
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001416 *
1417 * Reverses buffer clusters. That is, the buffer contents are
1418 * reversed, then each cluster (consecutive items having the
1419 * same cluster number) are reversed again.
1420 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301421 * Since: 0.9.2
Behdad Esfahbodc44b8182013-09-06 15:13:16 -04001422 **/
Behdad Esfahbodff44f882009-11-06 19:48:16 -05001423void
1424hb_buffer_reverse_clusters (hb_buffer_t *buffer)
1425{
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -04001426 buffer->reverse_clusters ();
Behdad Esfahbodff44f882009-11-06 19:48:16 -05001427}
1428
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001429/**
1430 * hb_buffer_guess_segment_properties:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001431 * @buffer: an #hb_buffer_t.
Behdad Esfahbod5f512012013-09-04 18:28:39 -04001432 *
1433 * Sets unset buffer segment properties based on buffer Unicode
1434 * contents. If buffer is not empty, it must have content type
1435 * %HB_BUFFER_CONTENT_TYPE_UNICODE.
1436 *
1437 * If buffer script is not set (ie. is %HB_SCRIPT_INVALID), it
1438 * will be set to the Unicode script of the first character in
1439 * the buffer that has a script other than %HB_SCRIPT_COMMON,
1440 * %HB_SCRIPT_INHERITED, and %HB_SCRIPT_UNKNOWN.
1441 *
1442 * Next, if buffer direction is not set (ie. is %HB_DIRECTION_INVALID),
1443 * it will be set to the natural horizontal direction of the
1444 * buffer script as returned by hb_script_get_horizontal_direction().
1445 *
1446 * Finally, if buffer language is not set (ie. is %HB_LANGUAGE_INVALID),
1447 * it will be set to the process's default language as returned by
1448 * hb_language_get_default(). This may change in the future by
1449 * taking buffer script into consideration when choosing a language.
1450 *
Sascha Brawer01c3a882015-06-01 13:22:01 +02001451 * Since: 0.9.7
Behdad Esfahbodc44b8182013-09-06 15:13:16 -04001452 **/
Behdad Esfahbod02aeca92011-08-04 22:31:05 -04001453void
Behdad Esfahbod3f82f8f2012-11-15 18:45:31 -08001454hb_buffer_guess_segment_properties (hb_buffer_t *buffer)
Behdad Esfahbod02aeca92011-08-04 22:31:05 -04001455{
Behdad Esfahbod3f82f8f2012-11-15 18:45:31 -08001456 buffer->guess_segment_properties ();
Behdad Esfahbod02aeca92011-08-04 22:31:05 -04001457}
1458
Behdad Esfahbod61820bc2015-01-26 14:25:52 -08001459template <typename utf_t>
Behdad Esfahbod7f19ae72012-09-25 11:22:28 -04001460static inline void
1461hb_buffer_add_utf (hb_buffer_t *buffer,
Behdad Esfahbod61820bc2015-01-26 14:25:52 -08001462 const typename utf_t::codepoint_t *text,
Behdad Esfahbod7f19ae72012-09-25 11:22:28 -04001463 int text_length,
1464 unsigned int item_offset,
1465 int item_length)
Behdad Esfahbod299f0892009-08-10 22:47:57 -04001466{
Behdad Esfahbod61820bc2015-01-26 14:25:52 -08001467 typedef typename utf_t::codepoint_t T;
Behdad Esfahbod976c8f42014-07-16 15:34:20 -04001468 const hb_codepoint_t replacement = buffer->replacement;
Behdad Esfahbod625dbf12014-07-16 14:49:55 -04001469
Behdad Esfahbod7f19ae72012-09-25 11:22:28 -04001470 assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
1471 (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
Behdad Esfahbod299f0892009-08-10 22:47:57 -04001472
Behdad Esfahbod7f19ae72012-09-25 11:22:28 -04001473 if (unlikely (hb_object_is_inert (buffer)))
1474 return;
Behdad Esfahbod2163afb2010-05-27 14:04:15 -04001475
Behdad Esfahbod1f66c3c2012-09-25 11:42:16 -04001476 if (text_length == -1)
Behdad Esfahbod625dbf12014-07-16 14:49:55 -04001477 text_length = utf_t::strlen (text);
Behdad Esfahbod7f19ae72012-09-25 11:22:28 -04001478
1479 if (item_length == -1)
1480 item_length = text_length - item_offset;
1481
1482 buffer->ensure (buffer->len + item_length * sizeof (T) / 4);
1483
Behdad Esfahbodda701112012-10-31 13:45:30 -07001484 /* If buffer is empty and pre-context provided, install it.
1485 * This check is written this way, to make sure people can
1486 * provide pre-context in one add_utf() call, then provide
1487 * text in a follow-up call. See:
1488 *
1489 * https://bugzilla.mozilla.org/show_bug.cgi?id=801410#c13
1490 */
1491 if (!buffer->len && item_offset > 0)
Behdad Esfahbod05207a72012-09-25 17:44:53 -04001492 {
1493 /* Add pre-context */
1494 buffer->clear_context (0);
1495 const T *prev = text + item_offset;
1496 const T *start = text;
1497 while (start < prev && buffer->context_len[0] < buffer->CONTEXT_LENGTH)
1498 {
1499 hb_codepoint_t u;
Behdad Esfahbod976c8f42014-07-16 15:34:20 -04001500 prev = utf_t::prev (prev, start, &u, replacement);
Behdad Esfahbod05207a72012-09-25 17:44:53 -04001501 buffer->context[0][buffer->context_len[0]++] = u;
1502 }
1503 }
1504
1505 const T *next = text + item_offset;
Behdad Esfahbod7f19ae72012-09-25 11:22:28 -04001506 const T *end = next + item_length;
Behdad Esfahbod05207a72012-09-25 17:44:53 -04001507 while (next < end)
1508 {
Behdad Esfahbod7f19ae72012-09-25 11:22:28 -04001509 hb_codepoint_t u;
1510 const T *old_next = next;
Behdad Esfahbod976c8f42014-07-16 15:34:20 -04001511 next = utf_t::next (next, end, &u, replacement);
Behdad Esfahbod66ac2ff2012-11-13 16:26:32 -08001512 buffer->add (u, old_next - (const T *) text);
Behdad Esfahbod05207a72012-09-25 17:44:53 -04001513 }
1514
1515 /* Add post-context */
1516 buffer->clear_context (1);
1517 end = text + text_length;
1518 while (next < end && buffer->context_len[1] < buffer->CONTEXT_LENGTH)
1519 {
1520 hb_codepoint_t u;
Behdad Esfahbod976c8f42014-07-16 15:34:20 -04001521 next = utf_t::next (next, end, &u, replacement);
Behdad Esfahbod05207a72012-09-25 17:44:53 -04001522 buffer->context[1][buffer->context_len[1]++] = u;
Behdad Esfahbod7f19ae72012-09-25 11:22:28 -04001523 }
1524
1525 buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE;
Behdad Esfahbod299f0892009-08-10 22:47:57 -04001526}
1527
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001528/**
1529 * hb_buffer_add_utf8:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001530 * @buffer: an #hb_buffer_t.
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001531 * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8
1532 * characters to append.
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001533 * @text_length: the length of the @text, or -1 if it is %NULL terminated.
1534 * @item_offset: the offset of the first character to add to the @buffer.
1535 * @item_length: the number of characters to add to the @buffer, or -1 for the
1536 * end of @text (assuming it is %NULL terminated).
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001537 *
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001538 * See hb_buffer_add_codepoints().
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001539 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001540 * Replaces invalid UTF-8 characters with the @buffer replacement code point,
1541 * see hb_buffer_set_replacement_codepoint().
1542 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301543 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001544 **/
Behdad Esfahbod299f0892009-08-10 22:47:57 -04001545void
1546hb_buffer_add_utf8 (hb_buffer_t *buffer,
1547 const char *text,
Behdad Esfahbod944b2ba2011-08-09 00:23:58 +02001548 int text_length,
Behdad Esfahbod299f0892009-08-10 22:47:57 -04001549 unsigned int item_offset,
Behdad Esfahbod944b2ba2011-08-09 00:23:58 +02001550 int item_length)
Behdad Esfahbod299f0892009-08-10 22:47:57 -04001551{
Behdad Esfahbod61820bc2015-01-26 14:25:52 -08001552 hb_buffer_add_utf<hb_utf8_t> (buffer, (const uint8_t *) text, text_length, item_offset, item_length);
Behdad Esfahbod299f0892009-08-10 22:47:57 -04001553}
1554
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001555/**
1556 * hb_buffer_add_utf16:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001557 * @buffer: an #hb_buffer_t.
1558 * @text: (array length=text_length): an array of UTF-16 characters to append.
1559 * @text_length: the length of the @text, or -1 if it is %NULL terminated.
1560 * @item_offset: the offset of the first character to add to the @buffer.
1561 * @item_length: the number of characters to add to the @buffer, or -1 for the
1562 * end of @text (assuming it is %NULL terminated).
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001563 *
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001564 * See hb_buffer_add_codepoints().
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001565 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001566 * Replaces invalid UTF-16 characters with the @buffer replacement code point,
1567 * see hb_buffer_set_replacement_codepoint().
1568 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301569 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001570 **/
Behdad Esfahbod299f0892009-08-10 22:47:57 -04001571void
1572hb_buffer_add_utf16 (hb_buffer_t *buffer,
1573 const uint16_t *text,
Behdad Esfahbod944b2ba2011-08-09 00:23:58 +02001574 int text_length,
Behdad Esfahbod299f0892009-08-10 22:47:57 -04001575 unsigned int item_offset,
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001576 int item_length)
Behdad Esfahbod299f0892009-08-10 22:47:57 -04001577{
Behdad Esfahbod61820bc2015-01-26 14:25:52 -08001578 hb_buffer_add_utf<hb_utf16_t> (buffer, text, text_length, item_offset, item_length);
Behdad Esfahbod0e0a4da2012-09-25 11:09:04 -04001579}
1580
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001581/**
1582 * hb_buffer_add_utf32:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001583 * @buffer: an #hb_buffer_t.
1584 * @text: (array length=text_length): an array of UTF-32 characters to append.
1585 * @text_length: the length of the @text, or -1 if it is %NULL terminated.
1586 * @item_offset: the offset of the first character to add to the @buffer.
1587 * @item_length: the number of characters to add to the @buffer, or -1 for the
1588 * end of @text (assuming it is %NULL terminated).
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001589 *
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001590 * See hb_buffer_add_codepoints().
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001591 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001592 * Replaces invalid UTF-32 characters with the @buffer replacement code point,
1593 * see hb_buffer_set_replacement_codepoint().
1594 *
Behdad Esfahbodb8811422015-09-03 15:53:22 +04301595 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001596 **/
Behdad Esfahbod299f0892009-08-10 22:47:57 -04001597void
1598hb_buffer_add_utf32 (hb_buffer_t *buffer,
1599 const uint32_t *text,
Behdad Esfahbod944b2ba2011-08-09 00:23:58 +02001600 int text_length,
Behdad Esfahbod299f0892009-08-10 22:47:57 -04001601 unsigned int item_offset,
Behdad Esfahbod944b2ba2011-08-09 00:23:58 +02001602 int item_length)
Behdad Esfahbod299f0892009-08-10 22:47:57 -04001603{
Behdad Esfahbod61820bc2015-01-26 14:25:52 -08001604 hb_buffer_add_utf<hb_utf32_t<> > (buffer, text, text_length, item_offset, item_length);
1605}
1606
1607/**
1608 * hb_buffer_add_latin1:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001609 * @buffer: an #hb_buffer_t.
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001610 * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8
1611 * characters to append.
1612 * @text_length: the length of the @text, or -1 if it is %NULL terminated.
1613 * @item_offset: the offset of the first character to add to the @buffer.
1614 * @item_length: the number of characters to add to the @buffer, or -1 for the
1615 * end of @text (assuming it is %NULL terminated).
Behdad Esfahbod61820bc2015-01-26 14:25:52 -08001616 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001617 * Similar to hb_buffer_add_codepoints(), but allows only access to first 256
1618 * Unicode code points that can fit in 8-bit strings.
1619 *
1620 * <note>Has nothing to do with non-Unicode Latin-1 encoding.</note>
Behdad Esfahbod61820bc2015-01-26 14:25:52 -08001621 *
Sascha Brawer01c3a882015-06-01 13:22:01 +02001622 * Since: 0.9.39
Behdad Esfahbod61820bc2015-01-26 14:25:52 -08001623 **/
1624void
1625hb_buffer_add_latin1 (hb_buffer_t *buffer,
1626 const uint8_t *text,
1627 int text_length,
1628 unsigned int item_offset,
1629 int item_length)
1630{
1631 hb_buffer_add_utf<hb_latin1_t> (buffer, text, text_length, item_offset, item_length);
Behdad Esfahbodbcba8b42014-07-16 14:59:04 -04001632}
1633
1634/**
1635 * hb_buffer_add_codepoints:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001636 * @buffer: a #hb_buffer_t to append characters to.
1637 * @text: (array length=text_length): an array of Unicode code points to append.
1638 * @text_length: the length of the @text, or -1 if it is %NULL terminated.
1639 * @item_offset: the offset of the first code point to add to the @buffer.
1640 * @item_length: the number of code points to add to the @buffer, or -1 for the
1641 * end of @text (assuming it is %NULL terminated).
Behdad Esfahbodbcba8b42014-07-16 14:59:04 -04001642 *
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001643 * Appends characters from @text array to @buffer. The @item_offset is the
1644 * position of the first character from @text that will be appended, and
1645 * @item_length is the number of character. When shaping part of a larger text
1646 * (e.g. a run of text from a paragraph), instead of passing just the substring
1647 * corresponding to the run, it is preferable to pass the whole
1648 * paragraph and specify the run start and length as @item_offset and
1649 * @item_length, respectively, to give HarfBuzz the full context to be able,
1650 * for example, to do cross-run Arabic shaping or properly handle combining
1651 * marks at stat of run.
Behdad Esfahbodbcba8b42014-07-16 14:59:04 -04001652 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001653 * This function does not check the validity of @text, it is up to the caller
1654 * to ensure it contains a valid Unicode code points.
1655 *
Sascha Brawer01c3a882015-06-01 13:22:01 +02001656 * Since: 0.9.31
Behdad Esfahbodbcba8b42014-07-16 14:59:04 -04001657 **/
1658void
1659hb_buffer_add_codepoints (hb_buffer_t *buffer,
1660 const hb_codepoint_t *text,
1661 int text_length,
1662 unsigned int item_offset,
1663 int item_length)
1664{
Behdad Esfahbod61820bc2015-01-26 14:25:52 -08001665 hb_buffer_add_utf<hb_utf32_t<false> > (buffer, text, text_length, item_offset, item_length);
Behdad Esfahbod299f0892009-08-10 22:47:57 -04001666}
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -04001667
1668
Behdad Esfahbod39b17832012-07-17 17:09:29 -04001669static int
1670compare_info_codepoint (const hb_glyph_info_t *pa,
1671 const hb_glyph_info_t *pb)
1672{
1673 return (int) pb->codepoint - (int) pa->codepoint;
1674}
1675
1676static inline void
1677normalize_glyphs_cluster (hb_buffer_t *buffer,
1678 unsigned int start,
1679 unsigned int end,
1680 bool backward)
1681{
1682 hb_glyph_position_t *pos = buffer->pos;
1683
1684 /* Total cluster advance */
1685 hb_position_t total_x_advance = 0, total_y_advance = 0;
1686 for (unsigned int i = start; i < end; i++)
1687 {
1688 total_x_advance += pos[i].x_advance;
1689 total_y_advance += pos[i].y_advance;
1690 }
1691
1692 hb_position_t x_advance = 0, y_advance = 0;
1693 for (unsigned int i = start; i < end; i++)
1694 {
1695 pos[i].x_offset += x_advance;
1696 pos[i].y_offset += y_advance;
1697
1698 x_advance += pos[i].x_advance;
1699 y_advance += pos[i].y_advance;
1700
1701 pos[i].x_advance = 0;
1702 pos[i].y_advance = 0;
1703 }
1704
1705 if (backward)
1706 {
1707 /* Transfer all cluster advance to the last glyph. */
1708 pos[end - 1].x_advance = total_x_advance;
1709 pos[end - 1].y_advance = total_y_advance;
1710
Behdad Esfahbod85846b32015-09-01 15:07:52 +01001711 hb_stable_sort (buffer->info + start, end - start - 1, compare_info_codepoint, buffer->pos + start);
Behdad Esfahbod39b17832012-07-17 17:09:29 -04001712 } else {
1713 /* Transfer all cluster advance to the first glyph. */
1714 pos[start].x_advance += total_x_advance;
1715 pos[start].y_advance += total_y_advance;
1716 for (unsigned int i = start + 1; i < end; i++) {
1717 pos[i].x_offset -= total_x_advance;
1718 pos[i].y_offset -= total_y_advance;
1719 }
Behdad Esfahbod85846b32015-09-01 15:07:52 +01001720 hb_stable_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + start + 1);
Behdad Esfahbod39b17832012-07-17 17:09:29 -04001721 }
1722}
1723
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001724/**
1725 * hb_buffer_normalize_glyphs:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001726 * @buffer: an #hb_buffer_t.
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001727 *
Khaled Hosny9ab9f972016-01-01 20:38:21 +04001728 * Reorders a glyph buffer to have canonical in-cluster glyph order / position.
1729 * The resulting clusters should behave identical to pre-reordering clusters.
1730 *
1731 * <note>This has nothing to do with Unicode normalization.</note>
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001732 *
Sascha Brawer01c3a882015-06-01 13:22:01 +02001733 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -04001734 **/
Behdad Esfahbod39b17832012-07-17 17:09:29 -04001735void
1736hb_buffer_normalize_glyphs (hb_buffer_t *buffer)
1737{
1738 assert (buffer->have_positions);
Behdad Esfahbod7d372802012-09-25 11:04:41 -04001739 assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
Behdad Esfahbod39b17832012-07-17 17:09:29 -04001740
1741 bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
1742
1743 unsigned int count = buffer->len;
1744 if (unlikely (!count)) return;
1745 hb_glyph_info_t *info = buffer->info;
1746
1747 unsigned int start = 0;
1748 unsigned int end;
1749 for (end = start + 1; end < count; end++)
1750 if (info[start].cluster != info[end].cluster) {
1751 normalize_glyphs_cluster (buffer, start, end, backward);
1752 start = end;
1753 }
1754 normalize_glyphs_cluster (buffer, start, end, backward);
1755}
Behdad Esfahbode995d332015-09-01 16:13:32 +01001756
1757void
1758hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *))
1759{
1760 assert (!have_positions);
1761 for (unsigned int i = start + 1; i < end; i++)
1762 {
1763 unsigned int j = i;
1764 while (j > start && compar (&info[j - 1], &info[i]) > 0)
1765 j--;
1766 if (i == j)
1767 continue;
1768 /* Move item i to occupy place for item j, shift what's in between. */
1769 merge_clusters (j, i + 1);
1770 {
1771 hb_glyph_info_t t = info[i];
1772 memmove (&info[j + 1], &info[j], (i - j) * sizeof (hb_glyph_info_t));
1773 info[j] = t;
1774 }
1775 }
1776}
Behdad Esfahbod0475ef22015-12-18 18:17:07 +00001777
1778/*
1779 * Debugging.
1780 */
1781
1782/**
1783 * hb_buffer_set_message_func:
Khaled Hosnyf18d2222015-12-29 15:21:20 +04001784 * @buffer: an #hb_buffer_t.
Behdad Esfahbod0475ef22015-12-18 18:17:07 +00001785 * @func: (closure user_data) (destroy destroy) (scope notified):
1786 * @user_data:
1787 * @destroy:
1788 *
1789 *
1790 *
1791 * Since: 1.1.3
1792 **/
1793void
1794hb_buffer_set_message_func (hb_buffer_t *buffer,
1795 hb_buffer_message_func_t func,
1796 void *user_data, hb_destroy_func_t destroy)
1797{
1798 if (buffer->message_destroy)
1799 buffer->message_destroy (buffer->message_data);
1800
1801 if (func) {
1802 buffer->message_func = func;
1803 buffer->message_data = user_data;
1804 buffer->message_destroy = destroy;
1805 } else {
1806 buffer->message_func = NULL;
1807 buffer->message_data = NULL;
1808 buffer->message_destroy = NULL;
1809 }
1810}
1811
1812bool
1813hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap)
1814{
1815 char buf[100];
1816 vsnprintf (buf, sizeof (buf), fmt, ap);
1817 return (bool) this->message_func (this, font, buf, this->message_data);
1818}