1/*
2 * Copyright © 1998-2004 David Turner and Werner Lemberg
3 * Copyright © 2004,2007,2009 Red Hat, Inc.
4 * Copyright © 2011,2012 Google, Inc.
5 *
6 * This is part of HarfBuzz, a text shaping library.
7 *
8 * 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
27 * Google Author(s): Behdad Esfahbod
28 */
29
30#ifndef HB_H_IN
31#error "Include <hb.h> instead."
32#endif
33
34#ifndef HB_BUFFER_H
35#define HB_BUFFER_H
36
37#include "hb-common.h"
38#include "hb-unicode.h"
39#include "hb-font.h"
40
41HB_BEGIN_DECLS
42
43/**
44 * hb_glyph_info_t:
45 * @codepoint: either a Unicode code point (before shaping) or a glyph index
46 * (after shaping).
47 * @cluster: the index of the character in the original text that corresponds
48 * to this #hb_glyph_info_t, or whatever the client passes to
49 * hb_buffer_add(). More than one #hb_glyph_info_t can have the same
50 * @cluster value, if they resulted from the same character (e.g. one
51 * to many glyph substitution), and when more than one character gets
52 * merged in the same glyph (e.g. many to one glyph substitution) the
53 * #hb_glyph_info_t will have the smallest cluster value of them.
54 * By default some characters are merged into the same cluster
55 * (e.g. combining marks have the same cluster as their bases)
56 * even if they are separate glyphs, hb_buffer_set_cluster_level()
57 * allow selecting more fine-grained cluster handling.
58 *
59 * The #hb_glyph_info_t is the structure that holds information about the
60 * glyphs and their relation to input text.
61 */
62typedef struct hb_glyph_info_t
63{
64 hb_codepoint_t codepoint;
65 /*< private >*/
66 hb_mask_t mask;
67 /*< public >*/
68 uint32_t cluster;
69
70 /*< private >*/
71 hb_var_int_t var1;
72 hb_var_int_t var2;
73} hb_glyph_info_t;
74
75/**
76 * hb_glyph_flags_t:
77 * @HB_GLYPH_FLAG_UNSAFE_TO_BREAK: Indicates that if input text is broken at the
78 * beginning of the cluster this glyph is part of,
79 * then both sides need to be re-shaped, as the
80 * result might be different. On the flip side,
81 * it means that when this flag is not present,
82 * then it's safe to break the glyph-run at the
83 * beginning of this cluster, and the two sides
84 * represent the exact same result one would get
85 * if breaking input text at the beginning of
86 * this cluster and shaping the two sides
87 * separately. This can be used to optimize
88 * paragraph layout, by avoiding re-shaping
89 * of each line after line-breaking, or limiting
90 * the reshaping to a small piece around the
91 * breaking point only.
92 * @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
93 *
94 * Since: 1.5.0
95 */
96typedef enum { /*< flags >*/
97 HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
98
99 HB_GLYPH_FLAG_DEFINED = 0x00000001 /* OR of all defined flags */
100} hb_glyph_flags_t;
101
102HB_EXTERN hb_glyph_flags_t
103hb_glyph_info_get_glyph_flags (const hb_glyph_info_t *info);
104
105#define hb_glyph_info_get_glyph_flags(info) \
106 ((hb_glyph_flags_t) ((unsigned int) (info)->mask & HB_GLYPH_FLAG_DEFINED))
107
108
109/**
110 * hb_glyph_position_t:
111 * @x_advance: how much the line advances after drawing this glyph when setting
112 * text in horizontal direction.
113 * @y_advance: how much the line advances after drawing this glyph when setting
114 * text in vertical direction.
115 * @x_offset: how much the glyph moves on the X-axis before drawing it, this
116 * should not affect how much the line advances.
117 * @y_offset: how much the glyph moves on the Y-axis before drawing it, this
118 * should not affect how much the line advances.
119 *
120 * The #hb_glyph_position_t is the structure that holds the positions of the
121 * glyph in both horizontal and vertical directions. All positions in
122 * #hb_glyph_position_t are relative to the current point.
123 *
124 */
125typedef struct hb_glyph_position_t {
126 hb_position_t x_advance;
127 hb_position_t y_advance;
128 hb_position_t x_offset;
129 hb_position_t y_offset;
130
131 /*< private >*/
132 hb_var_int_t var;
133} hb_glyph_position_t;
134
135/**
136 * hb_segment_properties_t:
137 * @direction: the #hb_direction_t of the buffer, see hb_buffer_set_direction().
138 * @script: the #hb_script_t of the buffer, see hb_buffer_set_script().
139 * @language: the #hb_language_t of the buffer, see hb_buffer_set_language().
140 *
141 * The structure that holds various text properties of an #hb_buffer_t. Can be
142 * set and retrieved using hb_buffer_set_segment_properties() and
143 * hb_buffer_get_segment_properties(), respectively.
144 */
145typedef struct hb_segment_properties_t {
146 hb_direction_t direction;
147 hb_script_t script;
148 hb_language_t language;
149 /*< private >*/
150 void *reserved1;
151 void *reserved2;
152} hb_segment_properties_t;
153
154#define HB_SEGMENT_PROPERTIES_DEFAULT {HB_DIRECTION_INVALID, \
155 HB_SCRIPT_INVALID, \
156 HB_LANGUAGE_INVALID, \
157 (void *) 0, \
158 (void *) 0}
159
160HB_EXTERN hb_bool_t
161hb_segment_properties_equal (const hb_segment_properties_t *a,
162 const hb_segment_properties_t *b);
163
164HB_EXTERN unsigned int
165hb_segment_properties_hash (const hb_segment_properties_t *p);
166
167
168
169/**
170 * hb_buffer_t:
171 *
172 * The main structure holding the input text and its properties before shaping,
173 * and output glyphs and their information after shaping.
174 */
175
176typedef struct hb_buffer_t hb_buffer_t;
177
178HB_EXTERN hb_buffer_t *
179hb_buffer_create (void);
180
181HB_EXTERN hb_buffer_t *
182hb_buffer_get_empty (void);
183
184HB_EXTERN hb_buffer_t *
185hb_buffer_reference (hb_buffer_t *buffer);
186
187HB_EXTERN void
188hb_buffer_destroy (hb_buffer_t *buffer);
189
190HB_EXTERN hb_bool_t
191hb_buffer_set_user_data (hb_buffer_t *buffer,
192 hb_user_data_key_t *key,
193 void * data,
194 hb_destroy_func_t destroy,
195 hb_bool_t replace);
196
197HB_EXTERN void *
198hb_buffer_get_user_data (hb_buffer_t *buffer,
199 hb_user_data_key_t *key);
200
201
202/**
203 * hb_buffer_content_type_t:
204 * @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer.
205 * @HB_BUFFER_CONTENT_TYPE_UNICODE: The buffer contains input characters (before shaping).
206 * @HB_BUFFER_CONTENT_TYPE_GLYPHS: The buffer contains output glyphs (after shaping).
207 */
208typedef enum {
209 HB_BUFFER_CONTENT_TYPE_INVALID = 0,
210 HB_BUFFER_CONTENT_TYPE_UNICODE,
211 HB_BUFFER_CONTENT_TYPE_GLYPHS
212} hb_buffer_content_type_t;
213
214HB_EXTERN void
215hb_buffer_set_content_type (hb_buffer_t *buffer,
216 hb_buffer_content_type_t content_type);
217
218HB_EXTERN hb_buffer_content_type_t
219hb_buffer_get_content_type (hb_buffer_t *buffer);
220
221
222HB_EXTERN void
223hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
224 hb_unicode_funcs_t *unicode_funcs);
225
226HB_EXTERN hb_unicode_funcs_t *
227hb_buffer_get_unicode_funcs (hb_buffer_t *buffer);
228
229HB_EXTERN void
230hb_buffer_set_direction (hb_buffer_t *buffer,
231 hb_direction_t direction);
232
233HB_EXTERN hb_direction_t
234hb_buffer_get_direction (hb_buffer_t *buffer);
235
236HB_EXTERN void
237hb_buffer_set_script (hb_buffer_t *buffer,
238 hb_script_t script);
239
240HB_EXTERN hb_script_t
241hb_buffer_get_script (hb_buffer_t *buffer);
242
243HB_EXTERN void
244hb_buffer_set_language (hb_buffer_t *buffer,
245 hb_language_t language);
246
247
248HB_EXTERN hb_language_t
249hb_buffer_get_language (hb_buffer_t *buffer);
250
251HB_EXTERN void
252hb_buffer_set_segment_properties (hb_buffer_t *buffer,
253 const hb_segment_properties_t *props);
254
255HB_EXTERN void
256hb_buffer_get_segment_properties (hb_buffer_t *buffer,
257 hb_segment_properties_t *props);
258
259HB_EXTERN void
260hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
261
262
263/**
264 * hb_buffer_flags_t:
265 * @HB_BUFFER_FLAG_DEFAULT: the default buffer flag.
266 * @HB_BUFFER_FLAG_BOT: flag indicating that special handling of the beginning
267 * of text paragraph can be applied to this buffer. Should usually
268 * be set, unless you are passing to the buffer only part
269 * of the text without the full context.
270 * @HB_BUFFER_FLAG_EOT: flag indicating that special handling of the end of text
271 * paragraph can be applied to this buffer, similar to
272 * @HB_BUFFER_FLAG_BOT.
273 * @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES:
274 * flag indication that character with Default_Ignorable
275 * Unicode property should use the corresponding glyph
276 * from the font, instead of hiding them (done by
277 * replacing them with the space glyph and zeroing the
278 * advance width.) This flag takes precedence over
279 * @HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES.
280 * @HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES:
281 * flag indication that character with Default_Ignorable
282 * Unicode property should be removed from glyph string
283 * instead of hiding them (done by replacing them with the
284 * space glyph and zeroing the advance width.)
285 * @HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES takes
286 * precedence over this flag. Since: 1.8.0
287 * @HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE:
288 * flag indicating that a dotted circle should
289 * not be inserted in the rendering of incorrect
290 * character sequences (such at <0905 093E>). Since: 2.4
291 *
292 * Since: 0.9.20
293 */
294typedef enum { /*< flags >*/
295 HB_BUFFER_FLAG_DEFAULT = 0x00000000u,
296 HB_BUFFER_FLAG_BOT = 0x00000001u, /* Beginning-of-text */
297 HB_BUFFER_FLAG_EOT = 0x00000002u, /* End-of-text */
298 HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u,
299 HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x00000008u,
300 HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u
301} hb_buffer_flags_t;
302
303HB_EXTERN void
304hb_buffer_set_flags (hb_buffer_t *buffer,
305 hb_buffer_flags_t flags);
306
307HB_EXTERN hb_buffer_flags_t
308hb_buffer_get_flags (hb_buffer_t *buffer);
309
310/**
311 * hb_buffer_cluster_level_t:
312 * @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES: Return cluster values grouped by graphemes into
313 * monotone order.
314 * @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS: Return cluster values grouped into monotone order.
315 * @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS: Don't group cluster values.
316 * @HB_BUFFER_CLUSTER_LEVEL_DEFAULT: Default cluster level,
317 * equal to @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES.
318 *
319 * Since: 0.9.42
320 */
321typedef enum {
322 HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES = 0,
323 HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS = 1,
324 HB_BUFFER_CLUSTER_LEVEL_CHARACTERS = 2,
325 HB_BUFFER_CLUSTER_LEVEL_DEFAULT = HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES
326} hb_buffer_cluster_level_t;
327
328HB_EXTERN void
329hb_buffer_set_cluster_level (hb_buffer_t *buffer,
330 hb_buffer_cluster_level_t cluster_level);
331
332HB_EXTERN hb_buffer_cluster_level_t
333hb_buffer_get_cluster_level (hb_buffer_t *buffer);
334
335/**
336 * HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT:
337 *
338 * The default code point for replacing invalid characters in a given encoding.
339 * Set to U+FFFD REPLACEMENT CHARACTER.
340 *
341 * Since: 0.9.31
342 */
343#define HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT 0xFFFDu
344
345HB_EXTERN void
346hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
347 hb_codepoint_t replacement);
348
349HB_EXTERN hb_codepoint_t
350hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer);
351
352HB_EXTERN void
353hb_buffer_set_invisible_glyph (hb_buffer_t *buffer,
354 hb_codepoint_t invisible);
355
356HB_EXTERN hb_codepoint_t
357hb_buffer_get_invisible_glyph (hb_buffer_t *buffer);
358
359
360HB_EXTERN void
361hb_buffer_reset (hb_buffer_t *buffer);
362
363HB_EXTERN void
364hb_buffer_clear_contents (hb_buffer_t *buffer);
365
366HB_EXTERN hb_bool_t
367hb_buffer_pre_allocate (hb_buffer_t *buffer,
368 unsigned int size);
369
370
371HB_EXTERN hb_bool_t
372hb_buffer_allocation_successful (hb_buffer_t *buffer);
373
374HB_EXTERN void
375hb_buffer_reverse (hb_buffer_t *buffer);
376
377HB_EXTERN void
378hb_buffer_reverse_range (hb_buffer_t *buffer,
379 unsigned int start, unsigned int end);
380
381HB_EXTERN void
382hb_buffer_reverse_clusters (hb_buffer_t *buffer);
383
384
385/* Filling the buffer in */
386
387HB_EXTERN void
388hb_buffer_add (hb_buffer_t *buffer,
389 hb_codepoint_t codepoint,
390 unsigned int cluster);
391
392HB_EXTERN void
393hb_buffer_add_utf8 (hb_buffer_t *buffer,
394 const char *text,
395 int text_length,
396 unsigned int item_offset,
397 int item_length);
398
399HB_EXTERN void
400hb_buffer_add_utf16 (hb_buffer_t *buffer,
401 const uint16_t *text,
402 int text_length,
403 unsigned int item_offset,
404 int item_length);
405
406HB_EXTERN void
407hb_buffer_add_utf32 (hb_buffer_t *buffer,
408 const uint32_t *text,
409 int text_length,
410 unsigned int item_offset,
411 int item_length);
412
413HB_EXTERN void
414hb_buffer_add_latin1 (hb_buffer_t *buffer,
415 const uint8_t *text,
416 int text_length,
417 unsigned int item_offset,
418 int item_length);
419
420HB_EXTERN void
421hb_buffer_add_codepoints (hb_buffer_t *buffer,
422 const hb_codepoint_t *text,
423 int text_length,
424 unsigned int item_offset,
425 int item_length);
426
427HB_EXTERN void
428hb_buffer_append (hb_buffer_t *buffer,
429 hb_buffer_t *source,
430 unsigned int start,
431 unsigned int end);
432
433HB_EXTERN hb_bool_t
434hb_buffer_set_length (hb_buffer_t *buffer,
435 unsigned int length);
436
437HB_EXTERN unsigned int
438hb_buffer_get_length (hb_buffer_t *buffer);
439
440/* Getting glyphs out of the buffer */
441
442HB_EXTERN hb_glyph_info_t *
443hb_buffer_get_glyph_infos (hb_buffer_t *buffer,
444 unsigned int *length);
445
446HB_EXTERN hb_glyph_position_t *
447hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
448 unsigned int *length);
449
450
451HB_EXTERN void
452hb_buffer_normalize_glyphs (hb_buffer_t *buffer);
453
454
455/*
456 * Serialize
457 */
458
459/**
460 * hb_buffer_serialize_flags_t:
461 * @HB_BUFFER_SERIALIZE_FLAG_DEFAULT: serialize glyph names, clusters and positions.
462 * @HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS: do not serialize glyph cluster.
463 * @HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS: do not serialize glyph position information.
464 * @HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES: do no serialize glyph name.
465 * @HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS: serialize glyph extents.
466 * @HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS: serialize glyph flags. Since: 1.5.0
467 * @HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES: do not serialize glyph advances,
468 * glyph offsets will reflect absolute glyph positions. Since: 1.8.0
469 *
470 * Flags that control what glyph information are serialized in hb_buffer_serialize_glyphs().
471 *
472 * Since: 0.9.20
473 */
474typedef enum { /*< flags >*/
475 HB_BUFFER_SERIALIZE_FLAG_DEFAULT = 0x00000000u,
476 HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001u,
477 HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002u,
478 HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u,
479 HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u,
480 HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS = 0x00000010u,
481 HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES = 0x00000020u
482} hb_buffer_serialize_flags_t;
483
484/**
485 * hb_buffer_serialize_format_t:
486 * @HB_BUFFER_SERIALIZE_FORMAT_TEXT: a human-readable, plain text format.
487 * @HB_BUFFER_SERIALIZE_FORMAT_JSON: a machine-readable JSON format.
488 * @HB_BUFFER_SERIALIZE_FORMAT_INVALID: invalid format.
489 *
490 * The buffer serialization and de-serialization format used in
491 * hb_buffer_serialize_glyphs() and hb_buffer_deserialize_glyphs().
492 *
493 * Since: 0.9.2
494 */
495typedef enum {
496 HB_BUFFER_SERIALIZE_FORMAT_TEXT = HB_TAG('T','E','X','T'),
497 HB_BUFFER_SERIALIZE_FORMAT_JSON = HB_TAG('J','S','O','N'),
498 HB_BUFFER_SERIALIZE_FORMAT_INVALID = HB_TAG_NONE
499} hb_buffer_serialize_format_t;
500
501HB_EXTERN hb_buffer_serialize_format_t
502hb_buffer_serialize_format_from_string (const char *str, int len);
503
504HB_EXTERN const char *
505hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format);
506
507HB_EXTERN const char **
508hb_buffer_serialize_list_formats (void);
509
510HB_EXTERN unsigned int
511hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
512 unsigned int start,
513 unsigned int end,
514 char *buf,
515 unsigned int buf_size,
516 unsigned int *buf_consumed,
517 hb_font_t *font,
518 hb_buffer_serialize_format_t format,
519 hb_buffer_serialize_flags_t flags);
520
521HB_EXTERN hb_bool_t
522hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
523 const char *buf,
524 int buf_len,
525 const char **end_ptr,
526 hb_font_t *font,
527 hb_buffer_serialize_format_t format);
528
529
530/*
531 * Compare buffers
532 */
533
534typedef enum { /*< flags >*/
535 HB_BUFFER_DIFF_FLAG_EQUAL = 0x0000,
536
537 /* Buffers with different content_type cannot be meaningfully compared
538 * in any further detail. */
539 HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH = 0x0001,
540
541 /* For buffers with differing length, the per-glyph comparison is not
542 * attempted, though we do still scan reference for dottedcircle / .notdef
543 * glyphs. */
544 HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH = 0x0002,
545
546 /* We want to know if dottedcircle / .notdef glyphs are present in the
547 * reference, as we may not care so much about other differences in this
548 * case. */
549 HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT = 0x0004,
550 HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT = 0x0008,
551
552 /* If the buffers have the same length, we compare them glyph-by-glyph
553 * and report which aspect(s) of the glyph info/position are different. */
554 HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH = 0x0010,
555 HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH = 0x0020,
556 HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH = 0x0040,
557 HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH = 0x0080
558
559} hb_buffer_diff_flags_t;
560
561/* Compare the contents of two buffers, report types of differences. */
562HB_EXTERN hb_buffer_diff_flags_t
563hb_buffer_diff (hb_buffer_t *buffer,
564 hb_buffer_t *reference,
565 hb_codepoint_t dottedcircle_glyph,
566 unsigned int position_fuzz);
567
568
569/*
570 * Debugging.
571 */
572
573typedef hb_bool_t (*hb_buffer_message_func_t) (hb_buffer_t *buffer,
574 hb_font_t *font,
575 const char *message,
576 void *user_data);
577
578HB_EXTERN void
579hb_buffer_set_message_func (hb_buffer_t *buffer,
580 hb_buffer_message_func_t func,
581 void *user_data, hb_destroy_func_t destroy);
582
583
584HB_END_DECLS
585
586#endif /* HB_BUFFER_H */
587