Lines Matching +full:is +full:- +full:buffer
2 * Copyright © 1998-2004 David Turner and Werner Lemberg
6 * This is part of HarfBuzz, a text shaping library.
8 * Permission is hereby granted, without written agreement and without
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
30 #include "hb-buffer.hh"
31 #include "hb-utf.hh"
35 * SECTION: hb-buffer
36 * @title: hb-buffer
44 * The input buffer is a sequence of Unicode codepoints, with
46 * buffer is a sequence of glyphs, with associated attributes such
67 return a->direction == b->direction && in hb_segment_properties_equal()
68 a->script == b->script && in hb_segment_properties_equal()
69 a->language == b->language && in hb_segment_properties_equal()
70 a->reserved1 == b->reserved1 && in hb_segment_properties_equal()
71 a->reserved2 == b->reserved2; in hb_segment_properties_equal()
89 return ((unsigned int) p->direction * 31 + in hb_segment_properties_hash()
90 (unsigned int) p->script) * 31 + in hb_segment_properties_hash()
91 (intptr_t) (p->language); in hb_segment_properties_hash()
101 * First, if @p does not have direction set, direction is copied from @src.
104 * does not have script set, script is copied from @src.
107 * can be unset), if @p does not have language set, language is copied from
119 if (!p->direction) in hb_segment_properties_overlay()
120 p->direction = src->direction; in hb_segment_properties_overlay()
122 if (p->direction != src->direction) in hb_segment_properties_overlay()
125 if (!p->script) in hb_segment_properties_overlay()
126 p->script = src->script; in hb_segment_properties_overlay()
128 if (p->script != src->script) in hb_segment_properties_overlay()
131 if (!p->language) in hb_segment_properties_overlay()
132 p->language = src->language; in hb_segment_properties_overlay()
135 /* Here is how the buffer works internally:
141 * same piece of memory, which is owned by info. This remains the
143 * In that case, sync() is mostly no-op and the glyph operations
144 * operate mostly in-place.
146 * As soon as out_info gets longer than info, out_info is moved over
147 * to an alternate buffer (which we reuse the pos buffer for), and its
229 memmove (info + idx + count, info + idx, (len - idx) * sizeof (info[0])); in shift_forward()
237 * is layering violation... */ in shift_forward()
238 hb_memset (info + len, 0, (idx + count - len) * sizeof (info[0])); in shift_forward()
262 /* HarfBuzz-Internal API */
354 glyph->codepoint = codepoint; in add()
355 glyph->mask = 0; in add()
356 glyph->cluster = cluster; in add()
404 if (unlikely (!successful || !next_glyphs (len - idx))) in sync()
445 return idx - old_idx; in sync_so_far()
460 assert (i <= out_len + (len - idx)); in move_to()
464 unsigned int count = i - out_len; in move_to()
474 unsigned int count = out_len - i; in move_to()
480 * But that would leave empty slots in the buffer in case of allocation in move_to()
483 if (unlikely (idx < count && !shift_forward (count - idx))) return false; in move_to()
487 idx -= count; in move_to()
488 out_len -= count; in move_to()
530 if (cluster != info[end - 1].cluster) in merge_clusters_impl()
531 while (end < len && info[end - 1].cluster == info[end].cluster) in merge_clusters_impl()
536 while (idx < start && info[start - 1].cluster == info[start].cluster) in merge_clusters_impl()
537 start--; in merge_clusters_impl()
539 /* If we hit the start of buffer, continue in out-buffer. */ in merge_clusters_impl()
541 for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--) in merge_clusters_impl()
542 set_cluster (out_info[i - 1], cluster); in merge_clusters_impl()
554 if (unlikely (end - start < 2)) in merge_out_clusters()
563 while (start && out_info[start - 1].cluster == out_info[start].cluster) in merge_out_clusters()
564 start--; in merge_out_clusters()
567 while (end < out_len && out_info[end - 1].cluster == out_info[end].cluster) in merge_out_clusters()
570 /* If we hit the end of out-buffer, continue in buffer. */ in merge_out_clusters()
572 for (unsigned int i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++) in merge_out_clusters()
581 /* The logic here is duplicated in hb_ot_hide_default_ignorables(). */ in delete_glyph()
585 (out_len && cluster == out_info[out_len - 1].cluster)) in delete_glyph()
594 if (cluster < out_info[out_len - 1].cluster) in delete_glyph()
597 unsigned int old_cluster = out_info[out_len - 1].cluster; in delete_glyph()
598 for (unsigned i = out_len; i && out_info[i - 1].cluster == old_cluster; i--) in delete_glyph()
599 set_cluster (out_info[i - 1], cluster, mask); in delete_glyph()
619 * NOTE! We can't use out-buffer as we have positioning data. */ in delete_glyphs_inplace()
627 * Same logic as delete_glyph(), but for in-place removal. */ in delete_glyphs_inplace()
636 if (cluster < info[j - 1].cluster) in delete_glyphs_inplace()
639 unsigned int old_cluster = info[j - 1].cluster; in delete_glyphs_inplace()
640 for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--) in delete_glyphs_inplace()
641 set_cluster (info[k - 1], cluster, mask); in delete_glyphs_inplace()
667 /* If script is set to INVALID, guess from buffer contents */ in guess_segment_properties()
670 hb_script_t script = unicode->script (info[i].codepoint); in guess_segment_properties()
680 /* If direction is set to INVALID, guess from script */ in guess_segment_properties()
687 /* If language is not set, use default language from locale */ in guess_segment_properties()
717 /* Zero is good enough for everything else. */
738 hb_buffer_t *buffer; in hb_buffer_create() local
740 if (!(buffer = hb_object_create<hb_buffer_t> ())) in hb_buffer_create()
743 buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT; in hb_buffer_create()
744 buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT; in hb_buffer_create()
746 buffer->reset (); in hb_buffer_create()
748 return buffer; in hb_buffer_create()
756 * difference is that the buffer is configured similarly to @src.
766 hb_buffer_t *buffer = hb_buffer_create (); in hb_buffer_create_similar() local
768 buffer->similar (*src); in hb_buffer_create_similar()
770 return buffer; in hb_buffer_create_similar()
775 * @buffer: An #hb_buffer_t
777 * Resets the buffer to its initial status, as if it was just newly created
783 hb_buffer_reset (hb_buffer_t *buffer) in hb_buffer_reset() argument
785 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_reset()
788 buffer->reset (); in hb_buffer_reset()
796 * Return value: (transfer full): The empty buffer
808 * @buffer: An #hb_buffer_t
810 * Increases the reference count on @buffer by one. This prevents @buffer from
811 * being destroyed until a matching call to hb_buffer_destroy() is made.
819 hb_buffer_reference (hb_buffer_t *buffer) in hb_buffer_reference() argument
821 return hb_object_reference (buffer); in hb_buffer_reference()
826 * @buffer: An #hb_buffer_t
828 * Deallocate the @buffer.
829 * Decreases the reference count on @buffer by one. If the result is zero, then
830 * @buffer and all associated resources are freed. See hb_buffer_reference().
835 hb_buffer_destroy (hb_buffer_t *buffer) in hb_buffer_destroy() argument
837 if (!hb_object_destroy (buffer)) return; in hb_buffer_destroy()
839 hb_unicode_funcs_destroy (buffer->unicode); in hb_buffer_destroy()
841 hb_free (buffer->info); in hb_buffer_destroy()
842 hb_free (buffer->pos); in hb_buffer_destroy()
844 if (buffer->message_destroy) in hb_buffer_destroy()
845 buffer->message_destroy (buffer->message_data); in hb_buffer_destroy()
848 hb_free (buffer); in hb_buffer_destroy()
853 * @buffer: An #hb_buffer_t
854 * @key: The user-data key
856 * @destroy: (nullable): A callback to call when @data is not needed anymore
859 * Attaches a user-data key/data pair to the specified buffer.
866 hb_buffer_set_user_data (hb_buffer_t *buffer, in hb_buffer_set_user_data() argument
872 return hb_object_set_user_data (buffer, key, data, destroy, replace); in hb_buffer_set_user_data()
877 * @buffer: An #hb_buffer_t
878 * @key: The user-data key to query
881 * attached to the specified buffer.
888 hb_buffer_get_user_data (const hb_buffer_t *buffer, in hb_buffer_get_user_data() argument
891 return hb_object_get_user_data (buffer, key); in hb_buffer_get_user_data()
897 * @buffer: An #hb_buffer_t
898 * @content_type: The type of buffer contents to set
900 * Sets the type of @buffer contents. Buffers are either empty, contain
906 * - A newly created buffer starts with content type
909 * with an argument of zero all set the buffer content type to invalid
912 * - Calling hb_buffer_add_utf8(), hb_buffer_add_utf16(),
914 * hb_buffer_add_latin1() expect that buffer is either empty and
915 * have a content type of invalid, or that buffer content type is
917 * type to Unicode if they added anything to an empty buffer.
919 * - Finally hb_shape() and hb_shape_full() expect that the buffer
920 * is either empty and have content type of invalid, or that buffer
921 * content type is %HB_BUFFER_CONTENT_TYPE_UNICODE, and upon
922 * success they set the buffer content type to
925 * The above transitions are designed such that one can use a buffer
926 * in a loop of "reset : add-text : shape" without needing to ever
932 hb_buffer_set_content_type (hb_buffer_t *buffer, in hb_buffer_set_content_type() argument
935 buffer->content_type = content_type; in hb_buffer_set_content_type()
940 * @buffer: An #hb_buffer_t
942 * Fetches the type of @buffer contents. Buffers are either empty, contain
946 * The type of @buffer contents
951 hb_buffer_get_content_type (const hb_buffer_t *buffer) in hb_buffer_get_content_type() argument
953 return buffer->content_type; in hb_buffer_get_content_type()
959 * @buffer: An #hb_buffer_t
960 * @unicode_funcs: The Unicode-functions structure
962 * Sets the Unicode-functions structure of a buffer to
968 hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, in hb_buffer_set_unicode_funcs() argument
971 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_set_unicode_funcs()
978 hb_unicode_funcs_destroy (buffer->unicode); in hb_buffer_set_unicode_funcs()
979 buffer->unicode = unicode_funcs; in hb_buffer_set_unicode_funcs()
984 * @buffer: An #hb_buffer_t
986 * Fetches the Unicode-functions structure of a buffer.
988 * Return value: The Unicode-functions structure
993 hb_buffer_get_unicode_funcs (const hb_buffer_t *buffer) in hb_buffer_get_unicode_funcs() argument
995 return buffer->unicode; in hb_buffer_get_unicode_funcs()
1000 * @buffer: An #hb_buffer_t
1001 * @direction: the #hb_direction_t of the @buffer
1003 * Set the text flow direction of the buffer. No shaping can happen without
1004 * setting @buffer direction, and it controls the visual direction for the
1007 * reversing RTL text before shaping, then shaping with LTR direction is not
1014 hb_buffer_set_direction (hb_buffer_t *buffer, in hb_buffer_set_direction() argument
1017 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_set_direction()
1020 buffer->props.direction = direction; in hb_buffer_set_direction()
1025 * @buffer: An #hb_buffer_t
1030 * The direction of the @buffer.
1035 hb_buffer_get_direction (const hb_buffer_t *buffer) in hb_buffer_get_direction() argument
1037 return buffer->props.direction; in hb_buffer_get_direction()
1042 * @buffer: An #hb_buffer_t
1045 * Sets the script of @buffer to @script.
1047 * Script is crucial for choosing the proper shaping behaviour for scripts that
1058 hb_buffer_set_script (hb_buffer_t *buffer, in hb_buffer_set_script() argument
1061 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_set_script()
1064 buffer->props.script = script; in hb_buffer_set_script()
1069 * @buffer: An #hb_buffer_t
1071 * Fetches the script of @buffer.
1074 * The #hb_script_t of the @buffer
1079 hb_buffer_get_script (const hb_buffer_t *buffer) in hb_buffer_get_script() argument
1081 return buffer->props.script; in hb_buffer_get_script()
1086 * @buffer: An #hb_buffer_t
1089 * Sets the language of @buffer to @language.
1092 * buffer which can result in applying language-specific behaviour. Languages
1102 hb_buffer_set_language (hb_buffer_t *buffer, in hb_buffer_set_language() argument
1105 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_set_language()
1108 buffer->props.language = language; in hb_buffer_set_language()
1113 * @buffer: An #hb_buffer_t
1118 * The #hb_language_t of the buffer. Must not be freed by the caller.
1123 hb_buffer_get_language (const hb_buffer_t *buffer) in hb_buffer_get_language() argument
1125 return buffer->props.language; in hb_buffer_get_language()
1130 * @buffer: An #hb_buffer_t
1133 * Sets the segment properties of the buffer, a shortcut for calling
1140 hb_buffer_set_segment_properties (hb_buffer_t *buffer, in hb_buffer_set_segment_properties() argument
1143 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_set_segment_properties()
1146 buffer->props = *props; in hb_buffer_set_segment_properties()
1151 * @buffer: An #hb_buffer_t
1154 * Sets @props to the #hb_segment_properties_t of @buffer.
1159 hb_buffer_get_segment_properties (const hb_buffer_t *buffer, in hb_buffer_get_segment_properties() argument
1162 *props = buffer->props; in hb_buffer_get_segment_properties()
1168 * @buffer: An #hb_buffer_t
1169 * @flags: The buffer flags to set
1171 * Sets @buffer flags to @flags. See #hb_buffer_flags_t.
1176 hb_buffer_set_flags (hb_buffer_t *buffer, in hb_buffer_set_flags() argument
1179 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_set_flags()
1182 buffer->flags = flags; in hb_buffer_set_flags()
1187 * @buffer: An #hb_buffer_t
1189 * Fetches the #hb_buffer_flags_t of @buffer.
1192 * The @buffer flags
1197 hb_buffer_get_flags (const hb_buffer_t *buffer) in hb_buffer_get_flags() argument
1199 return buffer->flags; in hb_buffer_get_flags()
1204 * @buffer: An #hb_buffer_t
1205 * @cluster_level: The cluster level to set on the buffer
1207 * Sets the cluster level of a buffer. The #hb_buffer_cluster_level_t
1208 * dictates one aspect of how HarfBuzz will treat non-base characters
1214 hb_buffer_set_cluster_level (hb_buffer_t *buffer, in hb_buffer_set_cluster_level() argument
1217 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_set_cluster_level()
1220 buffer->cluster_level = cluster_level; in hb_buffer_set_cluster_level()
1225 * @buffer: An #hb_buffer_t
1227 * Fetches the cluster level of a buffer. The #hb_buffer_cluster_level_t
1228 * dictates one aspect of how HarfBuzz will treat non-base characters
1231 * Return value: The cluster level of @buffer
1236 hb_buffer_get_cluster_level (const hb_buffer_t *buffer) in hb_buffer_get_cluster_level() argument
1238 return buffer->cluster_level; in hb_buffer_get_cluster_level()
1244 * @buffer: An #hb_buffer_t
1248 * when adding text to @buffer.
1250 * Default is #HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT.
1255 hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer, in hb_buffer_set_replacement_codepoint() argument
1258 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_set_replacement_codepoint()
1261 buffer->replacement = replacement; in hb_buffer_set_replacement_codepoint()
1266 * @buffer: An #hb_buffer_t
1269 * when adding text to @buffer.
1272 * The @buffer replacement #hb_codepoint_t
1277 hb_buffer_get_replacement_codepoint (const hb_buffer_t *buffer) in hb_buffer_get_replacement_codepoint() argument
1279 return buffer->replacement; in hb_buffer_get_replacement_codepoint()
1285 * @buffer: An #hb_buffer_t
1290 * U+0020 SPACE character is used. Otherwise, this value is used
1296 hb_buffer_set_invisible_glyph (hb_buffer_t *buffer, in hb_buffer_set_invisible_glyph() argument
1299 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_set_invisible_glyph()
1302 buffer->invisible = invisible; in hb_buffer_set_invisible_glyph()
1307 * @buffer: An #hb_buffer_t
1312 * The @buffer invisible #hb_codepoint_t
1317 hb_buffer_get_invisible_glyph (const hb_buffer_t *buffer) in hb_buffer_get_invisible_glyph() argument
1319 return buffer->invisible; in hb_buffer_get_invisible_glyph()
1324 * @buffer: An #hb_buffer_t
1325 * @not_found: the not-found #hb_codepoint_t
1330 * The not-found glyph defaults to zero, sometimes known as the
1336 hb_buffer_set_not_found_glyph (hb_buffer_t *buffer, in hb_buffer_set_not_found_glyph() argument
1339 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_set_not_found_glyph()
1342 buffer->not_found = not_found; in hb_buffer_set_not_found_glyph()
1347 * @buffer: An #hb_buffer_t
1352 * The @buffer not-found #hb_codepoint_t
1357 hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer) in hb_buffer_get_not_found_glyph() argument
1359 return buffer->not_found; in hb_buffer_get_not_found_glyph()
1365 * @buffer: An #hb_buffer_t
1373 hb_buffer_clear_contents (hb_buffer_t *buffer) in hb_buffer_clear_contents() argument
1375 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_clear_contents()
1378 buffer->clear (); in hb_buffer_clear_contents()
1383 * @buffer: An #hb_buffer_t
1386 * Pre allocates memory for @buffer to fit at least @size number of items.
1389 * `true` if @buffer memory allocation succeeded, `false` otherwise
1394 hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size) in hb_buffer_pre_allocate() argument
1396 return buffer->ensure (size); in hb_buffer_pre_allocate()
1401 * @buffer: An #hb_buffer_t
1403 * Check if allocating memory for the buffer succeeded.
1406 * `true` if @buffer memory allocation succeeded, `false` otherwise.
1411 hb_buffer_allocation_successful (hb_buffer_t *buffer) in hb_buffer_allocation_successful() argument
1413 return buffer->successful; in hb_buffer_allocation_successful()
1418 * @buffer: An #hb_buffer_t
1422 * Appends a character with the Unicode value of @codepoint to @buffer, and
1428 * This function does not check the validity of @codepoint, it is up to the
1429 * caller to ensure it is a valid Unicode code point.
1434 hb_buffer_add (hb_buffer_t *buffer, in hb_buffer_add() argument
1438 buffer->add (codepoint, cluster); in hb_buffer_add()
1439 buffer->clear_context (1); in hb_buffer_add()
1444 * @buffer: An #hb_buffer_t
1445 * @length: The new length of @buffer
1451 * `true` if @buffer memory allocation succeeded, `false` otherwise.
1456 hb_buffer_set_length (hb_buffer_t *buffer, in hb_buffer_set_length() argument
1459 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_set_length()
1462 if (unlikely (!buffer->ensure (length))) in hb_buffer_set_length()
1466 if (length > buffer->len) { in hb_buffer_set_length()
1467 hb_memset (buffer->info + buffer->len, 0, sizeof (buffer->info[0]) * (length - buffer->len)); in hb_buffer_set_length()
1468 if (buffer->have_positions) in hb_buffer_set_length()
1469 hb_memset (buffer->pos + buffer->len, 0, sizeof (buffer->pos[0]) * (length - buffer->len)); in hb_buffer_set_length()
1472 buffer->len = length; in hb_buffer_set_length()
1476 buffer->content_type = HB_BUFFER_CONTENT_TYPE_INVALID; in hb_buffer_set_length()
1477 buffer->clear_context (0); in hb_buffer_set_length()
1479 buffer->clear_context (1); in hb_buffer_set_length()
1486 * @buffer: An #hb_buffer_t
1488 * Returns the number of items in the buffer.
1491 * The @buffer length.
1492 * The value valid as long as buffer has not been modified.
1497 hb_buffer_get_length (const hb_buffer_t *buffer) in hb_buffer_get_length() argument
1499 return buffer->len; in hb_buffer_get_length()
1504 * @buffer: An #hb_buffer_t
1505 * @length: (out): The output-array length.
1507 * Returns @buffer glyph information array. Returned pointer
1508 * is valid as long as @buffer contents are not modified.
1511 * The @buffer glyph information array.
1512 * The value valid as long as buffer has not been modified.
1517 hb_buffer_get_glyph_infos (hb_buffer_t *buffer, in hb_buffer_get_glyph_infos() argument
1521 *length = buffer->len; in hb_buffer_get_glyph_infos()
1523 return (hb_glyph_info_t *) buffer->info; in hb_buffer_get_glyph_infos()
1528 * @buffer: An #hb_buffer_t
1531 * Returns @buffer glyph position array. Returned pointer
1532 * is valid as long as @buffer contents are not modified.
1534 * If buffer did not have positions before, the positions will be
1535 * initialized to zeros, unless this function is called from
1536 * within a buffer message callback (see hb_buffer_set_message_func()),
1537 * in which case `NULL` is returned.
1540 * The @buffer glyph position array.
1541 * The value valid as long as buffer has not been modified.
1546 hb_buffer_get_glyph_positions (hb_buffer_t *buffer, in hb_buffer_get_glyph_positions() argument
1550 *length = buffer->len; in hb_buffer_get_glyph_positions()
1552 if (!buffer->have_positions) in hb_buffer_get_glyph_positions()
1554 if (unlikely (buffer->message_depth)) in hb_buffer_get_glyph_positions()
1557 buffer->clear_positions (); in hb_buffer_get_glyph_positions()
1560 return (hb_glyph_position_t *) buffer->pos; in hb_buffer_get_glyph_positions()
1565 * @buffer: an #hb_buffer_t.
1567 * Returns whether @buffer has glyph position data.
1568 * A buffer gains position data when hb_buffer_get_glyph_positions() is called on it,
1569 * and cleared of position data when hb_buffer_clear_contents() is called.
1572 * `true` if the @buffer has position array, `false` otherwise.
1577 hb_buffer_has_positions (hb_buffer_t *buffer) in hb_buffer_has_positions() argument
1579 return buffer->have_positions; in hb_buffer_has_positions()
1601 * @buffer: An #hb_buffer_t
1603 * Reverses buffer contents.
1608 hb_buffer_reverse (hb_buffer_t *buffer) in hb_buffer_reverse() argument
1610 buffer->reverse (); in hb_buffer_reverse()
1615 * @buffer: An #hb_buffer_t
1619 * Reverses buffer contents between @start and @end.
1624 hb_buffer_reverse_range (hb_buffer_t *buffer, in hb_buffer_reverse_range() argument
1627 buffer->reverse_range (start, end); in hb_buffer_reverse_range()
1632 * @buffer: An #hb_buffer_t
1634 * Reverses buffer clusters. That is, the buffer contents are
1641 hb_buffer_reverse_clusters (hb_buffer_t *buffer) in hb_buffer_reverse_clusters() argument
1643 buffer->reverse_clusters (); in hb_buffer_reverse_clusters()
1648 * @buffer: An #hb_buffer_t
1650 * Sets unset buffer segment properties based on buffer Unicode
1651 * contents. If buffer is not empty, it must have content type
1654 * If buffer script is not set (ie. is #HB_SCRIPT_INVALID), it
1656 * the buffer that has a script other than #HB_SCRIPT_COMMON,
1659 * Next, if buffer direction is not set (ie. is #HB_DIRECTION_INVALID),
1661 * buffer script as returned by hb_script_get_horizontal_direction().
1663 * then #HB_DIRECTION_LTR is used.
1665 * Finally, if buffer language is not set (ie. is #HB_LANGUAGE_INVALID),
1668 * taking buffer script into consideration when choosing a language.
1669 * Note that hb_language_get_default() is NOT threadsafe the first time
1670 * it is called. See documentation for that function for details.
1675 hb_buffer_guess_segment_properties (hb_buffer_t *buffer) in hb_buffer_guess_segment_properties() argument
1677 buffer->guess_segment_properties (); in hb_buffer_guess_segment_properties()
1682 hb_buffer_add_utf (hb_buffer_t *buffer, in hb_buffer_add_utf() argument
1689 const hb_codepoint_t replacement = buffer->replacement; in hb_buffer_add_utf()
1691 buffer->assert_unicode (); in hb_buffer_add_utf()
1693 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_add_utf()
1696 if (text_length == -1) in hb_buffer_add_utf()
1699 if (item_length == -1) in hb_buffer_add_utf()
1700 item_length = text_length - item_offset; in hb_buffer_add_utf()
1704 !buffer->ensure (buffer->len + item_length * sizeof (T) / 4))) in hb_buffer_add_utf()
1707 /* If buffer is empty and pre-context provided, install it. in hb_buffer_add_utf()
1708 * This check is written this way, to make sure people can in hb_buffer_add_utf()
1709 * provide pre-context in one add_utf() call, then provide in hb_buffer_add_utf()
1710 * text in a follow-up call. See: in hb_buffer_add_utf()
1714 if (!buffer->len && item_offset > 0) in hb_buffer_add_utf()
1716 /* Add pre-context */ in hb_buffer_add_utf()
1717 buffer->clear_context (0); in hb_buffer_add_utf()
1720 while (start < prev && buffer->context_len[0] < buffer->CONTEXT_LENGTH) in hb_buffer_add_utf()
1724 buffer->context[0][buffer->context_len[0]++] = u; in hb_buffer_add_utf()
1735 buffer->add (u, old_next - (const T *) text); in hb_buffer_add_utf()
1738 /* Add post-context */ in hb_buffer_add_utf()
1739 buffer->clear_context (1); in hb_buffer_add_utf()
1741 while (next < end && buffer->context_len[1] < buffer->CONTEXT_LENGTH) in hb_buffer_add_utf()
1745 buffer->context[1][buffer->context_len[1]++] = u; in hb_buffer_add_utf()
1748 buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; in hb_buffer_add_utf()
1753 * @buffer: An #hb_buffer_t
1754 * @text: (array length=text_length) (element-type uint8_t): An array of UTF-8
1756 * @text_length: The length of the @text, or -1 if it is `NULL` terminated.
1757 * @item_offset: The offset of the first character to add to the @buffer.
1758 * @item_length: The number of characters to add to the @buffer, or -1 for the
1759 * end of @text (assuming it is `NULL` terminated).
1763 * Replaces invalid UTF-8 characters with the @buffer replacement code point,
1769 hb_buffer_add_utf8 (hb_buffer_t *buffer, in hb_buffer_add_utf8() argument
1775 …hb_buffer_add_utf<hb_utf8_t> (buffer, (const uint8_t *) text, text_length, item_offset, item_lengt… in hb_buffer_add_utf8()
1780 * @buffer: An #hb_buffer_t
1781 * @text: (array length=text_length): An array of UTF-16 characters to append
1782 * @text_length: The length of the @text, or -1 if it is `NULL` terminated
1783 * @item_offset: The offset of the first character to add to the @buffer
1784 * @item_length: The number of characters to add to the @buffer, or -1 for the
1785 * end of @text (assuming it is `NULL` terminated)
1789 * Replaces invalid UTF-16 characters with the @buffer replacement code point,
1795 hb_buffer_add_utf16 (hb_buffer_t *buffer, in hb_buffer_add_utf16() argument
1801 hb_buffer_add_utf<hb_utf16_t> (buffer, text, text_length, item_offset, item_length); in hb_buffer_add_utf16()
1806 * @buffer: An #hb_buffer_t
1807 * @text: (array length=text_length): An array of UTF-32 characters to append
1808 * @text_length: The length of the @text, or -1 if it is `NULL` terminated
1809 * @item_offset: The offset of the first character to add to the @buffer
1810 * @item_length: The number of characters to add to the @buffer, or -1 for the
1811 * end of @text (assuming it is `NULL` terminated)
1815 * Replaces invalid UTF-32 characters with the @buffer replacement code point,
1821 hb_buffer_add_utf32 (hb_buffer_t *buffer, in hb_buffer_add_utf32() argument
1827 hb_buffer_add_utf<hb_utf32_t> (buffer, text, text_length, item_offset, item_length); in hb_buffer_add_utf32()
1832 * @buffer: An #hb_buffer_t
1833 * @text: (array length=text_length) (element-type uint8_t): an array of UTF-8
1835 * @text_length: the length of the @text, or -1 if it is `NULL` terminated
1836 * @item_offset: the offset of the first character to add to the @buffer
1837 * @item_length: the number of characters to add to the @buffer, or -1 for the
1838 * end of @text (assuming it is `NULL` terminated)
1841 * Unicode code points that can fit in 8-bit strings.
1843 * <note>Has nothing to do with non-Unicode Latin-1 encoding.</note>
1848 hb_buffer_add_latin1 (hb_buffer_t *buffer, in hb_buffer_add_latin1() argument
1854 hb_buffer_add_utf<hb_latin1_t> (buffer, text, text_length, item_offset, item_length); in hb_buffer_add_latin1()
1859 * @buffer: a #hb_buffer_t to append characters to.
1861 * @text_length: the length of the @text, or -1 if it is `NULL` terminated.
1862 * @item_offset: the offset of the first code point to add to the @buffer.
1863 * @item_length: the number of code points to add to the @buffer, or -1 for the
1864 * end of @text (assuming it is `NULL` terminated).
1866 * Appends characters from @text array to @buffer. The @item_offset is the
1868 * @item_length is the number of character. When shaping part of a larger text
1870 * corresponding to the run, it is preferable to pass the whole
1873 * for example, to do cross-run Arabic shaping or properly handle combining
1876 * This function does not check the validity of @text, it is up to the caller
1879 * sanity-check on the input.
1884 hb_buffer_add_codepoints (hb_buffer_t *buffer, in hb_buffer_add_codepoints() argument
1890 hb_buffer_add_utf<hb_utf32_novalidate_t> (buffer, text, text_length, item_offset, item_length); in hb_buffer_add_codepoints()
1896 * @buffer: An #hb_buffer_t
1898 * @start: start index into source buffer to copy. Use 0 to copy from start of buffer.
1899 * @end: end index into source buffer to copy. Use @HB_FEATURE_GLOBAL_END to copy to end of buffer.
1901 * Append (part of) contents of another buffer to this buffer.
1906 hb_buffer_append (hb_buffer_t *buffer, in hb_buffer_append() argument
1911 assert (!buffer->have_output && !source->have_output); in hb_buffer_append()
1912 assert (buffer->have_positions == source->have_positions || in hb_buffer_append()
1913 !buffer->len || !source->len); in hb_buffer_append()
1914 assert (buffer->content_type == source->content_type || in hb_buffer_append()
1915 !buffer->len || !source->len); in hb_buffer_append()
1917 if (end > source->len) in hb_buffer_append()
1918 end = source->len; in hb_buffer_append()
1924 if (buffer->len + (end - start) < buffer->len) /* Overflows. */ in hb_buffer_append()
1926 buffer->successful = false; in hb_buffer_append()
1930 unsigned int orig_len = buffer->len; in hb_buffer_append()
1931 hb_buffer_set_length (buffer, buffer->len + (end - start)); in hb_buffer_append()
1932 if (unlikely (!buffer->successful)) in hb_buffer_append()
1936 buffer->content_type = source->content_type; in hb_buffer_append()
1937 if (!buffer->have_positions && source->have_positions) in hb_buffer_append()
1938 buffer->clear_positions (); in hb_buffer_append()
1940 hb_segment_properties_overlay (&buffer->props, &source->props); in hb_buffer_append()
1942 …hb_memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0])… in hb_buffer_append()
1943 if (buffer->have_positions) in hb_buffer_append()
1944 … hb_memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0])); in hb_buffer_append()
1946 if (source->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE) in hb_buffer_append()
1950 /* pre-context */ in hb_buffer_append()
1951 if (!orig_len && start + source->context_len[0] > 0) in hb_buffer_append()
1953 buffer->clear_context (0); in hb_buffer_append()
1954 while (start > 0 && buffer->context_len[0] < buffer->CONTEXT_LENGTH) in hb_buffer_append()
1955 buffer->context[0][buffer->context_len[0]++] = source->info[--start].codepoint; in hb_buffer_append()
1956 …for (auto i = 0u; i < source->context_len[0] && buffer->context_len[0] < buffer->CONTEXT_LENGTH; i… in hb_buffer_append()
1957 buffer->context[0][buffer->context_len[0]++] = source->context[0][i]; in hb_buffer_append()
1960 /* post-context */ in hb_buffer_append()
1961 buffer->clear_context (1); in hb_buffer_append()
1962 while (end < source->len && buffer->context_len[1] < buffer->CONTEXT_LENGTH) in hb_buffer_append()
1963 buffer->context[1][buffer->context_len[1]++] = source->info[end++].codepoint; in hb_buffer_append()
1964 …for (auto i = 0u; i < source->context_len[1] && buffer->context_len[1] < buffer->CONTEXT_LENGTH; i… in hb_buffer_append()
1965 buffer->context[1][buffer->context_len[1]++] = source->context[1][i]; in hb_buffer_append()
1974 return (int) pb->codepoint - (int) pa->codepoint; in compare_info_codepoint()
1978 normalize_glyphs_cluster (hb_buffer_t *buffer, in normalize_glyphs_cluster() argument
1983 hb_glyph_position_t *pos = buffer->pos; in normalize_glyphs_cluster()
2009 pos[end - 1].x_advance = total_x_advance; in normalize_glyphs_cluster()
2010 pos[end - 1].y_advance = total_y_advance; in normalize_glyphs_cluster()
2012 …hb_stable_sort (buffer->info + start, end - start - 1, compare_info_codepoint, buffer->pos + start… in normalize_glyphs_cluster()
2018 pos[i].x_offset -= total_x_advance; in normalize_glyphs_cluster()
2019 pos[i].y_offset -= total_y_advance; in normalize_glyphs_cluster()
2021 …hb_stable_sort (buffer->info + start + 1, end - start - 1, compare_info_codepoint, buffer->pos + s… in normalize_glyphs_cluster()
2027 * @buffer: An #hb_buffer_t
2029 * Reorders a glyph buffer to have canonical in-cluster glyph order / position.
2030 * The resulting clusters should behave identical to pre-reordering clusters.
2037 hb_buffer_normalize_glyphs (hb_buffer_t *buffer) in hb_buffer_normalize_glyphs() argument
2039 assert (buffer->have_positions); in hb_buffer_normalize_glyphs()
2041 buffer->assert_glyphs (); in hb_buffer_normalize_glyphs()
2043 bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); in hb_buffer_normalize_glyphs()
2045 foreach_cluster (buffer, start, end) in hb_buffer_normalize_glyphs()
2046 normalize_glyphs_cluster (buffer, start, end, backward); in hb_buffer_normalize_glyphs()
2056 while (j > start && compar (&info[j - 1], &info[i]) > 0) in sort()
2057 j--; in sort()
2064 memmove (&info[j + 1], &info[j], (i - j) * sizeof (hb_glyph_info_t)); in sort()
2077 * @buffer: a buffer.
2078 * @reference: other buffer to compare to.
2079 * @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepoint_t) -1.
2082 * If dottedcircle_glyph is (hb_codepoint_t) -1 then #HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
2084 * callers if just comparing two buffers is needed.
2089 hb_buffer_diff (hb_buffer_t *buffer, in hb_buffer_diff() argument
2094 if (buffer->content_type != reference->content_type && buffer->len && reference->len) in hb_buffer_diff()
2098 bool contains = dottedcircle_glyph != (hb_codepoint_t) -1; in hb_buffer_diff()
2100 unsigned int count = reference->len; in hb_buffer_diff()
2102 if (buffer->len != count) in hb_buffer_diff()
2105 * we can't compare glyph-by-glyph, but we do want to know if there in hb_buffer_diff()
2106 * are .notdef or dottedcircle glyphs present in the reference buffer in hb_buffer_diff()
2108 const hb_glyph_info_t *info = reference->info; in hb_buffer_diff()
2124 const hb_glyph_info_t *buf_info = buffer->info; in hb_buffer_diff()
2125 const hb_glyph_info_t *ref_info = reference->info; in hb_buffer_diff()
2128 if (buf_info->codepoint != ref_info->codepoint) in hb_buffer_diff()
2130 if (buf_info->cluster != ref_info->cluster) in hb_buffer_diff()
2132 if ((buf_info->mask ^ ref_info->mask) & HB_GLYPH_FLAG_DEFINED) in hb_buffer_diff()
2134 if (contains && ref_info->codepoint == dottedcircle_glyph) in hb_buffer_diff()
2136 if (contains && ref_info->codepoint == 0) in hb_buffer_diff()
2142 if (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS) in hb_buffer_diff()
2144 assert (buffer->have_positions); in hb_buffer_diff()
2145 const hb_glyph_position_t *buf_pos = buffer->pos; in hb_buffer_diff()
2146 const hb_glyph_position_t *ref_pos = reference->pos; in hb_buffer_diff()
2149 if ((unsigned int) abs (buf_pos->x_advance - ref_pos->x_advance) > position_fuzz || in hb_buffer_diff()
2150 (unsigned int) abs (buf_pos->y_advance - ref_pos->y_advance) > position_fuzz || in hb_buffer_diff()
2151 (unsigned int) abs (buf_pos->x_offset - ref_pos->x_offset) > position_fuzz || in hb_buffer_diff()
2152 (unsigned int) abs (buf_pos->y_offset - ref_pos->y_offset) > position_fuzz) in hb_buffer_diff()
2173 * @buffer: An #hb_buffer_t
2176 * @destroy: (nullable): The function to call when @user_data is not needed anymore
2183 hb_buffer_set_message_func (hb_buffer_t *buffer, in hb_buffer_set_message_func() argument
2187 if (unlikely (hb_object_is_immutable (buffer))) in hb_buffer_set_message_func()
2194 if (buffer->message_destroy) in hb_buffer_set_message_func()
2195 buffer->message_destroy (buffer->message_data); in hb_buffer_set_message_func()
2198 buffer->message_func = func; in hb_buffer_set_message_func()
2199 buffer->message_data = user_data; in hb_buffer_set_message_func()
2200 buffer->message_destroy = destroy; in hb_buffer_set_message_func()
2202 buffer->message_func = nullptr; in hb_buffer_set_message_func()
2203 buffer->message_data = nullptr; in hb_buffer_set_message_func()
2204 buffer->message_destroy = nullptr; in hb_buffer_set_message_func()
2216 bool ret = (bool) this->message_func (this, font, buf, this->message_data); in message_impl()
2218 message_depth--; in message_impl()