From 260fe985255c46fd2eb0aff378da8dccb5f2703f Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Mon, 16 Dec 2013 08:49:48 +0200 Subject: Update bundled HarfBuzz sources up to 0.9.25 Most important changes: - Myanmar, Indic, Javanese / Buginese shaper improvements - More aggressive shape-plan caching - Additional OpenType language tags Change-Id: I54ed62cfe936c06c18589d09ac119a0f5881a235 Reviewed-by: Lars Knoll --- src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh | 2 +- src/3rdparty/harfbuzz-ng/src/hb-blob.cc | 152 +++++- src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh | 10 +- .../harfbuzz-ng/src/hb-buffer-serialize.cc | 71 ++- src/3rdparty/harfbuzz-ng/src/hb-buffer.cc | 446 +++++++++++++++++- src/3rdparty/harfbuzz-ng/src/hb-buffer.h | 16 +- src/3rdparty/harfbuzz-ng/src/hb-common.cc | 161 ++++++- src/3rdparty/harfbuzz-ng/src/hb-common.h | 4 +- src/3rdparty/harfbuzz-ng/src/hb-face-private.hh | 1 - src/3rdparty/harfbuzz-ng/src/hb-face.cc | 172 ++++++- src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc | 10 + src/3rdparty/harfbuzz-ng/src/hb-font-private.hh | 15 +- src/3rdparty/harfbuzz-ng/src/hb-font.cc | 517 ++++++++++++++++++++- src/3rdparty/harfbuzz-ng/src/hb-font.h | 132 +++++- .../harfbuzz-ng/src/hb-open-type-private.hh | 2 - src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh | 2 +- src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh | 2 +- src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh | 2 +- .../harfbuzz-ng/src/hb-ot-layout-common-private.hh | 6 +- .../harfbuzz-ng/src/hb-ot-layout-gdef-table.hh | 10 +- .../harfbuzz-ng/src/hb-ot-layout-gpos-table.hh | 136 +++--- .../harfbuzz-ng/src/hb-ot-layout-gsub-table.hh | 95 +--- .../src/hb-ot-layout-gsubgpos-private.hh | 442 ++++++------------ .../harfbuzz-ng/src/hb-ot-layout-jstf-table.hh | 229 +++++++++ .../harfbuzz-ng/src/hb-ot-layout-private.hh | 403 ++++++++++------ src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc | 58 ++- src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h | 6 + src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc | 10 +- src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh | 2 +- src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh | 2 +- .../harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc | 21 +- .../src/hb-ot-shape-complex-indic-private.hh | 40 +- .../harfbuzz-ng/src/hb-ot-shape-complex-indic.cc | 358 +++++++++----- .../harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc | 35 +- .../harfbuzz-ng/src/hb-ot-shape-complex-private.hh | 4 +- .../harfbuzz-ng/src/hb-ot-shape-complex-sea.cc | 2 +- .../harfbuzz-ng/src/hb-ot-shape-fallback.cc | 73 ++- .../src/hb-ot-shape-normalize-private.hh | 2 - .../harfbuzz-ng/src/hb-ot-shape-normalize.cc | 29 +- .../harfbuzz-ng/src/hb-ot-shape-private.hh | 2 +- src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc | 156 ++++--- src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc | 315 ++++++++++--- src/3rdparty/harfbuzz-ng/src/hb-private.hh | 3 + src/3rdparty/harfbuzz-ng/src/hb-set-private.hh | 21 +- src/3rdparty/harfbuzz-ng/src/hb-set.cc | 244 ++++++++++ src/3rdparty/harfbuzz-ng/src/hb-set.h | 2 + .../harfbuzz-ng/src/hb-shape-plan-private.hh | 6 +- src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc | 173 ++++++- src/3rdparty/harfbuzz-ng/src/hb-shape.cc | 56 +++ src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh | 2 - src/3rdparty/harfbuzz-ng/src/hb-unicode.cc | 128 +++++ src/3rdparty/harfbuzz-ng/src/hb-unicode.h | 106 ++++- src/3rdparty/harfbuzz-ng/src/hb-version.h | 4 +- 53 files changed, 3885 insertions(+), 1013 deletions(-) create mode 100644 src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh (limited to 'src/3rdparty/harfbuzz-ng/src') diff --git a/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh index 9cc3bc5587..b5d64853ea 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh @@ -78,7 +78,7 @@ typedef int32_t hb_atomic_int_t; #if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100) #define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P)) #else -#if __ppc64__ || __x86_64__ +#if __ppc64__ || __x86_64__ || __arm64__ #define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P)) #else #define hb_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P)) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc index dfd134b776..d6acca0fca 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc @@ -29,7 +29,6 @@ #include "hb-private.hh" -#include "hb-blob.h" #include "hb-object-private.hh" #ifdef HAVE_SYS_MMAN_H @@ -76,6 +75,22 @@ _hb_blob_destroy_user_data (hb_blob_t *blob) } } +/** + * hb_blob_create: (Xconstructor) + * @data: (array length=length) (closure user_data) (destroy destroy) (scope notified) (transfer none): Pointer to blob data. + * @length: Length of @data in bytes. + * @mode: Memory mode for @data. + * @user_data: Data parameter to pass to @destroy. + * @destroy: Callback to call when @data is not needed anymore. + * + * Creates a new "blob" object wrapping @data. The @mode parameter is used + * to negotiate ownership and lifecycle of @data. + * + * Return value: New blob, or the empty blob if something failed or if @length is + * zero. Destroy with hb_blob_destroy(). + * + * Since: 1.0 + **/ hb_blob_t * hb_blob_create (const char *data, unsigned int length, @@ -109,6 +124,26 @@ hb_blob_create (const char *data, return blob; } +/** + * hb_blob_create_sub_blob: + * @parent: Parent blob. + * @offset: Start offset of sub-blob within @parent, in bytes. + * @length: Length of sub-blob. + * + * Returns a blob that represents a range of bytes in @parent. The new + * blob is always created with %HB_MEMORY_MODE_READONLY, meaning that it + * will never modify data in the parent blob. The parent data is not + * expected to be modified, and will result in undefined behavior if it + * is. + * + * Makes @parent immutable. + * + * Return value: New blob, or the empty blob if something failed or if + * @length is zero or @offset is beyond the end of @parent's data. Destroy + * with hb_blob_destroy(). + * + * Since: 1.0 + **/ hb_blob_t * hb_blob_create_sub_blob (hb_blob_t *parent, unsigned int offset, @@ -130,6 +165,17 @@ hb_blob_create_sub_blob (hb_blob_t *parent, return blob; } +/** + * hb_blob_get_empty: + * + * Returns the singleton empty blob. + * + * See TODO:link object types for more information. + * + * Return value: (transfer full): the empty blob. + * + * Since: 1.0 + **/ hb_blob_t * hb_blob_get_empty (void) { @@ -149,12 +195,36 @@ hb_blob_get_empty (void) return const_cast (&_hb_blob_nil); } +/** + * hb_blob_reference: (skip) + * @blob: a blob. + * + * Increases the reference count on @blob. + * + * See TODO:link object types for more information. + * + * Return value: @blob. + * + * Since: 1.0 + **/ hb_blob_t * hb_blob_reference (hb_blob_t *blob) { return hb_object_reference (blob); } +/** + * hb_blob_destroy: (skip) + * @blob: a blob. + * + * Descreases the reference count on @blob, and if it reaches zero, destroys + * @blob, freeing all memory, possibly calling the destroy-callback the blob + * was created for if it has not been called already. + * + * See TODO:link object types for more information. + * + * Since: 1.0 + **/ void hb_blob_destroy (hb_blob_t *blob) { @@ -165,6 +235,18 @@ hb_blob_destroy (hb_blob_t *blob) free (blob); } +/** + * hb_blob_set_user_data: (skip) + * @blob: a blob. + * @key: key for data to set. + * @data: data to set. + * @destroy: callback to call when @data is not needed anymore. + * @replace: whether to replace an existing data with the same key. + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_blob_set_user_data (hb_blob_t *blob, hb_user_data_key_t *key, @@ -175,6 +257,17 @@ hb_blob_set_user_data (hb_blob_t *blob, return hb_object_set_user_data (blob, key, data, destroy, replace); } +/** + * hb_blob_get_user_data: (skip) + * @blob: a blob. + * @key: key for data to get. + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ void * hb_blob_get_user_data (hb_blob_t *blob, hb_user_data_key_t *key) @@ -183,6 +276,14 @@ hb_blob_get_user_data (hb_blob_t *blob, } +/** + * hb_blob_make_immutable: + * @blob: a blob. + * + * + * + * Since: 1.0 + **/ void hb_blob_make_immutable (hb_blob_t *blob) { @@ -192,6 +293,16 @@ hb_blob_make_immutable (hb_blob_t *blob) blob->immutable = true; } +/** + * hb_blob_is_immutable: + * @blob: a blob. + * + * + * + * Return value: TODO + * + * Since: 1.0 + **/ hb_bool_t hb_blob_is_immutable (hb_blob_t *blob) { @@ -199,12 +310,33 @@ hb_blob_is_immutable (hb_blob_t *blob) } +/** + * hb_blob_get_length: + * @blob: a blob. + * + * + * + * Return value: the length of blob data in bytes. + * + * Since: 1.0 + **/ unsigned int hb_blob_get_length (hb_blob_t *blob) { return blob->length; } +/** + * hb_blob_get_data: + * @blob: a blob. + * @length: (out): + * + * + * + * Returns: (transfer none) (array length=length): + * + * Since: 1.0 + **/ const char * hb_blob_get_data (hb_blob_t *blob, unsigned int *length) { @@ -214,6 +346,22 @@ hb_blob_get_data (hb_blob_t *blob, unsigned int *length) return blob->data; } +/** + * hb_blob_get_data_writable: + * @blob: a blob. + * @length: (out): output length of the writable data. + * + * Tries to make blob data writable (possibly copying it) and + * return pointer to data. + * + * Fails if blob has been made immutable, or if memory allocation + * fails. + * + * Returns: (transfer none) (array length=length): Writable blob data, + * or %NULL if failed. + * + * Since: 1.0 + **/ char * hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length) { @@ -324,5 +472,3 @@ _try_writable (hb_blob_t *blob) return true; } - - diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh index a8cf770244..3a2b9ab481 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh @@ -31,7 +31,6 @@ #define HB_BUFFER_PRIVATE_HH #include "hb-private.hh" -#include "hb-buffer.h" #include "hb-object-private.hh" #include "hb-unicode-private.hh" @@ -103,6 +102,8 @@ struct hb_buffer_t { inline unsigned int backtrack_len (void) const { return have_output? out_len : idx; } + inline unsigned int lookahead_len (void) const + { return len - idx; } inline unsigned int next_serial (void) { return serial++; } HB_INTERNAL void allocate_var (unsigned int byte_i, unsigned int count, const char *owner); @@ -134,6 +135,7 @@ struct hb_buffer_t { HB_INTERNAL void output_info (const hb_glyph_info_t &glyph_info); /* Copies glyph at idx to output but doesn't advance idx */ HB_INTERNAL void copy_glyph (void); + HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */ /* Copies glyph at idx to output and advance idx. * If there's no output, just advance idx. */ inline void @@ -178,11 +180,13 @@ struct hb_buffer_t { HB_INTERNAL bool enlarge (unsigned int size); inline bool ensure (unsigned int size) - { return likely (size < allocated) ? true : enlarge (size); } + { return likely (!size || size < allocated) ? true : enlarge (size); } HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out); + HB_INTERNAL bool shift_forward (unsigned int count); - HB_INTERNAL void *get_scratch_buffer (unsigned int *size); + typedef long scratch_buffer_t; + HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size); inline void clear_context (unsigned int side) { context_len[side] = 0; } }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc index eac69000dd..4541db23bd 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc @@ -33,12 +33,32 @@ static const char *serialize_formats[] = { NULL }; +/** + * hb_buffer_serialize_list_formats: + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ const char ** hb_buffer_serialize_list_formats (void) { return serialize_formats; } +/** + * hb_buffer_serialize_format_from_string: + * @str: + * @len: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_buffer_serialize_format_t hb_buffer_serialize_format_from_string (const char *str, int len) { @@ -46,6 +66,16 @@ hb_buffer_serialize_format_from_string (const char *str, int len) return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020); } +/** + * hb_buffer_serialize_format_to_string: + * @format: + * + * + * + * Return value: + * + * Since: 1.0 + **/ const char * hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format) { @@ -116,9 +146,9 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer, *p++ = '}'; - if (buf_size > (p - b)) + unsigned int l = p - b; + if (buf_size > l) { - unsigned int l = p - b; memcpy (buf, b, l); buf += l; buf_size -= l; @@ -178,9 +208,9 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance)); } - if (buf_size > (p - b)) + unsigned int l = p - b; + if (buf_size > l) { - unsigned int l = p - b; memcpy (buf, b, l); buf += l; buf_size -= l; @@ -194,6 +224,24 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, } /* Returns number of items, starting at start, that were serialized. */ +/** + * hb_buffer_serialize_glyphs: + * @buffer: a buffer. + * @start: + * @end: + * @buf: (array length=buf_size): + * @buf_size: + * @buf_consumed: (out): + * @font: + * @format: + * @flags: + * + * + * + * Return value: + * + * Since: 1.0 + **/ unsigned int hb_buffer_serialize_glyphs (hb_buffer_t *buffer, unsigned int start, @@ -286,6 +334,21 @@ parse_int (const char *pp, const char *end, int32_t *pv) #include "hb-buffer-deserialize-json.hh" #include "hb-buffer-deserialize-text.hh" +/** + * hb_buffer_deserialize_glyphs: + * @buffer: a buffer. + * @buf: (array length=buf_len): + * @buf_len: + * @end_ptr: (out): + * @font: + * @format: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, const char *buf, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc index 340bd5351b..d6c6fcb8e6 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc @@ -139,7 +139,20 @@ hb_buffer_t::make_room_for (unsigned int num_in, return true; } -void * +bool +hb_buffer_t::shift_forward (unsigned int count) +{ + assert (have_output); + if (unlikely (!ensure (len + count))) return false; + + memmove (info + idx + count, info + idx, (len - idx) * sizeof (info[0])); + len += count; + idx += count; + + return true; +} + +hb_buffer_t::scratch_buffer_t * hb_buffer_t::get_scratch_buffer (unsigned int *size) { have_output = false; @@ -148,8 +161,9 @@ hb_buffer_t::get_scratch_buffer (unsigned int *size) out_len = 0; out_info = info; - *size = allocated * sizeof (pos[0]); - return pos; + assert ((uintptr_t) pos % sizeof (scratch_buffer_t) == 0); + *size = allocated * sizeof (pos[0]) / sizeof (scratch_buffer_t); + return (scratch_buffer_t *) (void *) pos; } @@ -345,6 +359,44 @@ hb_buffer_t::copy_glyph (void) out_len++; } +bool +hb_buffer_t::move_to (unsigned int i) +{ + if (!have_output) + { + assert (i <= len); + idx = i; + return true; + } + + assert (i <= out_len + (len - idx)); + + if (out_len < i) + { + unsigned int count = i - out_len; + if (unlikely (!make_room_for (count, count))) return false; + + memmove (out_info + out_len, info + idx, count * sizeof (out_info[0])); + idx += count; + out_len += count; + } + else if (out_len > i) + { + /* Tricky part: rewinding... */ + unsigned int count = out_len - i; + + if (unlikely (idx < count && !shift_forward (count + 32))) return false; + + assert (idx >= count); + + idx -= count; + out_len -= count; + memmove (info + idx, out_info + out_len, count * sizeof (out_info[0])); + } + + return true; +} + void hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index) { @@ -603,6 +655,15 @@ void hb_buffer_t::deallocate_var_all (void) /* Public API */ +/** + * hb_buffer_create: (Xconstructor) + * + * + * + * Return value: (transfer full) + * + * Since: 1.0 + **/ hb_buffer_t * hb_buffer_create (void) { @@ -616,6 +677,15 @@ hb_buffer_create (void) return buffer; } +/** + * hb_buffer_get_empty: + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_buffer_t * hb_buffer_get_empty (void) { @@ -637,12 +707,30 @@ hb_buffer_get_empty (void) return const_cast (&_hb_buffer_nil); } +/** + * hb_buffer_reference: (skip) + * @buffer: a buffer. + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_buffer_t * hb_buffer_reference (hb_buffer_t *buffer) { return hb_object_reference (buffer); } +/** + * hb_buffer_destroy: (skip) + * @buffer: a buffer. + * + * + * + * Since: 1.0 + **/ void hb_buffer_destroy (hb_buffer_t *buffer) { @@ -656,6 +744,20 @@ hb_buffer_destroy (hb_buffer_t *buffer) free (buffer); } +/** + * hb_buffer_set_user_data: (skip) + * @buffer: a buffer. + * @key: + * @data: + * @destroy: + * @replace: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_buffer_set_user_data (hb_buffer_t *buffer, hb_user_data_key_t *key, @@ -666,6 +768,17 @@ hb_buffer_set_user_data (hb_buffer_t *buffer, return hb_object_set_user_data (buffer, key, data, destroy, replace); } +/** + * hb_buffer_get_user_data: (skip) + * @buffer: a buffer. + * @key: + * + * + * + * Return value: + * + * Since: 1.0 + **/ void * hb_buffer_get_user_data (hb_buffer_t *buffer, hb_user_data_key_t *key) @@ -674,6 +787,15 @@ hb_buffer_get_user_data (hb_buffer_t *buffer, } +/** + * hb_buffer_set_content_type: + * @buffer: a buffer. + * @content_type: + * + * + * + * Since: 1.0 + **/ void hb_buffer_set_content_type (hb_buffer_t *buffer, hb_buffer_content_type_t content_type) @@ -681,6 +803,16 @@ hb_buffer_set_content_type (hb_buffer_t *buffer, buffer->content_type = content_type; } +/** + * hb_buffer_get_content_type: + * @buffer: a buffer. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_buffer_content_type_t hb_buffer_get_content_type (hb_buffer_t *buffer) { @@ -688,28 +820,56 @@ hb_buffer_get_content_type (hb_buffer_t *buffer) } +/** + * hb_buffer_set_unicode_funcs: + * @buffer: a buffer. + * @unicode_funcs: + * + * + * + * Since: 1.0 + **/ void hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, - hb_unicode_funcs_t *unicode) + hb_unicode_funcs_t *unicode_funcs) { if (unlikely (hb_object_is_inert (buffer))) return; - if (!unicode) - unicode = hb_unicode_funcs_get_default (); + if (!unicode_funcs) + unicode_funcs = hb_unicode_funcs_get_default (); - hb_unicode_funcs_reference (unicode); + hb_unicode_funcs_reference (unicode_funcs); hb_unicode_funcs_destroy (buffer->unicode); - buffer->unicode = unicode; + buffer->unicode = unicode_funcs; } +/** + * hb_buffer_get_unicode_funcs: + * @buffer: a buffer. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_unicode_funcs_t * hb_buffer_get_unicode_funcs (hb_buffer_t *buffer) { return buffer->unicode; } +/** + * hb_buffer_set_direction: + * @buffer: a buffer. + * @direction: + * + * + * + * Since: 1.0 + **/ void hb_buffer_set_direction (hb_buffer_t *buffer, hb_direction_t direction) @@ -721,12 +881,31 @@ hb_buffer_set_direction (hb_buffer_t *buffer, buffer->props.direction = direction; } +/** + * hb_buffer_get_direction: + * @buffer: a buffer. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_direction_t hb_buffer_get_direction (hb_buffer_t *buffer) { return buffer->props.direction; } +/** + * hb_buffer_set_script: + * @buffer: a buffer. + * @script: + * + * + * + * Since: 1.0 + **/ void hb_buffer_set_script (hb_buffer_t *buffer, hb_script_t script) @@ -737,12 +916,31 @@ hb_buffer_set_script (hb_buffer_t *buffer, buffer->props.script = script; } +/** + * hb_buffer_get_script: + * @buffer: a buffer. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_script_t hb_buffer_get_script (hb_buffer_t *buffer) { return buffer->props.script; } +/** + * hb_buffer_set_language: + * @buffer: a buffer. + * @language: + * + * + * + * Since: 1.0 + **/ void hb_buffer_set_language (hb_buffer_t *buffer, hb_language_t language) @@ -753,12 +951,31 @@ hb_buffer_set_language (hb_buffer_t *buffer, buffer->props.language = language; } +/** + * hb_buffer_get_language: + * @buffer: a buffer. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_language_t hb_buffer_get_language (hb_buffer_t *buffer) { return buffer->props.language; } +/** + * hb_buffer_set_segment_properties: + * @buffer: a buffer. + * @props: + * + * + * + * Since: 1.0 + **/ void hb_buffer_set_segment_properties (hb_buffer_t *buffer, const hb_segment_properties_t *props) @@ -769,6 +986,15 @@ hb_buffer_set_segment_properties (hb_buffer_t *buffer, buffer->props = *props; } +/** + * hb_buffer_get_segment_properties: + * @buffer: a buffer. + * @props: + * + * + * + * Since: 1.0 + **/ void hb_buffer_get_segment_properties (hb_buffer_t *buffer, hb_segment_properties_t *props) @@ -777,6 +1003,15 @@ hb_buffer_get_segment_properties (hb_buffer_t *buffer, } +/** + * hb_buffer_set_flags: + * @buffer: a buffer. + * @flags: + * + * + * + * Since: 1.0 + **/ void hb_buffer_set_flags (hb_buffer_t *buffer, hb_buffer_flags_t flags) @@ -787,6 +1022,16 @@ hb_buffer_set_flags (hb_buffer_t *buffer, buffer->flags = flags; } +/** + * hb_buffer_get_flags: + * @buffer: a buffer. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_buffer_flags_t hb_buffer_get_flags (hb_buffer_t *buffer) { @@ -794,30 +1039,77 @@ hb_buffer_get_flags (hb_buffer_t *buffer) } +/** + * hb_buffer_reset: + * @buffer: a buffer. + * + * + * + * Since: 1.0 + **/ void hb_buffer_reset (hb_buffer_t *buffer) { buffer->reset (); } +/** + * hb_buffer_clear_contents: + * @buffer: a buffer. + * + * + * + * Since: 1.0 + **/ void hb_buffer_clear_contents (hb_buffer_t *buffer) { buffer->clear (); } +/** + * hb_buffer_pre_allocate: + * @buffer: a buffer. + * @size: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size) { return buffer->ensure (size); } +/** + * hb_buffer_allocation_successful: + * @buffer: a buffer. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_buffer_allocation_successful (hb_buffer_t *buffer) { return !buffer->in_error; } +/** + * hb_buffer_add: + * @buffer: a buffer. + * @codepoint: + * @cluster: + * + * + * + * Since: 1.0 + **/ void hb_buffer_add (hb_buffer_t *buffer, hb_codepoint_t codepoint, @@ -827,6 +1119,17 @@ hb_buffer_add (hb_buffer_t *buffer, buffer->clear_context (1); } +/** + * hb_buffer_set_length: + * @buffer: a buffer. + * @length: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_buffer_set_length (hb_buffer_t *buffer, unsigned int length) @@ -847,19 +1150,43 @@ hb_buffer_set_length (hb_buffer_t *buffer, buffer->len = length; if (!length) + { + buffer->content_type = HB_BUFFER_CONTENT_TYPE_INVALID; buffer->clear_context (0); + } buffer->clear_context (1); return true; } +/** + * hb_buffer_get_length: + * @buffer: a buffer. + * + * Returns the number of items in the buffer. + * + * Return value: buffer length. + * + * Since: 1.0 + **/ unsigned int hb_buffer_get_length (hb_buffer_t *buffer) { return buffer->len; } -/* Return value valid as long as buffer not modified */ +/** + * hb_buffer_get_glyph_infos: + * @buffer: a buffer. + * @length: (out): output array length. + * + * Returns buffer glyph information array. Returned pointer + * is valid as long as buffer contents are not modified. + * + * Return value: (transfer none) (array length=length): buffer glyph information array. + * + * Since: 1.0 + **/ hb_glyph_info_t * hb_buffer_get_glyph_infos (hb_buffer_t *buffer, unsigned int *length) @@ -870,7 +1197,18 @@ hb_buffer_get_glyph_infos (hb_buffer_t *buffer, return (hb_glyph_info_t *) buffer->info; } -/* Return value valid as long as buffer not modified */ +/** + * hb_buffer_get_glyph_positions: + * @buffer: a buffer. + * @length: (out): output length. + * + * Returns buffer glyph position array. Returned pointer + * is valid as long as buffer contents are not modified. + * + * Return value: (transfer none) (array length=length): buffer glyph position array. + * + * Since: 1.0 + **/ hb_glyph_position_t * hb_buffer_get_glyph_positions (hb_buffer_t *buffer, unsigned int *length) @@ -884,18 +1222,60 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer, return (hb_glyph_position_t *) buffer->pos; } +/** + * hb_buffer_reverse: + * @buffer: a buffer. + * + * Reverses buffer contents. + * + * Since: 1.0 + **/ void hb_buffer_reverse (hb_buffer_t *buffer) { buffer->reverse (); } +/** + * hb_buffer_reverse_clusters: + * @buffer: a buffer. + * + * Reverses buffer clusters. That is, the buffer contents are + * reversed, then each cluster (consecutive items having the + * same cluster number) are reversed again. + * + * Since: 1.0 + **/ void hb_buffer_reverse_clusters (hb_buffer_t *buffer) { buffer->reverse_clusters (); } +/** + * hb_buffer_guess_segment_properties: + * @buffer: a buffer. + * + * Sets unset buffer segment properties based on buffer Unicode + * contents. If buffer is not empty, it must have content type + * %HB_BUFFER_CONTENT_TYPE_UNICODE. + * + * If buffer script is not set (ie. is %HB_SCRIPT_INVALID), it + * will be set to the Unicode script of the first character in + * the buffer that has a script other than %HB_SCRIPT_COMMON, + * %HB_SCRIPT_INHERITED, and %HB_SCRIPT_UNKNOWN. + * + * Next, if buffer direction is not set (ie. is %HB_DIRECTION_INVALID), + * it will be set to the natural horizontal direction of the + * buffer script as returned by hb_script_get_horizontal_direction(). + * + * Finally, if buffer language is not set (ie. is %HB_LANGUAGE_INVALID), + * it will be set to the process's default language as returned by + * hb_language_get_default(). This may change in the future by + * taking buffer script into consideration when choosing a language. + * + * Since: 1.0 + **/ void hb_buffer_guess_segment_properties (hb_buffer_t *buffer) { @@ -968,6 +1348,18 @@ hb_buffer_add_utf (hb_buffer_t *buffer, buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; } +/** + * hb_buffer_add_utf8: + * @buffer: a buffer. + * @text: (array length=text_length): + * @text_length: + * @item_offset: + * @item_length: + * + * + * + * Since: 1.0 + **/ void hb_buffer_add_utf8 (hb_buffer_t *buffer, const char *text, @@ -978,16 +1370,40 @@ hb_buffer_add_utf8 (hb_buffer_t *buffer, hb_buffer_add_utf (buffer, (const uint8_t *) text, text_length, item_offset, item_length); } +/** + * hb_buffer_add_utf16: + * @buffer: a buffer. + * @text: (array length=text_length): + * @text_length: + * @item_offset: + * @item_length: + * + * + * + * Since: 1.0 + **/ void hb_buffer_add_utf16 (hb_buffer_t *buffer, const uint16_t *text, int text_length, unsigned int item_offset, - int item_length) + int item_length) { hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length); } +/** + * hb_buffer_add_utf32: + * @buffer: a buffer. + * @text: (array length=text_length): + * @text_length: + * @item_offset: + * @item_length: + * + * + * + * Since: 1.0 + **/ void hb_buffer_add_utf32 (hb_buffer_t *buffer, const uint32_t *text, @@ -1054,6 +1470,14 @@ normalize_glyphs_cluster (hb_buffer_t *buffer, } } +/** + * hb_buffer_normalize_glyphs: + * @buffer: a buffer. + * + * + * + * Since: 1.0 + **/ void hb_buffer_normalize_glyphs (hb_buffer_t *buffer) { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h index 87c4ce58e8..3086851b01 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h @@ -172,10 +172,10 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer); typedef enum { /*< flags >*/ - HB_BUFFER_FLAG_DEFAULT = 0x00000000, - HB_BUFFER_FLAG_BOT = 0x00000001, /* Beginning-of-text */ - HB_BUFFER_FLAG_EOT = 0x00000002, /* End-of-text */ - HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004 + HB_BUFFER_FLAG_DEFAULT = 0x00000000u, + HB_BUFFER_FLAG_BOT = 0x00000001u, /* Beginning-of-text */ + HB_BUFFER_FLAG_EOT = 0x00000002u, /* End-of-text */ + HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u } hb_buffer_flags_t; void @@ -275,10 +275,10 @@ hb_buffer_normalize_glyphs (hb_buffer_t *buffer); */ typedef enum { /*< flags >*/ - HB_BUFFER_SERIALIZE_FLAG_DEFAULT = 0x00000000, - HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001, - HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002, - HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004 + HB_BUFFER_SERIALIZE_FLAG_DEFAULT = 0x00000000u, + HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001u, + HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002u, + HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u } hb_buffer_serialize_flags_t; typedef enum { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.cc b/src/3rdparty/harfbuzz-ng/src/hb-common.cc index 7c6d26290d..0fd790bc04 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-common.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-common.cc @@ -28,8 +28,6 @@ #include "hb-private.hh" -#include "hb-version.h" - #include "hb-mutex-private.hh" #include "hb-object-private.hh" @@ -57,25 +55,45 @@ _hb_options_init (void) /* hb_tag_t */ +/** + * hb_tag_from_string: + * @str: (array length=len): + * @len: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_tag_t -hb_tag_from_string (const char *s, int len) +hb_tag_from_string (const char *str, int len) { char tag[4]; unsigned int i; - if (!s || !len || !*s) + if (!str || !len || !*str) return HB_TAG_NONE; if (len < 0 || len > 4) len = 4; - for (i = 0; i < (unsigned) len && s[i]; i++) - tag[i] = s[i]; + for (i = 0; i < (unsigned) len && str[i]; i++) + tag[i] = str[i]; for (; i < 4; i++) tag[i] = ' '; return HB_TAG_CHAR4 (tag); } +/** + * hb_tag_to_string: + * @tag: + * @buf: (array fixed-size=4): + * + * + * + * Since: 1.0 + **/ void hb_tag_to_string (hb_tag_t tag, char *buf) { @@ -95,6 +113,17 @@ const char direction_strings[][4] = { "btt" }; +/** + * hb_direction_from_string: + * @str: (array length=len): + * @len: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_direction_t hb_direction_from_string (const char *str, int len) { @@ -112,6 +141,16 @@ hb_direction_from_string (const char *str, int len) return HB_DIRECTION_INVALID; } +/** + * hb_direction_to_string: + * @direction: + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ const char * hb_direction_to_string (hb_direction_t direction) { @@ -187,7 +226,7 @@ struct hb_language_item_t { return *this; } - void finish (void) { free (lang); } + void finish (void) { free ((void *) lang); } }; @@ -237,14 +276,27 @@ retry: } +/** + * hb_language_from_string: + * @str: (array length=len): + * @len: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_language_t hb_language_from_string (const char *str, int len) { + char strbuf[64]; + if (!str || !len || !*str) return HB_LANGUAGE_INVALID; - if (len >= 0) { - char strbuf[64]; + if (len >= 0) + { len = MIN (len, (int) sizeof (strbuf) - 1); str = (char *) memcpy (strbuf, str, len); strbuf[len] = '\0'; @@ -255,6 +307,16 @@ hb_language_from_string (const char *str, int len) return likely (item) ? item->lang : HB_LANGUAGE_INVALID; } +/** + * hb_language_to_string: + * @language: + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ const char * hb_language_to_string (hb_language_t language) { @@ -262,6 +324,15 @@ hb_language_to_string (hb_language_t language) return language->s; } +/** + * hb_language_get_default: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_language_t hb_language_get_default (void) { @@ -279,6 +350,16 @@ hb_language_get_default (void) /* hb_script_t */ +/** + * hb_script_from_iso15924_tag: + * @tag: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_script_t hb_script_from_iso15924_tag (hb_tag_t tag) { @@ -313,18 +394,49 @@ hb_script_from_iso15924_tag (hb_tag_t tag) return HB_SCRIPT_UNKNOWN; } +/** + * hb_script_from_string: + * @s: (array length=len): + * @len: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_script_t hb_script_from_string (const char *s, int len) { return hb_script_from_iso15924_tag (hb_tag_from_string (s, len)); } +/** + * hb_script_to_iso15924_tag: + * @script: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_tag_t hb_script_to_iso15924_tag (hb_script_t script) { return (hb_tag_t) script; } +/** + * hb_script_get_horizontal_direction: + * @script: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_direction_t hb_script_get_horizontal_direction (hb_script_t script) { @@ -409,6 +521,16 @@ hb_user_data_array_t::get (hb_user_data_key_t *key) /* hb_version */ +/** + * hb_version: + * @major: (out): Library major version component. + * @minor: (out): Library minor version component. + * @micro: (out): Library micro version component. + * + * Returns library version as three integer components. + * + * Since: 1.0 + **/ void hb_version (unsigned int *major, unsigned int *minor, @@ -419,12 +541,33 @@ hb_version (unsigned int *major, *micro = HB_VERSION_MICRO; } +/** + * hb_version_string: + * + * Returns library version as a string with three components. + * + * Return value: library version string. + * + * Since: 1.0 + **/ const char * hb_version_string (void) { return HB_VERSION_STRING; } +/** + * hb_version_check: + * @major: + * @minor: + * @micro: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_version_check (unsigned int major, unsigned int minor, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.h b/src/3rdparty/harfbuzz-ng/src/hb-common.h index 9079b2c046..e445504550 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-common.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-common.h @@ -90,7 +90,7 @@ typedef union _hb_var_int_t { typedef uint32_t hb_tag_t; -#define HB_TAG(a,b,c,d) ((hb_tag_t)((((uint8_t)(a))<<24)|(((uint8_t)(b))<<16)|(((uint8_t)(c))<<8)|((uint8_t)(d)))) +#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint8_t)(c1))<<24)|(((uint8_t)(c2))<<16)|(((uint8_t)(c3))<<8)|((uint8_t)(c4)))) #define HB_UNTAG(tag) ((uint8_t)((tag)>>24)), ((uint8_t)((tag)>>16)), ((uint8_t)((tag)>>8)), ((uint8_t)(tag)) #define HB_TAG_NONE HB_TAG(0,0,0,0) @@ -131,7 +131,7 @@ hb_direction_to_string (hb_direction_t direction); /* hb_language_t */ -typedef struct hb_language_impl_t *hb_language_t; +typedef const struct hb_language_impl_t *hb_language_t; /* len=-1 means str is NUL-terminated */ hb_language_t diff --git a/src/3rdparty/harfbuzz-ng/src/hb-face-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-face-private.hh index b33be0e5fc..6520d3dbdf 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-face-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-face-private.hh @@ -31,7 +31,6 @@ #include "hb-private.hh" -#include "hb-font.h" #include "hb-object-private.hh" #include "hb-shaper-private.hh" #include "hb-shape-plan-private.hh" diff --git a/src/3rdparty/harfbuzz-ng/src/hb-face.cc b/src/3rdparty/harfbuzz-ng/src/hb-face.cc index d8b9ed8c3f..71cf49a5bc 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-face.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-face.cc @@ -31,7 +31,6 @@ #include "hb-ot-layout-private.hh" #include "hb-font-private.hh" -#include "hb-blob.h" #include "hb-open-file-private.hh" #include "hb-ot-head-table.hh" #include "hb-ot-maxp-table.hh" @@ -68,6 +67,18 @@ const hb_face_t _hb_face_nil = { }; +/** + * hb_face_create_for_tables: + * @reference_table_func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Return value: (transfer full) + * + * Since: 1.0 + **/ hb_face_t * hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, void *user_data, @@ -137,6 +148,17 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void return blob; } +/** + * hb_face_create: (Xconstructor) + * @blob: + * @index: + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_face_t * hb_face_create (hb_blob_t *blob, unsigned int index) @@ -160,6 +182,15 @@ hb_face_create (hb_blob_t *blob, return face; } +/** + * hb_face_get_empty: + * + * + * + * Return value: (transfer full) + * + * Since: 1.0 + **/ hb_face_t * hb_face_get_empty (void) { @@ -167,12 +198,30 @@ hb_face_get_empty (void) } +/** + * hb_face_reference: (skip) + * @face: a face. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_face_t * hb_face_reference (hb_face_t *face) { return hb_object_reference (face); } +/** + * hb_face_destroy: (skip) + * @face: a face. + * + * + * + * Since: 1.0 + **/ void hb_face_destroy (hb_face_t *face) { @@ -196,6 +245,20 @@ hb_face_destroy (hb_face_t *face) free (face); } +/** + * hb_face_set_user_data: (skip) + * @face: a face. + * @key: + * @data: + * @destroy: + * @replace: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_face_set_user_data (hb_face_t *face, hb_user_data_key_t *key, @@ -206,6 +269,17 @@ hb_face_set_user_data (hb_face_t *face, return hb_object_set_user_data (face, key, data, destroy, replace); } +/** + * hb_face_get_user_data: (skip) + * @face: a face. + * @key: + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ void * hb_face_get_user_data (hb_face_t *face, hb_user_data_key_t *key) @@ -213,6 +287,14 @@ hb_face_get_user_data (hb_face_t *face, return hb_object_get_user_data (face, key); } +/** + * hb_face_make_immutable: + * @face: a face. + * + * + * + * Since: 1.0 + **/ void hb_face_make_immutable (hb_face_t *face) { @@ -222,6 +304,16 @@ hb_face_make_immutable (hb_face_t *face) face->immutable = true; } +/** + * hb_face_is_immutable: + * @face: a face. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_face_is_immutable (hb_face_t *face) { @@ -229,6 +321,17 @@ hb_face_is_immutable (hb_face_t *face) } +/** + * hb_face_reference_table: + * @face: a face. + * @tag: + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_blob_t * hb_face_reference_table (hb_face_t *face, hb_tag_t tag) @@ -236,12 +339,31 @@ hb_face_reference_table (hb_face_t *face, return face->reference_table (tag); } +/** + * hb_face_reference_blob: + * @face: a face. + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_blob_t * hb_face_reference_blob (hb_face_t *face) { return face->reference_table (HB_TAG_NONE); } +/** + * hb_face_set_index: + * @face: a face. + * @index: + * + * + * + * Since: 1.0 + **/ void hb_face_set_index (hb_face_t *face, unsigned int index) @@ -252,12 +374,31 @@ hb_face_set_index (hb_face_t *face, face->index = index; } +/** + * hb_face_get_index: + * @face: a face. + * + * + * + * Return value: + * + * Since: 1.0 + **/ unsigned int hb_face_get_index (hb_face_t *face) { return face->index; } +/** + * hb_face_set_upem: + * @face: a face. + * @upem: + * + * + * + * Since: 1.0 + **/ void hb_face_set_upem (hb_face_t *face, unsigned int upem) @@ -268,6 +409,16 @@ hb_face_set_upem (hb_face_t *face, face->upem = upem; } +/** + * hb_face_get_upem: + * @face: a face. + * + * + * + * Return value: + * + * Since: 1.0 + **/ unsigned int hb_face_get_upem (hb_face_t *face) { @@ -283,6 +434,15 @@ hb_face_t::load_upem (void) const hb_blob_destroy (head_blob); } +/** + * hb_face_set_glyph_count: + * @face: a face. + * @glyph_count: + * + * + * + * Since: 1.0 + **/ void hb_face_set_glyph_count (hb_face_t *face, unsigned int glyph_count) @@ -293,6 +453,16 @@ hb_face_set_glyph_count (hb_face_t *face, face->num_glyphs = glyph_count; } +/** + * hb_face_get_glyph_count: + * @face: a face. + * + * + * + * Return value: + * + * Since: 1.0 + **/ unsigned int hb_face_get_glyph_count (hb_face_t *face) { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc index 1a1fcfbda1..b894a4a47d 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc @@ -95,6 +95,16 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *features HB_UNUSED, unsigned int num_features HB_UNUSED) { + /* TODO + * + * - Apply fallback kern. + * - Handle Variation Selectors? + * - Apply normalization? + * + * This will make the fallback shaper into a dumb "TrueType" + * shaper which many people unfortunately still request. + */ + hb_codepoint_t space; font->get_glyph (' ', 0, &space); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-font-private.hh index 620d05e8f9..431d0477c2 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-font-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-font-private.hh @@ -31,7 +31,6 @@ #include "hb-private.hh" -#include "hb-font.h" #include "hb-object-private.hh" #include "hb-face-private.hh" #include "hb-shaper-private.hh" @@ -118,12 +117,12 @@ struct hb_font_t { /* Convert from parent-font user-space to our user-space */ inline hb_position_t parent_scale_x_distance (hb_position_t v) { if (unlikely (parent && parent->x_scale != x_scale)) - return v * (int64_t) this->x_scale / this->parent->x_scale; + return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale); return v; } inline hb_position_t parent_scale_y_distance (hb_position_t v) { if (unlikely (parent && parent->y_scale != y_scale)) - return v * (int64_t) this->y_scale / this->parent->y_scale; + return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale); return v; } inline hb_position_t parent_scale_x_position (hb_position_t v) { @@ -193,10 +192,10 @@ struct hb_font_t { klass->user_data.glyph_h_kerning); } - inline hb_position_t get_glyph_v_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) + inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph) { return klass->get.glyph_v_kerning (this, user_data, - left_glyph, right_glyph, + top_glyph, bottom_glyph, klass->user_data.glyph_v_kerning); } @@ -397,11 +396,7 @@ struct hb_font_t { } private: - inline hb_position_t em_scale (int16_t v, int scale) - { - unsigned int upem = face->get_upem (); - return (v * (int64_t) scale + upem / 2) / upem; - } + inline hb_position_t em_scale (int16_t v, int scale) { return (hb_position_t) (v * (int64_t) scale / face->get_upem ()); } }; #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-font.cc index c2f6f6ddd5..fc4c8ebf07 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-font.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-font.cc @@ -31,7 +31,6 @@ #include "hb-ot-layout-private.hh" #include "hb-font-private.hh" -#include "hb-blob.h" #include "hb-open-file-private.hh" #include "hb-ot-head-table.hh" #include "hb-ot-maxp-table.hh" @@ -230,6 +229,15 @@ static const hb_font_funcs_t _hb_font_funcs_nil = { }; +/** + * hb_font_funcs_create: (Xconstructor) + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_font_funcs_t * hb_font_funcs_create (void) { @@ -243,18 +251,45 @@ hb_font_funcs_create (void) return ffuncs; } +/** + * hb_font_funcs_get_empty: + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_font_funcs_t * hb_font_funcs_get_empty (void) { return const_cast (&_hb_font_funcs_nil); } +/** + * hb_font_funcs_reference: (skip) + * @ffuncs: font functions. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_font_funcs_t * hb_font_funcs_reference (hb_font_funcs_t *ffuncs) { return hb_object_reference (ffuncs); } +/** + * hb_font_funcs_destroy: (skip) + * @ffuncs: font functions. + * + * + * + * Since: 1.0 + **/ void hb_font_funcs_destroy (hb_font_funcs_t *ffuncs) { @@ -268,6 +303,20 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs) free (ffuncs); } +/** + * hb_font_funcs_set_user_data: (skip) + * @ffuncs: font functions. + * @key: + * @data: + * @destroy: + * @replace: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, hb_user_data_key_t *key, @@ -278,6 +327,17 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, return hb_object_set_user_data (ffuncs, key, data, destroy, replace); } +/** + * hb_font_funcs_get_user_data: (skip) + * @ffuncs: font functions. + * @key: + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ void * hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, hb_user_data_key_t *key) @@ -286,6 +346,14 @@ hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, } +/** + * hb_font_funcs_make_immutable: + * @ffuncs: font functions. + * + * + * + * Since: 1.0 + **/ void hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs) { @@ -295,6 +363,16 @@ hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs) ffuncs->immutable = true; } +/** + * hb_font_funcs_is_immutable: + * @ffuncs: font functions. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs) { @@ -336,6 +414,19 @@ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS /* Public getters */ +/** + * hb_font_get_glyph: + * @font: a font. + * @unicode: + * @variation_selector: + * @glyph: (out): + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_font_get_glyph (hb_font_t *font, hb_codepoint_t unicode, hb_codepoint_t variation_selector, @@ -344,6 +435,17 @@ hb_font_get_glyph (hb_font_t *font, return font->get_glyph (unicode, variation_selector, glyph); } +/** + * hb_font_get_glyph_h_advance: + * @font: a font. + * @glyph: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_position_t hb_font_get_glyph_h_advance (hb_font_t *font, hb_codepoint_t glyph) @@ -351,6 +453,17 @@ hb_font_get_glyph_h_advance (hb_font_t *font, return font->get_glyph_h_advance (glyph); } +/** + * hb_font_get_glyph_v_advance: + * @font: a font. + * @glyph: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_position_t hb_font_get_glyph_v_advance (hb_font_t *font, hb_codepoint_t glyph) @@ -358,6 +471,19 @@ hb_font_get_glyph_v_advance (hb_font_t *font, return font->get_glyph_v_advance (glyph); } +/** + * hb_font_get_glyph_h_origin: + * @font: a font. + * @glyph: + * @x: (out): + * @y: (out): + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_font_get_glyph_h_origin (hb_font_t *font, hb_codepoint_t glyph, @@ -366,6 +492,19 @@ hb_font_get_glyph_h_origin (hb_font_t *font, return font->get_glyph_h_origin (glyph, x, y); } +/** + * hb_font_get_glyph_v_origin: + * @font: a font. + * @glyph: + * @x: (out): + * @y: (out): + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_font_get_glyph_v_origin (hb_font_t *font, hb_codepoint_t glyph, @@ -374,6 +513,18 @@ hb_font_get_glyph_v_origin (hb_font_t *font, return font->get_glyph_v_origin (glyph, x, y); } +/** + * hb_font_get_glyph_h_kerning: + * @font: a font. + * @left_glyph: + * @right_glyph: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_position_t hb_font_get_glyph_h_kerning (hb_font_t *font, hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) @@ -381,13 +532,37 @@ hb_font_get_glyph_h_kerning (hb_font_t *font, return font->get_glyph_h_kerning (left_glyph, right_glyph); } +/** + * hb_font_get_glyph_v_kerning: + * @font: a font. + * @top_glyph: + * @bottom_glyph: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_position_t hb_font_get_glyph_v_kerning (hb_font_t *font, - hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) + hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph) { - return font->get_glyph_v_kerning (left_glyph, right_glyph); + return font->get_glyph_v_kerning (top_glyph, bottom_glyph); } +/** + * hb_font_get_glyph_extents: + * @font: a font. + * @glyph: + * @extents: (out): + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_font_get_glyph_extents (hb_font_t *font, hb_codepoint_t glyph, @@ -396,6 +571,20 @@ hb_font_get_glyph_extents (hb_font_t *font, return font->get_glyph_extents (glyph, extents); } +/** + * hb_font_get_glyph_contour_point: + * @font: a font. + * @glyph: + * @point_index: + * @x: (out): + * @y: (out): + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_font_get_glyph_contour_point (hb_font_t *font, hb_codepoint_t glyph, unsigned int point_index, @@ -404,6 +593,19 @@ hb_font_get_glyph_contour_point (hb_font_t *font, return font->get_glyph_contour_point (glyph, point_index, x, y); } +/** + * hb_font_get_glyph_name: + * @font: a font. + * @glyph: + * @name: (array length=size): + * @size: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_font_get_glyph_name (hb_font_t *font, hb_codepoint_t glyph, @@ -412,6 +614,19 @@ hb_font_get_glyph_name (hb_font_t *font, return font->get_glyph_name (glyph, name, size); } +/** + * hb_font_get_glyph_from_name: + * @font: a font. + * @name: (array length=len): + * @len: + * @glyph: (out): + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_font_get_glyph_from_name (hb_font_t *font, const char *name, int len, /* -1 means nul-terminated */ @@ -423,6 +638,18 @@ hb_font_get_glyph_from_name (hb_font_t *font, /* A bit higher-level, and with fallback */ +/** + * hb_font_get_glyph_advance_for_direction: + * @font: a font. + * @glyph: + * @direction: + * @x: (out): + * @y: (out): + * + * + * + * Since: 1.0 + **/ void hb_font_get_glyph_advance_for_direction (hb_font_t *font, hb_codepoint_t glyph, @@ -432,6 +659,18 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font, return font->get_glyph_advance_for_direction (glyph, direction, x, y); } +/** + * hb_font_get_glyph_origin_for_direction: + * @font: a font. + * @glyph: + * @direction: + * @x: (out): + * @y: (out): + * + * + * + * Since: 1.0 + **/ void hb_font_get_glyph_origin_for_direction (hb_font_t *font, hb_codepoint_t glyph, @@ -441,6 +680,18 @@ hb_font_get_glyph_origin_for_direction (hb_font_t *font, return font->get_glyph_origin_for_direction (glyph, direction, x, y); } +/** + * hb_font_add_glyph_origin_for_direction: + * @font: a font. + * @glyph: + * @direction: + * @x: (out): + * @y: (out): + * + * + * + * Since: 1.0 + **/ void hb_font_add_glyph_origin_for_direction (hb_font_t *font, hb_codepoint_t glyph, @@ -450,6 +701,18 @@ hb_font_add_glyph_origin_for_direction (hb_font_t *font, return font->add_glyph_origin_for_direction (glyph, direction, x, y); } +/** + * hb_font_subtract_glyph_origin_for_direction: + * @font: a font. + * @glyph: + * @direction: + * @x: (out): + * @y: (out): + * + * + * + * Since: 1.0 + **/ void hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, hb_codepoint_t glyph, @@ -459,6 +722,19 @@ hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, return font->subtract_glyph_origin_for_direction (glyph, direction, x, y); } +/** + * hb_font_get_glyph_kerning_for_direction: + * @font: a font. + * @first_glyph: + * @second_glyph: + * @direction: + * @x: (out): + * @y: (out): + * + * + * + * Since: 1.0 + **/ void hb_font_get_glyph_kerning_for_direction (hb_font_t *font, hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, @@ -468,6 +744,19 @@ hb_font_get_glyph_kerning_for_direction (hb_font_t *font, return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y); } +/** + * hb_font_get_glyph_extents_for_origin: + * @font: a font. + * @glyph: + * @direction: + * @extents: (out): + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_font_get_glyph_extents_for_origin (hb_font_t *font, hb_codepoint_t glyph, @@ -477,6 +766,21 @@ hb_font_get_glyph_extents_for_origin (hb_font_t *font, return font->get_glyph_extents_for_origin (glyph, direction, extents); } +/** + * hb_font_get_glyph_contour_point_for_origin: + * @font: a font. + * @glyph: + * @point_index: + * @direction: + * @x: (out): + * @y: (out): + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_font_get_glyph_contour_point_for_origin (hb_font_t *font, hb_codepoint_t glyph, unsigned int point_index, @@ -487,6 +791,17 @@ hb_font_get_glyph_contour_point_for_origin (hb_font_t *font, } /* Generates gidDDD if glyph has no name. */ +/** + * hb_font_glyph_to_string: + * @font: a font. + * @glyph: + * @s: (array length=size): + * @size: + * + * + * + * Since: 1.0 + **/ void hb_font_glyph_to_string (hb_font_t *font, hb_codepoint_t glyph, @@ -496,6 +811,19 @@ hb_font_glyph_to_string (hb_font_t *font, } /* Parses gidDDD and uniUUUU strings automatically. */ +/** + * hb_font_glyph_from_string: + * @font: a font. + * @s: (array length=len): + * @len: + * @glyph: (out): + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_font_glyph_from_string (hb_font_t *font, const char *s, int len, /* -1 means nul-terminated */ @@ -509,6 +837,16 @@ hb_font_glyph_from_string (hb_font_t *font, * hb_font_t */ +/** + * hb_font_create: (Xconstructor) + * @face: a face. + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_font_t * hb_font_create (hb_face_t *face) { @@ -528,6 +866,16 @@ hb_font_create (hb_face_t *face) return font; } +/** + * hb_font_create_sub_font: + * @parent: parent font. + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_font_t * hb_font_create_sub_font (hb_font_t *parent) { @@ -550,6 +898,15 @@ hb_font_create_sub_font (hb_font_t *parent) return font; } +/** + * hb_font_get_empty: + * + * + * + * Return value: (transfer full) + * + * Since: 1.0 + **/ hb_font_t * hb_font_get_empty (void) { @@ -581,12 +938,30 @@ hb_font_get_empty (void) return const_cast (&_hb_font_nil); } +/** + * hb_font_reference: (skip) + * @font: a font. + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_font_t * hb_font_reference (hb_font_t *font) { return hb_object_reference (font); } +/** + * hb_font_destroy: (skip) + * @font: a font. + * + * + * + * Since: 1.0 + **/ void hb_font_destroy (hb_font_t *font) { @@ -606,6 +981,20 @@ hb_font_destroy (hb_font_t *font) free (font); } +/** + * hb_font_set_user_data: (skip) + * @font: a font. + * @key: + * @data: + * @destroy: + * @replace: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_font_set_user_data (hb_font_t *font, hb_user_data_key_t *key, @@ -616,6 +1005,17 @@ hb_font_set_user_data (hb_font_t *font, return hb_object_set_user_data (font, key, data, destroy, replace); } +/** + * hb_font_get_user_data: (skip) + * @font: a font. + * @key: + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ void * hb_font_get_user_data (hb_font_t *font, hb_user_data_key_t *key) @@ -623,6 +1023,14 @@ hb_font_get_user_data (hb_font_t *font, return hb_object_get_user_data (font, key); } +/** + * hb_font_make_immutable: + * @font: a font. + * + * + * + * Since: 1.0 + **/ void hb_font_make_immutable (hb_font_t *font) { @@ -632,18 +1040,48 @@ hb_font_make_immutable (hb_font_t *font) font->immutable = true; } +/** + * hb_font_is_immutable: + * @font: a font. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_font_is_immutable (hb_font_t *font) { return font->immutable; } +/** + * hb_font_get_parent: + * @font: a font. + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ hb_font_t * hb_font_get_parent (hb_font_t *font) { return font->parent; } +/** + * hb_font_get_face: + * @font: a font. + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ hb_face_t * hb_font_get_face (hb_font_t *font) { @@ -651,15 +1089,26 @@ hb_font_get_face (hb_font_t *font) } +/** + * hb_font_set_funcs: + * @font: a font. + * @klass: (closure font_data) (destroy destroy) (scope notified): + * @font_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_font_set_funcs (hb_font_t *font, hb_font_funcs_t *klass, - void *user_data, + void *font_data, hb_destroy_func_t destroy) { if (font->immutable) { if (destroy) - destroy (user_data); + destroy (font_data); return; } @@ -672,30 +1121,50 @@ hb_font_set_funcs (hb_font_t *font, hb_font_funcs_reference (klass); hb_font_funcs_destroy (font->klass); font->klass = klass; - font->user_data = user_data; + font->user_data = font_data; font->destroy = destroy; } +/** + * hb_font_set_funcs_data: + * @font: a font. + * @font_data: (destroy destroy) (scope notified): + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_font_set_funcs_data (hb_font_t *font, - void *user_data, + void *font_data, hb_destroy_func_t destroy) { /* Destroy user_data? */ if (font->immutable) { if (destroy) - destroy (user_data); + destroy (font_data); return; } if (font->destroy) font->destroy (font->user_data); - font->user_data = user_data; + font->user_data = font_data; font->destroy = destroy; } +/** + * hb_font_set_scale: + * @font: a font. + * @x_scale: + * @y_scale: + * + * + * + * Since: 1.0 + **/ void hb_font_set_scale (hb_font_t *font, int x_scale, @@ -708,6 +1177,16 @@ hb_font_set_scale (hb_font_t *font, font->y_scale = y_scale; } +/** + * hb_font_get_scale: + * @font: a font. + * @x_scale: (out): + * @y_scale: (out): + * + * + * + * Since: 1.0 + **/ void hb_font_get_scale (hb_font_t *font, int *x_scale, @@ -717,6 +1196,16 @@ hb_font_get_scale (hb_font_t *font, if (y_scale) *y_scale = font->y_scale; } +/** + * hb_font_set_ppem: + * @font: a font. + * @x_ppem: + * @y_ppem: + * + * + * + * Since: 1.0 + **/ void hb_font_set_ppem (hb_font_t *font, unsigned int x_ppem, @@ -729,6 +1218,16 @@ hb_font_set_ppem (hb_font_t *font, font->y_ppem = y_ppem; } +/** + * hb_font_get_ppem: + * @font: a font. + * @x_ppem: (out): + * @y_ppem: (out): + * + * + * + * Since: 1.0 + **/ void hb_font_get_ppem (hb_font_t *font, unsigned int *x_ppem, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.h b/src/3rdparty/harfbuzz-ng/src/hb-font.h index 3a0c001b98..7273db43ed 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-font.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-font.h @@ -139,54 +139,180 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void * /* func setters */ +/** + * hb_font_funcs_set_glyph_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, - hb_font_get_glyph_func_t glyph_func, + hb_font_get_glyph_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_font_funcs_set_glyph_h_advance_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_h_advance_func_t func, void *user_data, hb_destroy_func_t destroy); + +/** + * hb_font_funcs_set_glyph_v_advance_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_v_advance_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_font_funcs_set_glyph_h_origin_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_h_origin_func_t func, void *user_data, hb_destroy_func_t destroy); + +/** + * hb_font_funcs_set_glyph_v_origin_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_v_origin_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_font_funcs_set_glyph_h_kerning_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_h_kerning_func_t func, void *user_data, hb_destroy_func_t destroy); + +/** + * hb_font_funcs_set_glyph_v_kerning_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_v_kerning_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_font_funcs_set_glyph_extents_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_extents_func_t func, void *user_data, hb_destroy_func_t destroy); + +/** + * hb_font_funcs_set_glyph_contour_point_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_contour_point_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_font_funcs_set_glyph_name_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs, - hb_font_get_glyph_name_func_t glyph_func, + hb_font_get_glyph_name_func_t func, void *user_data, hb_destroy_func_t destroy); + +/** + * hb_font_funcs_set_glyph_from_name_func: + * @ffuncs: font functions. + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs, - hb_font_get_glyph_from_name_func_t glyph_func, + hb_font_get_glyph_from_name_func_t func, void *user_data, hb_destroy_func_t destroy); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh index ee3a21dc3b..437ecd57f8 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh @@ -31,8 +31,6 @@ #include "hb-private.hh" -#include "hb-blob.h" - namespace OT { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh index 3a9451295d..0285f0cf31 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh @@ -43,7 +43,7 @@ namespace OT { struct head { - static const hb_tag_t Tag = HB_OT_TAG_head; + static const hb_tag_t tableTag = HB_OT_TAG_head; inline unsigned int get_upem (void) const { unsigned int upem = unitsPerEm; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh index 2b89c4e020..611de8a666 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh @@ -42,7 +42,7 @@ namespace OT { struct hhea { - static const hb_tag_t Tag = HB_OT_TAG_hhea; + static const hb_tag_t tableTag = HB_OT_TAG_hhea; inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (this); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh index b94337d0be..d107cf990a 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh @@ -50,7 +50,7 @@ struct LongHorMetric struct hmtx { - static const hb_tag_t Tag = HB_OT_TAG_hmtx; + static const hb_tag_t tableTag = HB_OT_TAG_hmtx; inline bool sanitize (hb_sanitize_context_t *c) { TRACE_SANITIZE (this); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh index 2f6e80468e..02d0d0f87c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh @@ -39,6 +39,7 @@ namespace OT { #define NOT_COVERED ((unsigned int) -1) #define MAX_NESTING_LEVEL 8 +#define MAX_CONTEXT_LENGTH 64 @@ -376,7 +377,7 @@ struct FeatureParamsStylisticSet return TRACE_RETURN (c->check_struct (this)); } - USHORT minorVersion; /* (set to 0): This corresponds to a “minor” + USHORT version; /* (set to 0): This corresponds to a “minor” * version number. Additional data may be * added to the end of this Feature Parameters * table in the future. */ @@ -399,6 +400,7 @@ struct FeatureParamsStylisticSet DEFINE_SIZE_STATIC (4); }; +/* http://www.microsoft.com/typography/otspec/features_ae.htm#cv01-cv99 */ struct FeatureParamsCharacterVariants { inline bool sanitize (hb_sanitize_context_t *c) { @@ -1111,7 +1113,7 @@ struct Device if (!pixels) return 0; - return pixels * (int64_t) scale / ppem; + return (int) (pixels * (int64_t) scale / ppem); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh index ff2d09c51f..389cbb9e39 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh @@ -324,7 +324,7 @@ struct MarkGlyphSets struct GDEF { - static const hb_tag_t Tag = HB_OT_TAG_GDEF; + static const hb_tag_t tableTag = HB_OT_TAG_GDEF; enum GlyphClasses { UnclassifiedGlyph = 0, @@ -383,12 +383,14 @@ struct GDEF { unsigned int klass = get_glyph_class (glyph); + ASSERT_STATIC ((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs); + ASSERT_STATIC ((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures); + ASSERT_STATIC ((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks); + switch (klass) { - default: - case UnclassifiedGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_UNCLASSIFIED; + default: return 0; case BaseGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH; case LigatureGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE; - case ComponentGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_COMPONENT; case MarkGlyph: klass = get_mark_attachment_type (glyph); return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh index 2cf90b7b5f..5e4326ef0c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh @@ -390,6 +390,7 @@ struct MarkArray : ArrayOf /* Array of MarkRecords--in Coverage orde unsigned int glyph_pos) const { TRACE_APPLY (this); + hb_buffer_t *buffer = c->buffer; const MarkRecord &record = ArrayOf::operator[](mark_index); unsigned int mark_class = record.klass; @@ -402,15 +403,15 @@ struct MarkArray : ArrayOf /* Array of MarkRecords--in Coverage orde hb_position_t mark_x, mark_y, base_x, base_y; - mark_anchor.get_anchor (c->font, c->buffer->cur().codepoint, &mark_x, &mark_y); - glyph_anchor.get_anchor (c->font, c->buffer->info[glyph_pos].codepoint, &base_x, &base_y); + mark_anchor.get_anchor (c->font, buffer->cur().codepoint, &mark_x, &mark_y); + glyph_anchor.get_anchor (c->font, buffer->info[glyph_pos].codepoint, &base_x, &base_y); - hb_glyph_position_t &o = c->buffer->cur_pos(); + hb_glyph_position_t &o = buffer->cur_pos(); o.x_offset = base_x - mark_x; o.y_offset = base_y - mark_y; - o.attach_lookback() = c->buffer->idx - glyph_pos; + o.attach_lookback() = buffer->idx - glyph_pos; - c->buffer->idx++; + buffer->idx++; return TRACE_RETURN (true); } @@ -439,13 +440,14 @@ struct SinglePosFormat1 inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (this); - unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + hb_buffer_t *buffer = c->buffer; + unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); valueFormat.apply_value (c->font, c->direction, this, - values, c->buffer->cur_pos()); + values, buffer->cur_pos()); - c->buffer->idx++; + buffer->idx++; return TRACE_RETURN (true); } @@ -484,16 +486,17 @@ struct SinglePosFormat2 inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (this); - unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + hb_buffer_t *buffer = c->buffer; + unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); if (likely (index >= valueCount)) return TRACE_RETURN (false); valueFormat.apply_value (c->font, c->direction, this, &values[index * valueFormat.get_len ()], - c->buffer->cur_pos()); + buffer->cur_pos()); - c->buffer->idx++; + buffer->idx++; return TRACE_RETURN (true); } @@ -588,6 +591,7 @@ struct PairSet unsigned int pos) const { TRACE_APPLY (this); + hb_buffer_t *buffer = c->buffer; unsigned int len1 = valueFormats[0].get_len (); unsigned int len2 = valueFormats[1].get_len (); unsigned int record_size = USHORT::static_size * (1 + len1 + len2); @@ -597,15 +601,15 @@ struct PairSet for (unsigned int i = 0; i < count; i++) { /* TODO bsearch */ - if (c->buffer->info[pos].codepoint == record->secondGlyph) + if (buffer->info[pos].codepoint == record->secondGlyph) { valueFormats[0].apply_value (c->font, c->direction, this, - &record->values[0], c->buffer->cur_pos()); + &record->values[0], buffer->cur_pos()); valueFormats[1].apply_value (c->font, c->direction, this, - &record->values[len1], c->buffer->pos[pos]); + &record->values[len1], buffer->pos[pos]); if (len2) pos++; - c->buffer->idx = pos; + buffer->idx = pos; return TRACE_RETURN (true); } record = &StructAtOffset (record, record_size); @@ -659,10 +663,11 @@ struct PairPosFormat1 inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (this); - hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); + hb_buffer_t *buffer = c->buffer; + hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, 1); if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); - unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); if (!skippy_iter.next ()) return TRACE_RETURN (false); @@ -729,10 +734,11 @@ struct PairPosFormat2 inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (this); - hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); + hb_buffer_t *buffer = c->buffer; + hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, 1); if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); - unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint); + unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); if (likely (index == NOT_COVERED)) return TRACE_RETURN (false); if (!skippy_iter.next ()) return TRACE_RETURN (false); @@ -741,19 +747,19 @@ struct PairPosFormat2 unsigned int len2 = valueFormat2.get_len (); unsigned int record_len = len1 + len2; - unsigned int klass1 = (this+classDef1).get_class (c->buffer->cur().codepoint); - unsigned int klass2 = (this+classDef2).get_class (c->buffer->info[skippy_iter.idx].codepoint); + unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint); + unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return TRACE_RETURN (false); const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; valueFormat1.apply_value (c->font, c->direction, this, - v, c->buffer->cur_pos()); + v, buffer->cur_pos()); valueFormat2.apply_value (c->font, c->direction, this, - v + len1, c->buffer->pos[skippy_iter.idx]); + v + len1, buffer->pos[skippy_iter.idx]); - c->buffer->idx = skippy_iter.idx; + buffer->idx = skippy_iter.idx; if (len2) - c->buffer->idx++; + buffer->idx++; return TRACE_RETURN (true); } @@ -875,29 +881,30 @@ struct CursivePosFormat1 inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (this); + hb_buffer_t *buffer = c->buffer; /* We don't handle mark glyphs here. */ - if (c->buffer->cur().glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK) return TRACE_RETURN (false); + if (unlikely (_hb_glyph_info_is_mark (&buffer->cur()))) return TRACE_RETURN (false); - hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1); + hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, 1); if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); - const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (c->buffer->cur().codepoint)]; + const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)]; if (!this_record.exitAnchor) return TRACE_RETURN (false); if (!skippy_iter.next ()) return TRACE_RETURN (false); - const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage (c->buffer->info[skippy_iter.idx].codepoint)]; + const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)]; if (!next_record.entryAnchor) return TRACE_RETURN (false); - unsigned int i = c->buffer->idx; + unsigned int i = buffer->idx; unsigned int j = skippy_iter.idx; hb_position_t entry_x, entry_y, exit_x, exit_y; - (this+this_record.exitAnchor).get_anchor (c->font, c->buffer->info[i].codepoint, &exit_x, &exit_y); - (this+next_record.entryAnchor).get_anchor (c->font, c->buffer->info[j].codepoint, &entry_x, &entry_y); + (this+this_record.exitAnchor).get_anchor (c->font, buffer->info[i].codepoint, &exit_x, &exit_y); + (this+next_record.entryAnchor).get_anchor (c->font, buffer->info[j].codepoint, &entry_x, &entry_y); - hb_glyph_position_t *pos = c->buffer->pos; + hb_glyph_position_t *pos = buffer->pos; hb_position_t d; /* Main-direction adjustment */ @@ -950,7 +957,7 @@ struct CursivePosFormat1 pos[j].x_offset = exit_x - entry_x; } - c->buffer->idx = j; + buffer->idx = j; return TRACE_RETURN (true); } @@ -1022,23 +1029,24 @@ struct MarkBasePosFormat1 inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (this); - unsigned int mark_index = (this+markCoverage).get_coverage (c->buffer->cur().codepoint); + hb_buffer_t *buffer = c->buffer; + unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint); if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false); /* now we search backwards for a non-mark glyph */ - hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1); + hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, buffer->idx, 1); skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); do { if (!skippy_iter.prev ()) return TRACE_RETURN (false); /* We only want to attach to the first of a MultipleSubst sequence. Reject others. */ - if (0 == get_lig_comp (c->buffer->info[skippy_iter.idx])) break; + if (0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx])) break; skippy_iter.reject (); } while (1); - /* The following assertion is too strong, so we've disabled it. */ - if (!(c->buffer->info[skippy_iter.idx].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH)) {/*return TRACE_RETURN (false);*/} + /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */ + if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { /*return TRACE_RETURN (false);*/ } - unsigned int base_index = (this+baseCoverage).get_coverage (c->buffer->info[skippy_iter.idx].codepoint); + unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint); if (base_index == NOT_COVERED) return TRACE_RETURN (false); return TRACE_RETURN ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx)); @@ -1125,19 +1133,20 @@ struct MarkLigPosFormat1 inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (this); - unsigned int mark_index = (this+markCoverage).get_coverage (c->buffer->cur().codepoint); + hb_buffer_t *buffer = c->buffer; + unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint); if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false); /* now we search backwards for a non-mark glyph */ - hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1); + hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, buffer->idx, 1); skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks); if (!skippy_iter.prev ()) return TRACE_RETURN (false); - /* The following assertion is too strong, so we've disabled it. */ - if (!(c->buffer->info[skippy_iter.idx].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE)) {/*return TRACE_RETURN (false);*/} + /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */ + if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { /*return TRACE_RETURN (false);*/ } unsigned int j = skippy_iter.idx; - unsigned int lig_index = (this+ligatureCoverage).get_coverage (c->buffer->info[j].codepoint); + unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint); if (lig_index == NOT_COVERED) return TRACE_RETURN (false); const LigatureArray& lig_array = this+ligatureArray; @@ -1152,11 +1161,11 @@ struct MarkLigPosFormat1 * can directly use the component index. If not, we attach the mark * glyph to the last component of the ligature. */ unsigned int comp_index; - unsigned int lig_id = get_lig_id (c->buffer->info[j]); - unsigned int mark_id = get_lig_id (c->buffer->cur()); - unsigned int mark_comp = get_lig_comp (c->buffer->cur()); + unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]); + unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur()); + unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur()); if (lig_id && lig_id == mark_id && mark_comp > 0) - comp_index = MIN (comp_count, get_lig_comp (c->buffer->cur())) - 1; + comp_index = MIN (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1; else comp_index = comp_count - 1; @@ -1240,22 +1249,23 @@ struct MarkMarkPosFormat1 inline bool apply (hb_apply_context_t *c) const { TRACE_APPLY (this); - unsigned int mark1_index = (this+mark1Coverage).get_coverage (c->buffer->cur().codepoint); + hb_buffer_t *buffer = c->buffer; + unsigned int mark1_index = (this+mark1Coverage).get_coverage (buffer->cur().codepoint); if (likely (mark1_index == NOT_COVERED)) return TRACE_RETURN (false); /* now we search backwards for a suitable mark glyph until a non-mark glyph */ - hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1); + hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, buffer->idx, 1); skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags); if (!skippy_iter.prev ()) return TRACE_RETURN (false); - if (!(c->buffer->info[skippy_iter.idx].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) { return TRACE_RETURN (false); } + if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])) { return TRACE_RETURN (false); } unsigned int j = skippy_iter.idx; - unsigned int id1 = get_lig_id (c->buffer->cur()); - unsigned int id2 = get_lig_id (c->buffer->info[j]); - unsigned int comp1 = get_lig_comp (c->buffer->cur()); - unsigned int comp2 = get_lig_comp (c->buffer->info[j]); + unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur()); + unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]); + unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur()); + unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]); if (likely (id1 == id2)) { if (id1 == 0) /* Marks belonging to the same base. */ @@ -1273,7 +1283,7 @@ struct MarkMarkPosFormat1 return TRACE_RETURN (false); good: - unsigned int mark2_index = (this+mark2Coverage).get_coverage (c->buffer->info[j].codepoint); + unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint); if (mark2_index == NOT_COVERED) return TRACE_RETURN (false); return TRACE_RETURN ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j)); @@ -1434,12 +1444,6 @@ struct PosLookup : Lookup return false; } - inline hb_is_inplace_context_t::return_t is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - return TRACE_RETURN (true); - } - inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); @@ -1505,7 +1509,7 @@ typedef OffsetListOf PosLookupList; struct GPOS : GSUBGPOS { - static const hb_tag_t Tag = HB_OT_TAG_GPOS; + static const hb_tag_t tableTag = HB_OT_TAG_GPOS; inline const PosLookup& get_lookup (unsigned int i) const { return CastR (GSUBGPOS::get_lookup (i)); } @@ -1591,9 +1595,7 @@ GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer) for (unsigned int i = 0; i < len; i++) fix_mark_attachment (pos, i, direction); - HB_BUFFER_DEALLOCATE_VAR (buffer, syllable); - HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props); - HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props); + _hb_buffer_deallocate_gsubgpos_vars (buffer); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh index 6ab1a2b921..76b4f33c70 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh @@ -37,12 +37,6 @@ namespace OT { struct SingleSubstFormat1 { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -121,12 +115,6 @@ struct SingleSubstFormat1 struct SingleSubstFormat2 { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -263,13 +251,6 @@ struct SingleSubst struct Sequence { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - /* For len==0 we don't do anything, so it's harmless. */ - return TRACE_RETURN (substitute.len <= 1); - } - inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -291,8 +272,8 @@ struct Sequence TRACE_APPLY (this); if (unlikely (!substitute.len)) return TRACE_RETURN (false); - unsigned int klass = c->buffer->cur().glyph_props() & - HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE ? HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0; + unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ? + HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0; unsigned int count = substitute.len; if (count == 1) /* Special-case to make it in-place. */ { @@ -301,7 +282,7 @@ struct Sequence else { for (unsigned int i = 0; i < count; i++) { - set_lig_props_for_component (c->buffer->cur(), i); + _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i); c->output_glyph (substitute.array[i], klass); } c->buffer->skip_glyph (); @@ -334,18 +315,6 @@ struct Sequence struct MultipleSubstFormat1 { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - /* Some tools generate MultipleSubst with each substitute having length 1! - * So, check them. */ - unsigned int count = sequence.len; - for (unsigned int i = 0; i < count; i++) - if (!(this+sequence[i]).is_inplace (c)) - return TRACE_RETURN (false); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -471,12 +440,6 @@ typedef ArrayOf AlternateSet; /* Array of alternate GlyphIDs--in struct AlternateSubstFormat1 { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -663,27 +626,26 @@ struct Ligature unsigned int count = component.len; if (unlikely (count < 1)) return TRACE_RETURN (false); - unsigned int end_offset = 0; bool is_mark_ligature = false; unsigned int total_component_count = 0; + unsigned int match_length = 0; + unsigned int match_positions[MAX_CONTEXT_LENGTH]; + if (likely (!match_input (c, count, &component[1], match_glyph, NULL, - &end_offset, + &match_length, + match_positions, &is_mark_ligature, &total_component_count))) return TRACE_RETURN (false); - /* Deal, we are forming the ligature. */ - c->buffer->merge_clusters (c->buffer->idx, c->buffer->idx + end_offset); - ligate_input (c, count, - &component[1], - match_glyph, - NULL, + match_positions, + match_length, ligGlyph, is_mark_ligature, total_component_count); @@ -797,12 +759,6 @@ struct LigatureSet struct LigatureSubstFormat1 { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - return TRACE_RETURN (false); - } - inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -951,12 +907,6 @@ struct ExtensionSubst : Extension struct ReverseChainSingleSubstFormat1 { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -1038,7 +988,9 @@ struct ReverseChainSingleSubstFormat1 1)) { c->replace_glyph_inplace (substitute[index]); - c->buffer->idx--; /* Reverse! */ + /* Note: We DON'T decrease buffer->idx. The main loop does it + * for us. This is useful for preventing surprises if someone + * calls us through a Context lookup. */ return TRACE_RETURN (true); } @@ -1194,13 +1146,6 @@ struct SubstLookup : Lookup return lookup_type_is_reverse (type); } - inline hb_is_inplace_context_t::return_t is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - c->set_recurse_func (dispatch_recurse_func); - return TRACE_RETURN (dispatch (c)); - } - inline hb_closure_context_t::return_t closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -1351,7 +1296,7 @@ typedef OffsetListOf SubstLookupList; struct GSUB : GSUBGPOS { - static const hb_tag_t Tag = HB_OT_TAG_GSUB; + static const hb_tag_t tableTag = HB_OT_TAG_GSUB; inline const SubstLookup& get_lookup (unsigned int i) const { return CastR (GSUBGPOS::get_lookup (i)); } @@ -1373,15 +1318,15 @@ struct GSUB : GSUBGPOS void GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer) { - HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props); - HB_BUFFER_ALLOCATE_VAR (buffer, lig_props); - HB_BUFFER_ALLOCATE_VAR (buffer, syllable); + _hb_buffer_allocate_gsubgpos_vars (buffer); const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef; unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) { - buffer->info[i].lig_props() = buffer->info[i].syllable() = 0; - buffer->info[i].glyph_props() = gdef.get_glyph_props (buffer->info[i].codepoint); + for (unsigned int i = 0; i < count; i++) + { + _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint)); + _hb_glyph_info_clear_lig_props (&buffer->info[i]); + buffer->info[i].syllable() = 0; } } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh index 316f506f0d..bdd773e36b 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh @@ -43,56 +43,6 @@ namespace OT { (&c->debug_depth, c->get_name (), this, HB_FUNC, \ ""); - - -#ifndef HB_DEBUG_IS_INPLACE -#define HB_DEBUG_IS_INPLACE (HB_DEBUG+0) -#endif - -#define TRACE_IS_INPLACE(this) \ - hb_auto_trace_t trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - ""); - -struct hb_is_inplace_context_t -{ - inline const char *get_name (void) { return "IS_INPLACE"; } - static const unsigned int max_debug_depth = HB_DEBUG_IS_INPLACE; - typedef bool return_t; - typedef return_t (*recurse_func_t) (hb_is_inplace_context_t *c, unsigned int lookup_index); - template - inline return_t dispatch (const T &obj) { return obj.is_inplace (this); } - static return_t default_return_value (void) { return true; } - bool stop_sublookup_iteration (return_t r) const { return !r; } - - return_t recurse (unsigned int lookup_index) - { - if (unlikely (nesting_level_left == 0 || !recurse_func)) - return default_return_value (); - - nesting_level_left--; - bool ret = recurse_func (this, lookup_index); - nesting_level_left++; - return ret; - } - - hb_face_t *face; - recurse_func_t recurse_func; - unsigned int nesting_level_left; - unsigned int debug_depth; - - hb_is_inplace_context_t (hb_face_t *face_, - unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) : - face (face_), - recurse_func (NULL), - nesting_level_left (nesting_level_left_), - debug_depth (0) {} - - void set_recurse_func (recurse_func_t func) { recurse_func = func; } -}; - - - #ifndef HB_DEBUG_CLOSURE #define HB_DEBUG_CLOSURE (HB_DEBUG+0) #endif @@ -401,7 +351,7 @@ struct hb_apply_context_t { unsigned int property; - property = info.glyph_props(); + property = _hb_glyph_info_get_glyph_props (&info); if (!c->match_properties (info.codepoint, property, lookup_props)) return SKIP_YES; @@ -409,7 +359,7 @@ struct hb_apply_context_t if (unlikely (_hb_glyph_info_is_default_ignorable (&info) && (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) && (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) && - !is_a_ligature (info))) + !_hb_glyph_info_ligated (&info))) return SKIP_MAYBE; return SKIP_NO; @@ -610,36 +560,47 @@ struct hb_apply_context_t { unsigned int property; - property = info->glyph_props(); + property = _hb_glyph_info_get_glyph_props (info); return match_properties (info->codepoint, property, lookup_props); } - inline void set_class (hb_codepoint_t glyph_index, unsigned int class_guess) const + inline void _set_glyph_props (hb_codepoint_t glyph_index, + unsigned int class_guess = 0, + bool ligature = false) const { + unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) & + HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE; + add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED; + if (ligature) + add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED; if (likely (has_glyph_classes)) - buffer->cur().glyph_props() = gdef.get_glyph_props (glyph_index); + _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index)); else if (class_guess) - buffer->cur().glyph_props() = class_guess; + _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess); } - inline void output_glyph (hb_codepoint_t glyph_index, - unsigned int class_guess = 0) const + inline void replace_glyph (hb_codepoint_t glyph_index) const { - set_class (glyph_index, class_guess); - buffer->output_glyph (glyph_index); + _set_glyph_props (glyph_index); + buffer->replace_glyph (glyph_index); } - inline void replace_glyph (hb_codepoint_t glyph_index, - unsigned int class_guess = 0) const + inline void replace_glyph_inplace (hb_codepoint_t glyph_index) const { - set_class (glyph_index, class_guess); + _set_glyph_props (glyph_index); + buffer->cur().codepoint = glyph_index; + } + inline void replace_glyph_with_ligature (hb_codepoint_t glyph_index, + unsigned int class_guess) const + { + _set_glyph_props (glyph_index, class_guess, true); buffer->replace_glyph (glyph_index); } - inline void replace_glyph_inplace (hb_codepoint_t glyph_index, - unsigned int class_guess = 0) const + inline void output_glyph (hb_codepoint_t glyph_index, + unsigned int class_guess) const { - set_class (glyph_index, class_guess); - buffer->cur().codepoint = glyph_index; + _set_glyph_props (glyph_index, class_guess); + buffer->output_glyph (glyph_index); } }; @@ -752,13 +713,18 @@ static inline bool match_input (hb_apply_context_t *c, const USHORT input[], /* Array of input values--start with second glyph */ match_func_t match_func, const void *match_data, - unsigned int *end_offset = NULL, + unsigned int *end_offset, + unsigned int match_positions[MAX_CONTEXT_LENGTH], bool *p_is_mark_ligature = NULL, unsigned int *p_total_component_count = NULL) { TRACE_APPLY (NULL); - hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1); + if (unlikely (count > MAX_CONTEXT_LENGTH)) TRACE_RETURN (false); + + hb_buffer_t *buffer = c->buffer; + + hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, count - 1); skippy_iter.set_match_func (match_func, match_data, input); if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false); @@ -780,20 +746,23 @@ static inline bool match_input (hb_apply_context_t *c, * ligate with a conjunct...) */ - bool is_mark_ligature = !!(c->buffer->cur().glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK); + bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur()); unsigned int total_component_count = 0; - total_component_count += get_lig_num_comps (c->buffer->cur()); + total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur()); - unsigned int first_lig_id = get_lig_id (c->buffer->cur()); - unsigned int first_lig_comp = get_lig_comp (c->buffer->cur()); + unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur()); + unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur()); + match_positions[0] = buffer->idx; for (unsigned int i = 1; i < count; i++) { if (!skippy_iter.next ()) return TRACE_RETURN (false); - unsigned int this_lig_id = get_lig_id (c->buffer->info[skippy_iter.idx]); - unsigned int this_lig_comp = get_lig_comp (c->buffer->info[skippy_iter.idx]); + match_positions[i] = skippy_iter.idx; + + unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]); + unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]); if (first_lig_id && first_lig_comp) { /* If first component was attached to a previous ligature component, @@ -809,12 +778,11 @@ static inline bool match_input (hb_apply_context_t *c, return TRACE_RETURN (false); } - is_mark_ligature = is_mark_ligature && (c->buffer->info[skippy_iter.idx].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK); - total_component_count += get_lig_num_comps (c->buffer->info[skippy_iter.idx]); + is_mark_ligature = is_mark_ligature && _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]); + total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]); } - if (end_offset) - *end_offset = skippy_iter.idx - c->buffer->idx + 1; + *end_offset = skippy_iter.idx - buffer->idx + 1; if (p_is_mark_ligature) *p_is_mark_ligature = is_mark_ligature; @@ -825,17 +793,18 @@ static inline bool match_input (hb_apply_context_t *c, return TRACE_RETURN (true); } static inline void ligate_input (hb_apply_context_t *c, - unsigned int count, /* Including the first glyph (not matched) */ - const USHORT input[], /* Array of input values--start with second glyph */ - match_func_t match_func, - const void *match_data, + unsigned int count, /* Including the first glyph */ + unsigned int match_positions[MAX_CONTEXT_LENGTH], /* Including the first glyph */ + unsigned int match_length, hb_codepoint_t lig_glyph, bool is_mark_ligature, unsigned int total_component_count) { - hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1); - skippy_iter.set_match_func (match_func, match_data, input); - if (skippy_iter.has_no_chance ()) return; + TRACE_APPLY (NULL); + + hb_buffer_t *buffer = c->buffer; + + buffer->merge_clusters (buffer->idx, buffer->idx + match_length); /* * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave @@ -866,48 +835,49 @@ static inline void ligate_input (hb_apply_context_t *c, */ unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE; - unsigned int lig_id = is_mark_ligature ? 0 : allocate_lig_id (c->buffer); - unsigned int last_lig_id = get_lig_id (c->buffer->cur()); - unsigned int last_num_components = get_lig_num_comps (c->buffer->cur()); + unsigned int lig_id = is_mark_ligature ? 0 : _hb_allocate_lig_id (buffer); + unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur()); + unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur()); unsigned int components_so_far = last_num_components; if (!is_mark_ligature) { - set_lig_props_for_ligature (c->buffer->cur(), lig_id, total_component_count); - if (_hb_glyph_info_get_general_category (&c->buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) - _hb_glyph_info_set_general_category (&c->buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER); + _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count); + if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) + { + _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER); + _hb_glyph_info_set_modified_combining_class (&buffer->cur(), 0); + } } - c->replace_glyph (lig_glyph, klass); + c->replace_glyph_with_ligature (lig_glyph, klass); for (unsigned int i = 1; i < count; i++) { - if (!skippy_iter.next ()) return; - - while (c->buffer->idx < skippy_iter.idx) + while (buffer->idx < match_positions[i]) { if (!is_mark_ligature) { unsigned int new_lig_comp = components_so_far - last_num_components + - MIN (MAX (get_lig_comp (c->buffer->cur()), 1u), last_num_components); - set_lig_props_for_mark (c->buffer->cur(), lig_id, new_lig_comp); + MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->cur()), 1u), last_num_components); + _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp); } - c->buffer->next_glyph (); + buffer->next_glyph (); } - last_lig_id = get_lig_id (c->buffer->cur()); - last_num_components = get_lig_num_comps (c->buffer->cur()); + last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur()); + last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur()); components_so_far += last_num_components; /* Skip the base glyph */ - c->buffer->idx++; + buffer->idx++; } if (!is_mark_ligature && last_lig_id) { /* Re-adjust components for any marks following. */ - for (unsigned int i = c->buffer->idx; i < c->buffer->len; i++) { - if (last_lig_id == get_lig_id (c->buffer->info[i])) { + for (unsigned int i = buffer->idx; i < buffer->len; i++) { + if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) { unsigned int new_lig_comp = components_so_far - last_num_components + - MIN (MAX (get_lig_comp (c->buffer->info[i]), 1u), last_num_components); - set_lig_props_for_mark (c->buffer->info[i], lig_id, new_lig_comp); + MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->info[i]), 1u), last_num_components); + _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp); } else break; } @@ -982,99 +952,82 @@ static inline void recurse_lookups (context_t *c, static inline bool apply_lookup (hb_apply_context_t *c, unsigned int count, /* Including the first glyph */ - const USHORT input[], /* Array of input values--start with second glyph */ - match_func_t match_func, - const void *match_data, + unsigned int match_positions[MAX_CONTEXT_LENGTH], /* Including the first glyph */ unsigned int lookupCount, - const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */) + const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */ + unsigned int match_length) { TRACE_APPLY (NULL); - unsigned int end = c->buffer->len; - if (unlikely (count == 0 || c->buffer->idx + count > end)) - return TRACE_RETURN (false); - - /* TODO We don't support lookupRecord arrays that are not increasing: - * Should be easy for in_place ones at least. */ + hb_buffer_t *buffer = c->buffer; + unsigned int end; - /* Note: If sublookup is reverse, it will underflow after the first loop - * and we jump out of it. Not entirely disastrous. So we don't check - * for reverse lookup here. - */ + /* All positions are distance from beginning of *output* buffer. + * Adjust. */ + { + unsigned int bl = buffer->backtrack_len (); + end = bl + match_length; - hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1); - skippy_iter.set_match_func (match_func, match_data, input); - uint8_t syllable = c->buffer->cur().syllable(); + int delta = bl - buffer->idx; + /* Convert positions to new indexing. */ + for (unsigned int j = 0; j < count; j++) + match_positions[j] += delta; + } - unsigned int i = 0; - if (lookupCount && 0 == lookupRecord->sequenceIndex) + for (unsigned int i = 0; i < lookupCount; i++) { - unsigned int old_pos = c->buffer->idx; + unsigned int idx = lookupRecord[i].sequenceIndex; + if (idx >= count) + continue; - /* Apply a lookup */ - bool done = c->recurse (lookupRecord->lookupListIndex); + buffer->move_to (match_positions[idx]); - lookupRecord++; - lookupCount--; - i++; + unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len (); + if (!c->recurse (lookupRecord[i].lookupListIndex)) + continue; - if (!done) - goto not_applied; - else - { - if (c->table_index == 1) - c->buffer->idx = old_pos + 1; - /* Reinitialize iterator. */ - hb_apply_context_t::skipping_forward_iterator_t tmp (c, c->buffer->idx - 1, count - i); - tmp.set_syllable (syllable); - skippy_iter = tmp; - } - } - else - { - not_applied: - /* No lookup applied for this index */ - c->buffer->next_glyph (); - i++; - } - while (i < count) - { - if (!skippy_iter.next ()) return TRACE_RETURN (true); - while (c->buffer->idx < skippy_iter.idx) - c->buffer->next_glyph (); + unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len (); + int delta = new_len - orig_len; - if (lookupCount && i == lookupRecord->sequenceIndex) - { - unsigned int old_pos = c->buffer->idx; + if (!delta) + continue; - /* Apply a lookup */ - bool done = c->recurse (lookupRecord->lookupListIndex); + /* Recursed lookup changed buffer len. Adjust. */ - lookupRecord++; - lookupCount--; - i++; + /* end can't go back past the current match position. */ + end = MAX ((int) match_positions[idx] + 1, int (end) + delta); - if (!done) - goto not_applied2; - else - { - if (c->table_index == 1) - c->buffer->idx = old_pos + 1; - /* Reinitialize iterator. */ - hb_apply_context_t::skipping_forward_iterator_t tmp (c, c->buffer->idx - 1, count - i); - tmp.set_syllable (syllable); - skippy_iter = tmp; - } + unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */ + + if (delta > 0) + { + if (unlikely (delta + count > MAX_CONTEXT_LENGTH)) + break; } else { - not_applied2: - /* No lookup applied for this index */ - c->buffer->next_glyph (); - i++; + /* NOTE: delta is negative. */ + delta = MAX (delta, (int) next - (int) count); + next -= delta; } + + /* Shift! */ + memmove (match_positions + next + delta, match_positions + next, + (count - next) * sizeof (match_positions[0])); + next += delta; + count += delta; + + /* Fill in new entries. */ + for (unsigned int j = idx + 1; j < next; j++) + match_positions[j] = match_positions[j - 1] + 1; + + /* And fixup the rest. */ + for (; next < count; next++) + match_positions[next] += delta; } + buffer->move_to (end); + return TRACE_RETURN (true); } @@ -1146,28 +1099,20 @@ static inline bool context_apply_lookup (hb_apply_context_t *c, const LookupRecord lookupRecord[], ContextApplyLookupContext &lookup_context) { + unsigned int match_length = 0; + unsigned int match_positions[MAX_CONTEXT_LENGTH]; return match_input (c, inputCount, input, - lookup_context.funcs.match, lookup_context.match_data) + lookup_context.funcs.match, lookup_context.match_data, + &match_length, match_positions) && apply_lookup (c, - inputCount, input, - lookup_context.funcs.match, lookup_context.match_data, - lookupCount, lookupRecord); + inputCount, match_positions, + lookupCount, lookupRecord, + match_length); } struct Rule { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - const LookupRecord *lookupRecord = &StructAtOffset (input, input[0].static_size * (inputCount ? inputCount - 1 : 0)); - unsigned int count = lookupCount; - for (unsigned int i = 0; i < count; i++) - if (!c->recurse (lookupRecord[i].lookupListIndex)) - return TRACE_RETURN (false); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const { TRACE_CLOSURE (this); @@ -1227,16 +1172,6 @@ struct Rule struct RuleSet { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - unsigned int num_rules = rule.len; - for (unsigned int i = 0; i < num_rules; i++) - if (!(this+rule[i]).is_inplace (c)) - return TRACE_RETURN (false); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const { TRACE_CLOSURE (this); @@ -1293,16 +1228,6 @@ struct RuleSet struct ContextFormat1 { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - unsigned int count = ruleSet.len; - for (unsigned int i = 0; i < count; i++) - if (!(this+ruleSet[i]).is_inplace (c)) - return TRACE_RETURN (false); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -1389,16 +1314,6 @@ struct ContextFormat1 struct ContextFormat2 { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - unsigned int count = ruleSet.len; - for (unsigned int i = 0; i < count; i++) - if (!(this+ruleSet[i]).is_inplace (c)) - return TRACE_RETURN (false); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -1494,17 +1409,6 @@ struct ContextFormat2 struct ContextFormat3 { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - const LookupRecord *lookupRecord = &StructAtOffset (coverage, coverage[0].static_size * glyphCount); - unsigned int count = lookupCount; - for (unsigned int i = 0; i < count; i++) - if (!c->recurse (lookupRecord[i].lookupListIndex)) - return TRACE_RETURN (false); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -1726,39 +1630,27 @@ static inline bool chain_context_apply_lookup (hb_apply_context_t *c, const LookupRecord lookupRecord[], ChainContextApplyLookupContext &lookup_context) { - unsigned int lookahead_offset = 0; + unsigned int match_length = 0; + unsigned int match_positions[MAX_CONTEXT_LENGTH]; return match_input (c, inputCount, input, lookup_context.funcs.match, lookup_context.match_data[1], - &lookahead_offset) + &match_length, match_positions) && match_backtrack (c, backtrackCount, backtrack, lookup_context.funcs.match, lookup_context.match_data[0]) && match_lookahead (c, lookaheadCount, lookahead, lookup_context.funcs.match, lookup_context.match_data[2], - lookahead_offset) + match_length) && apply_lookup (c, - inputCount, input, - lookup_context.funcs.match, lookup_context.match_data[1], - lookupCount, lookupRecord); + inputCount, match_positions, + lookupCount, lookupRecord, + match_length); } struct ChainRule { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - const HeadlessArrayOf &input = StructAfter > (backtrack); - const ArrayOf &lookahead = StructAfter > (input); - const ArrayOf &lookup = StructAfter > (lookahead); - unsigned int count = lookup.len; - for (unsigned int i = 0; i < count; i++) - if (!c->recurse (lookup.array[i].lookupListIndex)) - return TRACE_RETURN (false); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const { TRACE_CLOSURE (this); @@ -1844,16 +1736,6 @@ struct ChainRule struct ChainRuleSet { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - unsigned int num_rules = rule.len; - for (unsigned int i = 0; i < num_rules; i++) - if (!(this+rule[i]).is_inplace (c)) - return TRACE_RETURN (false); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const { TRACE_CLOSURE (this); @@ -1907,16 +1789,6 @@ struct ChainRuleSet struct ChainContextFormat1 { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - unsigned int count = ruleSet.len; - for (unsigned int i = 0; i < count; i++) - if (!(this+ruleSet[i]).is_inplace (c)) - return TRACE_RETURN (false); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -2000,16 +1872,6 @@ struct ChainContextFormat1 struct ChainContextFormat2 { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - unsigned int count = ruleSet.len; - for (unsigned int i = 0; i < count; i++) - if (!(this+ruleSet[i]).is_inplace (c)) - return TRACE_RETURN (false); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); @@ -2134,20 +1996,6 @@ struct ChainContextFormat2 struct ChainContextFormat3 { - inline bool is_inplace (hb_is_inplace_context_t *c) const - { - TRACE_IS_INPLACE (this); - const OffsetArrayOf &input = StructAfter > (backtrack); - const OffsetArrayOf &lookahead = StructAfter > (input); - const ArrayOf &lookup = StructAfter > (lookahead); - - unsigned int count = lookup.len; - for (unsigned int i = 0; i < count; i++) - if (!c->recurse (lookup.array[i].lookupListIndex)) - return TRACE_RETURN (false); - return TRACE_RETURN (true); - } - inline void closure (hb_closure_context_t *c) const { TRACE_CLOSURE (this); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh new file mode 100644 index 0000000000..79eb859566 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh @@ -0,0 +1,229 @@ +/* + * Copyright © 2013 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_LAYOUT_JSTF_TABLE_HH +#define HB_OT_LAYOUT_JSTF_TABLE_HH + +#include "hb-open-type-private.hh" +#include "hb-ot-layout-gpos-table.hh" + + +namespace OT { + + +/* + * JstfModList -- Justification Modification List Tables + */ + +typedef IndexArray JstfModList; + + +/* + * JstfMax -- Justification Maximum Table + */ + +typedef OffsetListOf JstfMax; + + +/* + * JstfPriority -- Justification Priority Table + */ + +struct JstfPriority +{ + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + return TRACE_RETURN (c->check_struct (this) && + shrinkageEnableGSUB.sanitize (c, this) && + shrinkageDisableGSUB.sanitize (c, this) && + shrinkageEnableGPOS.sanitize (c, this) && + shrinkageDisableGPOS.sanitize (c, this) && + shrinkageJstfMax.sanitize (c, this) && + extensionEnableGSUB.sanitize (c, this) && + extensionDisableGSUB.sanitize (c, this) && + extensionEnableGPOS.sanitize (c, this) && + extensionDisableGPOS.sanitize (c, this) && + extensionJstfMax.sanitize (c, this)); + } + + protected: + OffsetTo + shrinkageEnableGSUB; /* Offset to Shrinkage Enable GSUB + * JstfModList table--from beginning of + * JstfPriority table--may be NULL */ + OffsetTo + shrinkageDisableGSUB; /* Offset to Shrinkage Disable GSUB + * JstfModList table--from beginning of + * JstfPriority table--may be NULL */ + OffsetTo + shrinkageEnableGPOS; /* Offset to Shrinkage Enable GPOS + * JstfModList table--from beginning of + * JstfPriority table--may be NULL */ + OffsetTo + shrinkageDisableGPOS; /* Offset to Shrinkage Disable GPOS + * JstfModList table--from beginning of + * JstfPriority table--may be NULL */ + OffsetTo + shrinkageJstfMax; /* Offset to Shrinkage JstfMax table-- + * from beginning of JstfPriority table + * --may be NULL */ + OffsetTo + extensionEnableGSUB; /* Offset to Extension Enable GSUB + * JstfModList table--from beginning of + * JstfPriority table--may be NULL */ + OffsetTo + extensionDisableGSUB; /* Offset to Extension Disable GSUB + * JstfModList table--from beginning of + * JstfPriority table--may be NULL */ + OffsetTo + extensionEnableGPOS; /* Offset to Extension Enable GPOS + * JstfModList table--from beginning of + * JstfPriority table--may be NULL */ + OffsetTo + extensionDisableGPOS; /* Offset to Extension Disable GPOS + * JstfModList table--from beginning of + * JstfPriority table--may be NULL */ + OffsetTo + extensionJstfMax; /* Offset to Extension JstfMax table-- + * from beginning of JstfPriority table + * --may be NULL */ + + public: + DEFINE_SIZE_STATIC (20); +}; + + +/* + * JstfLangSys -- Justification Language System Table + */ + +struct JstfLangSys : OffsetListOf +{ + inline bool sanitize (hb_sanitize_context_t *c, + const Record::sanitize_closure_t * = NULL) { + TRACE_SANITIZE (this); + return TRACE_RETURN (OffsetListOf::sanitize (c)); + } +}; + + +/* + * ExtenderGlyphs -- Extender Glyph Table + */ + +typedef SortedArrayOf ExtenderGlyphs; + + +/* + * JstfScript -- The Justification Table + */ + +struct JstfScript +{ + inline unsigned int get_lang_sys_count (void) const + { return langSys.len; } + inline const Tag& get_lang_sys_tag (unsigned int i) const + { return langSys.get_tag (i); } + inline unsigned int get_lang_sys_tags (unsigned int start_offset, + unsigned int *lang_sys_count /* IN/OUT */, + hb_tag_t *lang_sys_tags /* OUT */) const + { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); } + inline const JstfLangSys& get_lang_sys (unsigned int i) const + { + if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys (); + return this+langSys[i].offset; + } + inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const + { return langSys.find_index (tag, index); } + + inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; } + inline const JstfLangSys& get_default_lang_sys (void) const { return this+defaultLangSys; } + + inline bool sanitize (hb_sanitize_context_t *c, + const Record::sanitize_closure_t * = NULL) { + TRACE_SANITIZE (this); + return TRACE_RETURN (extenderGlyphs.sanitize (c, this) && + defaultLangSys.sanitize (c, this) && + langSys.sanitize (c, this)); + } + + protected: + OffsetTo + extenderGlyphs; /* Offset to ExtenderGlyph table--from beginning + * of JstfScript table-may be NULL */ + OffsetTo + defaultLangSys; /* Offset to DefaultJstfLangSys table--from + * beginning of JstfScript table--may be Null */ + RecordArrayOf + langSys; /* Array of JstfLangSysRecords--listed + * alphabetically by LangSysTag */ + public: + DEFINE_SIZE_ARRAY (6, langSys); +}; + + +/* + * JSTF -- The Justification Table + */ + +struct JSTF +{ + static const hb_tag_t tableTag = HB_OT_TAG_JSTF; + + inline unsigned int get_script_count (void) const + { return scriptList.len; } + inline const Tag& get_script_tag (unsigned int i) const + { return scriptList.get_tag (i); } + inline unsigned int get_script_tags (unsigned int start_offset, + unsigned int *script_count /* IN/OUT */, + hb_tag_t *script_tags /* OUT */) const + { return scriptList.get_tags (start_offset, script_count, script_tags); } + inline const JstfScript& get_script (unsigned int i) const + { return this+scriptList[i].offset; } + inline bool find_script_index (hb_tag_t tag, unsigned int *index) const + { return scriptList.find_index (tag, index); } + + inline bool sanitize (hb_sanitize_context_t *c) { + TRACE_SANITIZE (this); + return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) && + scriptList.sanitize (c, this)); + } + + protected: + FixedVersion version; /* Version of the JSTF table--initially set + * to 0x00010000 */ + RecordArrayOf + scriptList; /* Array of JstfScripts--listed + * alphabetically by ScriptTag */ + public: + DEFINE_SIZE_ARRAY (6, scriptList); +}; + + +} /* namespace OT */ + + +#endif /* HB_OT_LAYOUT_JSTF_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-private.hh index c5ba8b4b4d..0a0a54b25d 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-private.hh @@ -1,6 +1,6 @@ /* * Copyright © 2007,2008,2009 Red Hat, Inc. - * Copyright © 2012 Google, Inc. + * Copyright © 2012,2013 Google, Inc. * * This is part of HarfBuzz, a text shaping library. * @@ -31,47 +31,184 @@ #include "hb-private.hh" -#include "hb-ot-layout.h" - #include "hb-font-private.hh" #include "hb-buffer-private.hh" #include "hb-set-private.hh" -/* buffer var allocations, used during the GSUB/GPOS processing */ -#define glyph_props() var1.u16[0] /* GDEF glyph properties */ -#define syllable() var1.u8[2] /* GSUB/GPOS shaping boundaries */ -#define lig_props() var1.u8[3] /* GSUB/GPOS ligature tracking */ +/* + * GDEF + */ + +typedef enum +{ + /* The following three match LookupFlags::Ignore* numbers. */ + HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH = 0x02u, + HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE = 0x04u, + HB_OT_LAYOUT_GLYPH_PROPS_MARK = 0x08u, + + /* The following are used internally; not derived from GDEF. */ + HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED = 0x10u, + HB_OT_LAYOUT_GLYPH_PROPS_LIGATED = 0x20u, + + HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED | + HB_OT_LAYOUT_GLYPH_PROPS_LIGATED +} hb_ot_layout_glyph_class_mask_t; + + +/* + * GSUB/GPOS + */ + +HB_INTERNAL hb_bool_t +hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face, + unsigned int lookup_index, + const hb_codepoint_t *glyphs, + unsigned int glyphs_length, + hb_bool_t zero_context); + + +/* Should be called before all the substitute_lookup's are done. */ +HB_INTERNAL void +hb_ot_layout_substitute_start (hb_font_t *font, + hb_buffer_t *buffer); + + +struct hb_ot_layout_lookup_accelerator_t; + +namespace OT { + struct hb_apply_context_t; + struct SubstLookup; +} + +HB_INTERNAL void +hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, + const OT::SubstLookup &lookup, + const hb_ot_layout_lookup_accelerator_t &accel); + + +/* Should be called after all the substitute_lookup's are done */ +HB_INTERNAL void +hb_ot_layout_substitute_finish (hb_font_t *font, + hb_buffer_t *buffer); + + +/* Should be called before all the position_lookup's are done. Resets positions to zero. */ +HB_INTERNAL void +hb_ot_layout_position_start (hb_font_t *font, + hb_buffer_t *buffer); + +/* Should be called after all the position_lookup's are done */ +HB_INTERNAL void +hb_ot_layout_position_finish (hb_font_t *font, + hb_buffer_t *buffer); + + + +/* + * hb_ot_layout_t + */ + +namespace OT { + struct GDEF; + struct GSUB; + struct GPOS; +} + +struct hb_ot_layout_lookup_accelerator_t +{ + template + inline void init (const TLookup &lookup) + { + digest.init (); + lookup.add_coverage (&digest); + } + + template + inline void fini (const TLookup &lookup) + { + } + + hb_set_digest_t digest; +}; + +struct hb_ot_layout_t +{ + hb_blob_t *gdef_blob; + hb_blob_t *gsub_blob; + hb_blob_t *gpos_blob; + + const struct OT::GDEF *gdef; + const struct OT::GSUB *gsub; + const struct OT::GPOS *gpos; + + unsigned int gsub_lookup_count; + unsigned int gpos_lookup_count; + + hb_ot_layout_lookup_accelerator_t *gsub_accels; + hb_ot_layout_lookup_accelerator_t *gpos_accels; +}; + + +HB_INTERNAL hb_ot_layout_t * +_hb_ot_layout_create (hb_face_t *face); + +HB_INTERNAL void +_hb_ot_layout_destroy (hb_ot_layout_t *layout); + + +#define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot) + + +/* + * Buffer var routines. + */ /* buffer var allocations, used during the entire shaping process */ #define unicode_props0() var2.u8[0] #define unicode_props1() var2.u8[1] +/* buffer var allocations, used during the GSUB/GPOS processing */ +#define glyph_props() var1.u16[0] /* GDEF glyph properties */ +#define lig_props() var1.u8[2] /* GSUB/GPOS ligature tracking */ +#define syllable() var1.u8[3] /* GSUB/GPOS shaping boundaries */ + +/* unicode_props */ + +enum { + MASK0_ZWJ = 0x20u, + MASK0_ZWNJ = 0x40u, + MASK0_IGNORABLE = 0x80u, + MASK0_GEN_CAT = 0x1Fu +}; inline void _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode) { + /* XXX This shouldn't be inlined, or at least not while is_default_ignorable() is inline. */ info->unicode_props0() = ((unsigned int) unicode->general_category (info->codepoint)) | - (unicode->is_default_ignorable (info->codepoint) ? 0x80 : 0) | - (info->codepoint == 0x200C ? 0x40 : 0) | - (info->codepoint == 0x200D ? 0x20 : 0); + (unicode->is_default_ignorable (info->codepoint) ? MASK0_IGNORABLE : 0) | + (info->codepoint == 0x200C ? MASK0_ZWNJ : 0) | + (info->codepoint == 0x200D ? MASK0_ZWJ : 0); info->unicode_props1() = unicode->modified_combining_class (info->codepoint); } inline void -_hb_glyph_info_set_general_category (hb_glyph_info_t *info, hb_unicode_general_category_t gen_cat) +_hb_glyph_info_set_general_category (hb_glyph_info_t *info, + hb_unicode_general_category_t gen_cat) { - info->unicode_props0() = (unsigned int) gen_cat | ((info->unicode_props0()) & ~0x1F); + info->unicode_props0() = (unsigned int) gen_cat | ((info->unicode_props0()) & ~MASK0_GEN_CAT); } inline hb_unicode_general_category_t _hb_glyph_info_get_general_category (const hb_glyph_info_t *info) { - return (hb_unicode_general_category_t) (info->unicode_props0() & 0x1F); + return (hb_unicode_general_category_t) (info->unicode_props0() & MASK0_GEN_CAT); } inline void -_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info, unsigned int modified_class) +_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info, + unsigned int modified_class) { info->unicode_props1() = modified_class; } @@ -85,43 +222,28 @@ _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info) inline hb_bool_t _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info) { - return !!(info->unicode_props0() & 0x80); + return !!(info->unicode_props0() & MASK0_IGNORABLE); } inline hb_bool_t _hb_glyph_info_is_zwnj (const hb_glyph_info_t *info) { - return !!(info->unicode_props0() & 0x40); + return !!(info->unicode_props0() & MASK0_ZWNJ); } inline hb_bool_t _hb_glyph_info_is_zwj (const hb_glyph_info_t *info) { - return !!(info->unicode_props0() & 0x20); + return !!(info->unicode_props0() & MASK0_ZWJ); } +inline void +_hb_glyph_info_flip_joiners (hb_glyph_info_t *info) +{ + info->unicode_props0() ^= MASK0_ZWNJ | MASK0_ZWJ; +} -#define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot) - -/* - * GDEF - */ - -typedef enum { - HB_OT_LAYOUT_GLYPH_PROPS_UNCLASSIFIED = 1 << HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED, - HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH = 1 << HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH, - HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE = 1 << HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE, - HB_OT_LAYOUT_GLYPH_PROPS_MARK = 1 << HB_OT_LAYOUT_GLYPH_CLASS_MARK, - HB_OT_LAYOUT_GLYPH_PROPS_COMPONENT = 1 << HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT -} hb_ot_layout_glyph_class_mask_t; - - - -/* - * GSUB/GPOS - */ - -/* lig_id / lig_comp +/* lig_props: aka lig_id / lig_comp * * When a ligature is formed: * @@ -131,7 +253,9 @@ typedef enum { * - The marks get lig_comp > 0, reflecting which component of the ligature * they were applied to. * - This is used in GPOS to attach marks to the right component of a ligature - * in MarkLigPos. + * in MarkLigPos, + * - Note that when marks are ligated together, much of the above is skipped + * and the current lig_id reused. * * When a multiple-substitution is done: * @@ -141,156 +265,159 @@ typedef enum { * multiple substitution in MarkBasePos. * * The numbers are also used in GPOS to do mark-to-mark positioning only - * to marks that belong to the same component of a ligature in MarkMarPos. + * to marks that belong to the same component of the same ligature. */ + +static inline void +_hb_glyph_info_clear_lig_props (hb_glyph_info_t *info) +{ + info->lig_props() = 0; +} + #define IS_LIG_BASE 0x10 + static inline void -set_lig_props_for_ligature (hb_glyph_info_t &info, unsigned int lig_id, unsigned int lig_num_comps) +_hb_glyph_info_set_lig_props_for_ligature (hb_glyph_info_t *info, + unsigned int lig_id, + unsigned int lig_num_comps) { - info.lig_props() = (lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F); + info->lig_props() = (lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F); } + static inline void -set_lig_props_for_mark (hb_glyph_info_t &info, unsigned int lig_id, unsigned int lig_comp) +_hb_glyph_info_set_lig_props_for_mark (hb_glyph_info_t *info, + unsigned int lig_id, + unsigned int lig_comp) { - info.lig_props() = (lig_id << 5) | (lig_comp & 0x0F); + info->lig_props() = (lig_id << 5) | (lig_comp & 0x0F); } + static inline void -set_lig_props_for_component (hb_glyph_info_t &info, unsigned int comp) +_hb_glyph_info_set_lig_props_for_component (hb_glyph_info_t *info, unsigned int comp) { - set_lig_props_for_mark (info, 0, comp); + _hb_glyph_info_set_lig_props_for_mark (info, 0, comp); } static inline unsigned int -get_lig_id (const hb_glyph_info_t &info) +_hb_glyph_info_get_lig_id (const hb_glyph_info_t *info) { - return info.lig_props() >> 5; + return info->lig_props() >> 5; } + static inline bool -is_a_ligature (const hb_glyph_info_t &info) +_hb_glyph_info_ligated_internal (const hb_glyph_info_t *info) { - return !!(info.lig_props() & IS_LIG_BASE); + return !!(info->lig_props() & IS_LIG_BASE); } + static inline unsigned int -get_lig_comp (const hb_glyph_info_t &info) +_hb_glyph_info_get_lig_comp (const hb_glyph_info_t *info) { - if (is_a_ligature (info)) + if (_hb_glyph_info_ligated_internal (info)) return 0; else - return info.lig_props() & 0x0F; + return info->lig_props() & 0x0F; } + static inline unsigned int -get_lig_num_comps (const hb_glyph_info_t &info) +_hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info) { - if ((info.glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE) && is_a_ligature (info)) - return info.lig_props() & 0x0F; + if ((info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE) && + _hb_glyph_info_ligated_internal (info)) + return info->lig_props() & 0x0F; else return 1; } -static inline uint8_t allocate_lig_id (hb_buffer_t *buffer) { +static inline uint8_t +_hb_allocate_lig_id (hb_buffer_t *buffer) { uint8_t lig_id = buffer->next_serial () & 0x07; if (unlikely (!lig_id)) - lig_id = allocate_lig_id (buffer); /* in case of overflow */ + lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */ return lig_id; } +/* glyph_props: */ -HB_INTERNAL hb_bool_t -hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face, - unsigned int lookup_index, - const hb_codepoint_t *glyphs, - unsigned int glyphs_length, - hb_bool_t zero_context); - - -/* Should be called before all the substitute_lookup's are done. */ -HB_INTERNAL void -hb_ot_layout_substitute_start (hb_font_t *font, - hb_buffer_t *buffer); - - -struct hb_ot_layout_lookup_accelerator_t; - -namespace OT { - struct hb_apply_context_t; - struct SubstLookup; +inline void +_hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props) +{ + info->glyph_props() = props; } -HB_INTERNAL void -hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, - const OT::SubstLookup &lookup, - const hb_ot_layout_lookup_accelerator_t &accel); - - -/* Should be called after all the substitute_lookup's are done */ -HB_INTERNAL void -hb_ot_layout_substitute_finish (hb_font_t *font, - hb_buffer_t *buffer); - - -/* Should be called before all the position_lookup's are done. Resets positions to zero. */ -HB_INTERNAL void -hb_ot_layout_position_start (hb_font_t *font, - hb_buffer_t *buffer); - -/* Should be called after all the position_lookup's are done */ -HB_INTERNAL void -hb_ot_layout_position_finish (hb_font_t *font, - hb_buffer_t *buffer); - - - -/* - * hb_ot_layout_t - */ - -namespace OT { - struct GDEF; - struct GSUB; - struct GPOS; +inline unsigned int +_hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info) +{ + return info->glyph_props(); } -struct hb_ot_layout_lookup_accelerator_t +inline bool +_hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info) { - template - inline void init (const TLookup &lookup) - { - digest.init (); - lookup.add_coverage (&digest); - } + return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH); +} - template - inline void fini (const TLookup &lookup) - { - } +inline bool +_hb_glyph_info_is_ligature (const hb_glyph_info_t *info) +{ + return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE); +} - hb_set_digest_t digest; -}; +inline bool +_hb_glyph_info_is_mark (const hb_glyph_info_t *info) +{ + return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK); +} -struct hb_ot_layout_t +static inline bool +_hb_glyph_info_substituted (const hb_glyph_info_t *info) { - hb_blob_t *gdef_blob; - hb_blob_t *gsub_blob; - hb_blob_t *gpos_blob; + return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED); +} - const struct OT::GDEF *gdef; - const struct OT::GSUB *gsub; - const struct OT::GPOS *gpos; +static inline bool +_hb_glyph_info_ligated (const hb_glyph_info_t *info) +{ + return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED); +} - unsigned int gsub_lookup_count; - unsigned int gpos_lookup_count; +/* Allocation / deallocation. */ - hb_ot_layout_lookup_accelerator_t *gsub_accels; - hb_ot_layout_lookup_accelerator_t *gpos_accels; -}; +inline void +_hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer) +{ + HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props0); + HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props1); +} +inline void +_hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer) +{ + HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props0); + HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props1); +} -HB_INTERNAL hb_ot_layout_t * -_hb_ot_layout_create (hb_face_t *face); +inline void +_hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer) +{ + HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props); + HB_BUFFER_ALLOCATE_VAR (buffer, lig_props); + HB_BUFFER_ALLOCATE_VAR (buffer, syllable); +} -HB_INTERNAL void -_hb_ot_layout_destroy (hb_ot_layout_t *layout); +inline void +_hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer) +{ + HB_BUFFER_DEALLOCATE_VAR (buffer, syllable); + HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props); + HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props); +} +/* Make sure no one directly touches our props... */ +#undef unicode_props0 +#undef unicode_props1 +#undef lig_props +#undef glyph_props #endif /* HB_OT_LAYOUT_PRIVATE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc index 520deff710..183726e63c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc @@ -33,6 +33,7 @@ #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" +#include "hb-ot-layout-jstf-table.hh" #include "hb-ot-map-private.hh" @@ -413,6 +414,24 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face, return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); } +unsigned int +hb_ot_layout_table_get_lookup_count (hb_face_t *face, + hb_tag_t table_tag) +{ + switch (table_tag) + { + case HB_OT_TAG_GSUB: + { + return hb_ot_layout_from_face (face)->gsub_lookup_count; + } + case HB_OT_TAG_GPOS: + { + return hb_ot_layout_from_face (face)->gpos_lookup_count; + } + } + return 0; +} + static void _hb_ot_layout_collect_lookups_lookups (hb_face_t *face, hb_tag_t table_tag, @@ -764,6 +783,7 @@ hb_ot_layout_get_size_params (hb_face_t *face, struct GSUBProxy { static const unsigned int table_index = 0; + static const bool inplace = false; typedef OT::SubstLookup Lookup; GSUBProxy (hb_face_t *face) : @@ -777,6 +797,7 @@ struct GSUBProxy struct GPOSProxy { static const unsigned int table_index = 1; + static const bool inplace = true; typedef OT::PosLookup Lookup; GPOSProxy (hb_face_t *face) : @@ -804,10 +825,9 @@ apply_string (OT::hb_apply_context_t *c, const hb_ot_layout_lookup_accelerator_t &accel) { bool ret = false; - OT::hb_is_inplace_context_t inplace_c (c->face); - bool inplace = lookup.is_inplace (&inplace_c); + hb_buffer_t *buffer = c->buffer; - if (unlikely (!c->buffer->len || !c->lookup_mask)) + if (unlikely (!buffer->len || !c->lookup_mask)) return false; c->set_lookup (lookup); @@ -816,43 +836,43 @@ apply_string (OT::hb_apply_context_t *c, { /* in/out forward substitution/positioning */ if (Proxy::table_index == 0) - c->buffer->clear_output (); - c->buffer->idx = 0; + buffer->clear_output (); + buffer->idx = 0; - while (c->buffer->idx < c->buffer->len) + while (buffer->idx < buffer->len) { - if (accel.digest.may_have (c->buffer->cur().codepoint) && - (c->buffer->cur().mask & c->lookup_mask) && + if (accel.digest.may_have (buffer->cur().codepoint) && + (buffer->cur().mask & c->lookup_mask) && apply_once (c, lookup)) ret = true; else - c->buffer->next_glyph (); + buffer->next_glyph (); } if (ret) { - if (!inplace) - c->buffer->swap_buffers (); + if (!Proxy::inplace) + buffer->swap_buffers (); else - assert (!c->buffer->has_separate_output ()); + assert (!buffer->has_separate_output ()); } } else { /* in-place backward substitution/positioning */ if (Proxy::table_index == 0) - c->buffer->remove_output (); - c->buffer->idx = c->buffer->len - 1; + buffer->remove_output (); + buffer->idx = buffer->len - 1; do { - if (accel.digest.may_have (c->buffer->cur().codepoint) && - (c->buffer->cur().mask & c->lookup_mask) && + if (accel.digest.may_have (buffer->cur().codepoint) && + (buffer->cur().mask & c->lookup_mask) && apply_once (c, lookup)) ret = true; - else - c->buffer->idx--; + /* The reverse lookup doesn't "advance" cursor (for good reason). */ + buffer->idx--; } - while ((int) c->buffer->idx >= 0); + while ((int) buffer->idx >= 0); } return ret; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h index 134f1a6c16..dfc7f2446f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.h @@ -41,6 +41,7 @@ HB_BEGIN_DECLS #define HB_OT_TAG_GDEF HB_TAG('G','D','E','F') #define HB_OT_TAG_GSUB HB_TAG('G','S','U','B') #define HB_OT_TAG_GPOS HB_TAG('G','P','O','S') +#define HB_OT_TAG_JSTF HB_TAG('J','S','T','F') /* @@ -179,6 +180,11 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face, unsigned int *lookup_count /* IN/OUT */, unsigned int *lookup_indexes /* OUT */); +unsigned int +hb_ot_layout_table_get_lookup_count (hb_face_t *face, + hb_tag_t table_tag); + + void hb_ot_layout_collect_lookups (hb_face_t *face, hb_tag_t table_tag, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc index 43856fa37e..559193c1ba 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc @@ -40,6 +40,9 @@ hb_ot_map_t::add_lookups (hb_face_t *face, { unsigned int lookup_indices[32]; unsigned int offset, len; + unsigned int table_lookup_count; + + table_lookup_count = hb_ot_layout_table_get_lookup_count (face, table_tags[table_index]); offset = 0; do { @@ -50,7 +53,10 @@ hb_ot_map_t::add_lookups (hb_face_t *face, offset, &len, lookup_indices); - for (unsigned int i = 0; i < len; i++) { + for (unsigned int i = 0; i < len; i++) + { + if (lookup_indices[i] >= table_lookup_count) + continue; hb_ot_map_t::lookup_map_t *lookup = lookups[table_index].push (); if (unlikely (!lookup)) return; @@ -175,7 +181,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) continue; /* Feature disabled, or not enough bits. */ - bool found = false; + hb_bool_t found = false; unsigned int feature_index[2]; for (unsigned int table_index = 0; table_index < 2; table_index++) found |= hb_ot_layout_language_find_feature (face, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh index 0ce3ebcc2a..e6d255579c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh @@ -41,7 +41,7 @@ namespace OT { struct maxp { - static const hb_tag_t Tag = HB_OT_TAG_maxp; + static const hb_tag_t tableTag = HB_OT_TAG_maxp; inline unsigned int get_num_glyphs (void) const { return numGlyphs; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh index e36b0f7c97..07dc0565ca 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh @@ -74,7 +74,7 @@ struct NameRecord struct name { - static const hb_tag_t Tag = HB_OT_TAG_name; + static const hb_tag_t tableTag = HB_OT_TAG_name; inline unsigned int get_name (unsigned int platform_id, unsigned int encoding_id, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc index a57e81a5ec..4f6c86e8ee 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc @@ -156,6 +156,11 @@ static const struct arabic_state_table_entry { }; +static void +nuke_joiners (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); + static void arabic_fallback_shape (const hb_ot_shape_plan_t *plan, hb_font_t *font, @@ -176,6 +181,8 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) * TODO: Add test cases for these two. */ + map->add_gsub_pause (nuke_joiners); + map->add_global_bool_feature (HB_TAG('c','c','m','p')); map->add_global_bool_feature (HB_TAG('l','o','c','l')); @@ -273,7 +280,8 @@ arabic_joining (hb_buffer_t *buffer) const arabic_state_table_entry *entry = &arabic_state_table[state][this_type]; if (entry->prev_action != NONE && prev != (unsigned int) -1) - buffer->info[prev].arabic_shaping_action() = entry->prev_action; + for (; prev < i; prev++) + buffer->info[prev].arabic_shaping_action() = entry->prev_action; buffer->info[i].arabic_shaping_action() = entry->curr_action; @@ -313,6 +321,17 @@ setup_masks_arabic (const hb_ot_shape_plan_t *plan, } +static void +nuke_joiners (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) +{ + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + if (_hb_glyph_info_is_zwj (&buffer->info[i])) + _hb_glyph_info_flip_joiners (&buffer->info[i]); +} + static void arabic_fallback_shape (const hb_ot_shape_plan_t *plan, hb_font_t *font, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh index 39268b1453..3de5c203fa 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh @@ -43,23 +43,25 @@ * Not sure how to avoid duplication. */ enum indic_category_t { OT_X = 0, - OT_C, - OT_V, - OT_N, - OT_H, - OT_ZWNJ, - OT_ZWJ, - OT_M, - OT_SM, - OT_VD, - OT_A, - OT_NBSP, - OT_DOTTEDCIRCLE, /* Not in the spec, but special in Uniscribe. /Very very/ special! */ - OT_RS, /* Register Shifter, used in Khmer OT spec */ - OT_Coeng, - OT_Repha, - OT_Ra, /* Not explicitly listed in the OT spec, but used in the grammar. */ - OT_CM + OT_C = 1, + OT_V = 2, + OT_N = 3, + OT_H = 4, + OT_ZWNJ = 5, + OT_ZWJ = 6, + OT_M = 7, + OT_SM = 8, + OT_VD = 9, + OT_A = 10, + OT_NBSP = 11, + OT_DOTTEDCIRCLE = 12, + OT_RS = 13, /* Register Shifter, used in Khmer OT spec. */ + OT_Coeng = 14, /* Khmer-style Virama. */ + OT_Repha = 15, /* Atomically-encoded logical or visual repha. */ + OT_Ra = 16, + OT_CM = 17, /* Consonant-Medial. */ + OT_Avag = 18, /* Avagraha. */ + OT_CM2 = 31 /* Consonant-Medial, second slot. */ }; /* Visual positions in a syllable from left to right. */ @@ -93,7 +95,7 @@ enum indic_position_t { enum indic_syllabic_category_t { INDIC_SYLLABIC_CATEGORY_OTHER = OT_X, - INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_X, + INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_Avag, INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM, INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C, INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C, @@ -101,7 +103,7 @@ enum indic_syllabic_category_t { INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C, INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_CM, INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_NBSP, - INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_C, + INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM, INDIC_SYLLABIC_CATEGORY_CONSONANT_REPHA = OT_Repha, INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X, INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc index d3c475b6ab..9edefe305d 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc @@ -128,14 +128,6 @@ static const hb_codepoint_t ra_chars[] = { 0x179A, /* Khmer */ /* No Reph, Visual Repha */ }; -static inline indic_position_t -consonant_position (hb_codepoint_t u) -{ - if ((u & ~0x007F) == 0x1780) - return POS_BELOW_C; /* In Khmer coeng model, post and below forms should not be reordered. */ - return POS_BASE_C; /* Will recategorize later based on font lookups. */ -} - static inline bool is_ra (hb_codepoint_t u) { @@ -149,7 +141,7 @@ static inline bool is_one_of (const hb_glyph_info_t &info, unsigned int flags) { /* If it ligated, all bets are off. */ - if (is_a_ligature (info)) return false; + if (_hb_glyph_info_ligated (&info)) return false; return !!(FLAG (info.indic_category()) & flags); } @@ -160,12 +152,14 @@ is_joiner (const hb_glyph_info_t &info) return is_one_of (info, JOINER_FLAGS); } +#define MEDIAL_FLAGS (FLAG (OT_CM) | FLAG (OT_CM2)) + /* Note: * * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels * cannot happen in a consonant syllable. The plus side however is, we can call the * consonant syllable logic from the vowel syllable function and get it all right! */ -#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CM) | FLAG (OT_Ra) | FLAG (OT_V) | FLAG (OT_NBSP) | FLAG (OT_DOTTEDCIRCLE)) +#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_NBSP) | FLAG (OT_DOTTEDCIRCLE)) static inline bool is_consonant (const hb_glyph_info_t &info) { @@ -194,15 +188,15 @@ set_indic_properties (hb_glyph_info_t &info) /* The spec says U+0952 is OT_A. However, testing shows that Uniscribe - * treats U+0951..U+0952 all as OT_VD. + * treats U+0951..U+0954 all behave similarly. * TESTS: * U+092E,U+0947,U+0952 * U+092E,U+0952,U+0947 * U+092E,U+0947,U+0951 * U+092E,U+0951,U+0947 - * */ + */ if (unlikely (hb_in_range (u, 0x0951, 0x0954))) - cat = OT_VD; + cat = OT_A; if (unlikely (u == 0x17D1)) cat = OT_X; @@ -220,7 +214,10 @@ set_indic_properties (hb_glyph_info_t &info) else if (unlikely (u == 0x200C)) cat = OT_ZWNJ; else if (unlikely (u == 0x200D)) cat = OT_ZWJ; else if (unlikely (u == 0x25CC)) cat = OT_DOTTEDCIRCLE; - else if (unlikely (u == 0x0A71)) cat = OT_SM; /* GURMUKHI ADDAK. More like consonant medial. like 0A75. */ + else if (unlikely (u == 0x0A71)) cat = OT_SM; /* GURMUKHI ADDAK. Move it to the end. */ + else if (unlikely (u == 0xA982)) cat = OT_SM; /* Javanese repha. */ + else if (unlikely (u == 0xA9BE)) cat = OT_CM2; /* Javanese medial ya. */ + else if (unlikely (u == 0xA9BD)) { cat = OT_M; pos = POS_POST_C; } /* Javanese vocalic r. */ if (cat == OT_Repha) { /* There are two kinds of characters marked as Repha: @@ -241,7 +238,7 @@ set_indic_properties (hb_glyph_info_t &info) if ((FLAG (cat) & CONSONANT_FLAGS)) { - pos = consonant_position (u); + pos = POS_BASE_C; if (is_ra (u)) cat = OT_Ra; } @@ -249,7 +246,7 @@ set_indic_properties (hb_glyph_info_t &info) { pos = matra_position (u, pos); } - else if (cat == OT_SM || cat == OT_VD) + else if ((FLAG (cat) & (FLAG (OT_SM) | FLAG (OT_VD) | FLAG (OT_A) | FLAG (OT_Avag)))) { pos = POS_SMVD; } @@ -277,16 +274,16 @@ set_indic_properties (hb_glyph_info_t &info) enum base_position_t { BASE_POS_FIRST, + BASE_POS_LAST_SINHALA, BASE_POS_LAST }; enum reph_position_t { - REPH_POS_DEFAULT = POS_BEFORE_POST, - REPH_POS_AFTER_MAIN = POS_AFTER_MAIN, REPH_POS_BEFORE_SUB = POS_BEFORE_SUB, REPH_POS_AFTER_SUB = POS_AFTER_SUB, REPH_POS_BEFORE_POST = POS_BEFORE_POST, - REPH_POS_AFTER_POST = POS_AFTER_POST + REPH_POS_AFTER_POST = POS_AFTER_POST, + REPH_POS_DONT_CARE = POS_RA_TO_BECOME_REPH }; enum reph_mode_t { REPH_MODE_IMPLICIT, /* Reph formed out of initial Ra,H sequence. */ @@ -294,6 +291,15 @@ enum reph_mode_t { REPH_MODE_VIS_REPHA, /* Encoded Repha character, no reordering needed. */ REPH_MODE_LOG_REPHA /* Encoded Repha character, needs reordering. */ }; +enum blwf_mode_t { + BLWF_MODE_PRE_AND_POST, /* Below-forms feature applied to pre-base and post-base. */ + BLWF_MODE_POST_ONLY /* Below-forms feature applied to post-base only. */ +}; +enum pref_len_t { + PREF_LEN_1 = 1, + PREF_LEN_2 = 2, + PREF_LEN_DONT_CARE = PREF_LEN_2 +}; struct indic_config_t { hb_script_t script; @@ -302,24 +308,27 @@ struct indic_config_t base_position_t base_pos; reph_position_t reph_pos; reph_mode_t reph_mode; + blwf_mode_t blwf_mode; + pref_len_t pref_len; }; static const indic_config_t indic_configs[] = { /* Default. Should be first. */ - {HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_DEFAULT, REPH_MODE_IMPLICIT}, - {HB_SCRIPT_DEVANAGARI,true, 0x094D,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT}, - {HB_SCRIPT_BENGALI, true, 0x09CD,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT}, - {HB_SCRIPT_GURMUKHI, true, 0x0A4D,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT}, - {HB_SCRIPT_GUJARATI, true, 0x0ACD,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT}, - {HB_SCRIPT_ORIYA, true, 0x0B4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT}, - {HB_SCRIPT_TAMIL, true, 0x0BCD,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT}, - {HB_SCRIPT_TELUGU, true, 0x0C4D,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT}, - {HB_SCRIPT_KANNADA, true, 0x0CCD,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT}, - {HB_SCRIPT_MALAYALAM, true, 0x0D4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA}, - {HB_SCRIPT_SINHALA, false,0x0DCA,BASE_POS_FIRST,REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT}, - {HB_SCRIPT_KHMER, false,0x17D2,BASE_POS_FIRST,REPH_POS_DEFAULT, REPH_MODE_VIS_REPHA}, - {HB_SCRIPT_JAVANESE, false,0xA9C0,BASE_POS_LAST, REPH_POS_DEFAULT, REPH_MODE_IMPLICIT}, + {HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_1}, + {HB_SCRIPT_DEVANAGARI,true, 0x094D,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, + {HB_SCRIPT_BENGALI, true, 0x09CD,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, + {HB_SCRIPT_GURMUKHI, true, 0x0A4D,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, + {HB_SCRIPT_GUJARATI, true, 0x0ACD,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, + {HB_SCRIPT_ORIYA, true, 0x0B4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, + {HB_SCRIPT_TAMIL, true, 0x0BCD,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, + {HB_SCRIPT_TELUGU, true, 0x0C4D,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2}, + {HB_SCRIPT_KANNADA, true, 0x0CCD,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY, PREF_LEN_2}, + {HB_SCRIPT_MALAYALAM, true, 0x0D4D,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, + {HB_SCRIPT_SINHALA, false,0x0DCA,BASE_POS_LAST_SINHALA, + REPH_POS_AFTER_MAIN, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST, PREF_LEN_DONT_CARE}, + {HB_SCRIPT_KHMER, false,0x17D2,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_2}, + {HB_SCRIPT_JAVANESE, false,0xA9C0,BASE_POS_FIRST,REPH_POS_DONT_CARE, REPH_MODE_VIS_REPHA,BLWF_MODE_PRE_AND_POST, PREF_LEN_1}, }; @@ -346,15 +355,17 @@ indic_features[] = {HB_TAG('r','k','r','f'), F_GLOBAL}, {HB_TAG('p','r','e','f'), F_NONE}, {HB_TAG('b','l','w','f'), F_NONE}, - {HB_TAG('h','a','l','f'), F_NONE}, {HB_TAG('a','b','v','f'), F_NONE}, + {HB_TAG('h','a','l','f'), F_NONE}, {HB_TAG('p','s','t','f'), F_NONE}, - {HB_TAG('c','f','a','r'), F_NONE}, {HB_TAG('v','a','t','u'), F_GLOBAL}, {HB_TAG('c','j','c','t'), F_GLOBAL}, + {HB_TAG('c','f','a','r'), F_NONE}, /* * Other features. * These features are applied all at once, after final_reordering. + * Default Bengali font in Windows for example has intermixed + * lookups for init,pres,abvs,blws features. */ {HB_TAG('i','n','i','t'), F_NONE}, {HB_TAG('p','r','e','s'), F_GLOBAL}, @@ -378,12 +389,12 @@ enum { _RKRF, PREF, BLWF, - HALF, ABVF, + HALF, PSTF, - CFAR, _VATU, _CJCT, + CFAR, INIT, _PRES, @@ -411,6 +422,10 @@ static void final_reordering (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); +static void +clear_syllables (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); static void collect_features_indic (hb_ot_shape_planner_t *plan) @@ -436,14 +451,26 @@ collect_features_indic (hb_ot_shape_planner_t *plan) for (; i < INDIC_NUM_FEATURES; i++) { map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ); } + + map->add_global_bool_feature (HB_TAG('c','a','l','t')); + map->add_global_bool_feature (HB_TAG('c','l','i','g')); + + map->add_gsub_pause (clear_syllables); } static void override_features_indic (hb_ot_shape_planner_t *plan) { - /* Uniscribe does not apply 'kern'. */ + /* Uniscribe does not apply 'kern' in Khmer. */ if (hb_options ().uniscribe_bug_compatible) - plan->map.add_feature (HB_TAG('k','e','r','n'), 0, F_GLOBAL); + { + switch ((hb_tag_t) plan->props.script) + { + case HB_SCRIPT_KHMER: + plan->map.add_feature (HB_TAG('k','e','r','n'), 0, F_GLOBAL); + break; + } + } plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL); } @@ -451,8 +478,9 @@ override_features_indic (hb_ot_shape_planner_t *plan) struct would_substitute_feature_t { - inline void init (const hb_ot_map_t *map, hb_tag_t feature_tag) + inline void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_) { + zero_context = zero_context_; map->get_stage_lookups (0/*GSUB*/, map->get_feature_stage (0/*GSUB*/, feature_tag), &lookups, &count); @@ -460,7 +488,6 @@ struct would_substitute_feature_t inline bool would_substitute (const hb_codepoint_t *glyphs, unsigned int glyphs_count, - bool zero_context, hb_face_t *face) const { for (unsigned int i = 0; i < count; i++) @@ -472,6 +499,7 @@ struct would_substitute_feature_t private: const hb_ot_map_t::lookup_map_t *lookups; unsigned int count; + bool zero_context; }; struct indic_shape_plan_t @@ -527,10 +555,13 @@ data_create_indic (const hb_ot_shape_plan_t *plan) indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FF) != '2'); indic_plan->virama_glyph = (hb_codepoint_t) -1; - indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f')); - indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f')); - indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f')); - indic_plan->pstf.init (&plan->map, HB_TAG('p','s','t','f')); + /* Use zero-context would_substitute() matching for new-spec of the main + * Indic scripts, but not for old-spec or scripts with one spec only. */ + bool zero_context = indic_plan->config->has_old_spec || !indic_plan->is_old_spec; + indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f'), zero_context); + indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), zero_context); + indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f'), zero_context); + indic_plan->pstf.init (&plan->map, HB_TAG('p','s','t','f'), zero_context); for (unsigned int i = 0; i < ARRAY_LENGTH (indic_plan->mask_array); i++) indic_plan->mask_array[i] = (indic_features[i].flags & F_GLOBAL) ? @@ -547,7 +578,8 @@ data_destroy_indic (void *data) static indic_position_t consonant_position_from_face (const indic_shape_plan_t *indic_plan, - const hb_codepoint_t glyphs[2], + const hb_codepoint_t consonant, + const hb_codepoint_t virama, hb_face_t *face) { /* For old-spec, the order of glyphs is Consonant,Virama, @@ -560,16 +592,19 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan, * 930,94D in 'blwf', not the expected 94D,930 (with new-spec * table). As such, we simply match both sequences. Seems * to work. */ - bool zero_context = indic_plan->is_old_spec ? false : true; - hb_codepoint_t glyphs_r[2] = {glyphs[1], glyphs[0]}; - if (indic_plan->pref.would_substitute (glyphs , 2, zero_context, face) || - indic_plan->pref.would_substitute (glyphs_r, 2, zero_context, face)) - return POS_POST_C; - if (indic_plan->blwf.would_substitute (glyphs , 2, zero_context, face) || - indic_plan->blwf.would_substitute (glyphs_r, 2, zero_context, face)) + hb_codepoint_t glyphs[3] = {virama, consonant, virama}; + if (indic_plan->blwf.would_substitute (glyphs , 2, face) || + indic_plan->blwf.would_substitute (glyphs+1, 2, face)) return POS_BELOW_C; - if (indic_plan->pstf.would_substitute (glyphs , 2, zero_context, face) || - indic_plan->pstf.would_substitute (glyphs_r, 2, zero_context, face)) + if (indic_plan->pstf.would_substitute (glyphs , 2, face) || + indic_plan->pstf.would_substitute (glyphs+1, 2, face)) + return POS_POST_C; + unsigned int pref_len = indic_plan->config->pref_len; + if ((pref_len == PREF_LEN_2 && + (indic_plan->pref.would_substitute (glyphs , 2, face) || + indic_plan->pref.would_substitute (glyphs+1, 2, face))) + || (pref_len == PREF_LEN_1 && + indic_plan->pref.would_substitute (glyphs+1, 1, face))) return POS_POST_C; return POS_BASE_C; } @@ -579,6 +614,7 @@ enum syllable_type_t { consonant_syllable, vowel_syllable, standalone_cluster, + avagraha_cluster, broken_cluster, non_indic_cluster, }; @@ -628,15 +664,18 @@ update_consonant_positions (const hb_ot_shape_plan_t *plan, { const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data; - hb_codepoint_t glyphs[2]; - if (indic_plan->get_virama_glyph (font, &glyphs[0])) + if (indic_plan->config->base_pos != BASE_POS_LAST) + return; + + hb_codepoint_t virama; + if (indic_plan->get_virama_glyph (font, &virama)) { hb_face_t *face = font->face; unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) if (buffer->info[i].indic_position() == POS_BASE_C) { - glyphs[1] = buffer->info[i].codepoint; - buffer->info[i].indic_position() = consonant_position_from_face (indic_plan, glyphs, face); + hb_codepoint_t consonant = buffer->info[i].codepoint; + buffer->info[i].indic_position() = consonant_position_from_face (indic_plan, consonant, virama, face); } } } @@ -677,7 +716,8 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, * and has more than one consonant, Ra is excluded from candidates for * base consonants. */ unsigned int limit = start; - if (indic_plan->mask_array[RPHF] && + if (indic_plan->config->reph_pos != REPH_POS_DONT_CARE && + indic_plan->mask_array[RPHF] && start + 3 <= end && ( (indic_plan->config->reph_mode == REPH_MODE_IMPLICIT && !is_joiner (info[start + 2])) || @@ -686,7 +726,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, { /* See if it matches the 'rphf' feature. */ hb_codepoint_t glyphs[2] = {info[start].codepoint, info[start + 1].codepoint}; - if (indic_plan->rphf.would_substitute (glyphs, ARRAY_LENGTH (glyphs), true, face)) + if (indic_plan->rphf.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) { limit += 2; while (limit < end && is_joiner (info[limit])) @@ -758,9 +798,12 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, } break; - case BASE_POS_FIRST: + case BASE_POS_LAST_SINHALA: { - /* In scripts without half forms (eg. Khmer), the first consonant is always the base. */ + /* Sinhala base positioning is slightly different from main Indic, in that: + * 1. It's ZWJ behavior is different, + * 2. We don't need to look into the font for consonant positions. + */ if (!has_reph) base = limit; @@ -768,7 +811,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, /* Find the last base consonant that is not blocked by ZWJ. If there is * a ZWJ right before a base consonant, that would request a subjoined form. */ for (unsigned int i = limit; i < end; i++) - if (is_consonant (info[i]) && info[i].indic_position() == POS_BASE_C) + if (is_consonant (info[i])) { if (limit < i && info[i - 1].indic_category() == OT_ZWJ) break; @@ -778,7 +821,23 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, /* Mark all subsequent consonants as below. */ for (unsigned int i = base + 1; i < end; i++) - if (is_consonant (info[i]) && info[i].indic_position() == POS_BASE_C) + if (is_consonant (info[i])) + info[i].indic_position() = POS_BELOW_C; + } + break; + + case BASE_POS_FIRST: + { + /* The first consonant is always the base. */ + + assert (indic_plan->config->reph_mode == REPH_MODE_VIS_REPHA); + assert (!has_reph); + + base = start; + + /* Mark all subsequent consonants as below. */ + for (unsigned int i = base + 1; i < end; i++) + if (is_consonant (info[i])) info[i].indic_position() = POS_BELOW_C; } break; @@ -877,7 +936,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, indic_position_t last_pos = POS_START; for (unsigned int i = start; i < end; i++) { - if ((FLAG (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | HALANT_OR_COENG_FLAGS))) + if ((FLAG (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | HALANT_OR_COENG_FLAGS))) { info[i].indic_position() = last_pos; if (unlikely (info[i].indic_category() == OT_H && @@ -903,33 +962,68 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, } } } - /* Re-attach ZWJ, ZWNJ, and halant to next char, for after-base consonants. */ + /* For post-base consonants let them own anything before them + * since the last consonant or matra. */ { - unsigned int last_halant = end; + unsigned int last = base; for (unsigned int i = base + 1; i < end; i++) - if (is_halant_or_coeng (info[i])) - last_halant = i; - else if (is_consonant (info[i])) { - for (unsigned int j = last_halant; j < i; j++) - if (info[j].indic_position() != POS_SMVD) + if (is_consonant (info[i])) + { + for (unsigned int j = last + 1; j < i; j++) + if (info[j].indic_position() < POS_SMVD) info[j].indic_position() = info[i].indic_position(); - } + last = i; + } else if (info[i].indic_category() == OT_M) + last = i; } + { - /* Things are out-of-control for post base positions, they may shuffle - * around like crazy, so merge clusters. For pre-base stuff, we handle - * cluster issues in final reordering. */ - buffer->merge_clusters (base, end); + /* Use syllable() for sort accounting temporarily. */ + unsigned int syllable = info[start].syllable(); + for (unsigned int i = start; i < end; i++) + info[i].syllable() = i - start; + /* Sit tight, rock 'n roll! */ hb_bubble_sort (info + start, end - start, compare_indic_order); /* Find base again */ base = end; for (unsigned int i = start; i < end; i++) - if (info[i].indic_position() == POS_BASE_C) { - base = i; + if (info[i].indic_position() == POS_BASE_C) + { + base = i; break; } + /* Things are out-of-control for post base positions, they may shuffle + * around like crazy. In old-spec mode, we move halants around, so in + * that case merge all clusters after base. Otherwise, check the sort + * order and merge as needed. + * For pre-base stuff, we handle cluster issues in final reordering. */ + if (indic_plan->is_old_spec || end - base > 127) + buffer->merge_clusters (base, end); + else + { + /* Note! syllable() is a one-byte field. */ + for (unsigned int i = base; i < end; i++) + if (info[i].syllable() != 255) + { + unsigned int max = i; + unsigned int j = start + info[i].syllable(); + while (j != i) + { + max = MAX (max, j); + unsigned int next = start + info[j].syllable(); + info[j].syllable() = 255; /* So we don't process j later again. */ + j = next; + } + if (i != max) + buffer->merge_clusters (i, max + 1); + } + } + + /* Put syllable back in. */ + for (unsigned int i = start; i < end; i++) + info[i].syllable() = syllable; } /* Setup masks now */ @@ -943,6 +1037,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, /* Pre-base */ mask = indic_plan->mask_array[HALF]; + if (!indic_plan->is_old_spec && + indic_plan->config->blwf_mode == BLWF_MODE_PRE_AND_POST) + mask |= indic_plan->mask_array[BLWF]; for (unsigned int i = start; i < base; i++) info[i].mask |= mask; /* Base */ @@ -987,15 +1084,19 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, } } - if (indic_plan->mask_array[PREF] && base + 2 < end) + unsigned int pref_len = indic_plan->config->pref_len; + if (indic_plan->mask_array[PREF] && base + pref_len < end) { + assert (1 <= pref_len && pref_len <= 2); /* Find a Halant,Ra sequence and mark it for pre-base reordering processing. */ - for (unsigned int i = base + 1; i + 1 < end; i++) { - hb_codepoint_t glyphs[2] = {info[i].codepoint, info[i + 1].codepoint}; - if (indic_plan->pref.would_substitute (glyphs, ARRAY_LENGTH (glyphs), true, face)) + for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) { + hb_codepoint_t glyphs[2]; + for (unsigned int j = 0; j < pref_len; j++) + glyphs[j] = info[i + j].codepoint; + if (indic_plan->pref.would_substitute (glyphs, pref_len, face)) { - info[i++].mask |= indic_plan->mask_array[PREF]; - info[i++].mask |= indic_plan->mask_array[PREF]; + for (unsigned int j = 0; j < pref_len; j++) + info[i++].mask |= indic_plan->mask_array[PREF]; /* Mark the subsequent stuff with 'cfar'. Used in Khmer. * Read the feature spec. @@ -1003,8 +1104,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, * U+1784,U+17D2,U+179A,U+17D2,U+1782 * U+1784,U+17D2,U+1782,U+17D2,U+179A */ - for (; i < end; i++) - info[i].mask |= indic_plan->mask_array[CFAR]; + if (indic_plan->mask_array[CFAR]) + for (; i < end; i++) + info[i].mask |= indic_plan->mask_array[CFAR]; break; } @@ -1074,6 +1176,16 @@ initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan, initial_reordering_standalone_cluster (plan, face, buffer, start, end); } +static void +initial_reordering_avagraha_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_face_t *face HB_UNUSED, + hb_buffer_t *buffer HB_UNUSED, + unsigned int start HB_UNUSED, unsigned int end HB_UNUSED) +{ + /* Nothing to do right now. If we ever switch to using the output + * buffer in the reordering process, we'd need to next_glyph() here. */ +} + static void initial_reordering_non_indic_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_face_t *face HB_UNUSED, @@ -1096,6 +1208,7 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan, case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return; case vowel_syllable: initial_reordering_vowel_syllable (plan, face, buffer, start, end); return; case standalone_cluster: initial_reordering_standalone_cluster (plan, face, buffer, start, end); return; + case avagraha_cluster: initial_reordering_avagraha_cluster (plan, face, buffer, start, end); return; case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return; case non_indic_cluster: initial_reordering_non_indic_cluster (plan, face, buffer, start, end); return; } @@ -1265,9 +1378,9 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, info[new_pos] = tmp; if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */ base--; + buffer->merge_clusters (new_pos, MIN (end, base + 1)); new_pos--; } - buffer->merge_clusters (new_pos, MIN (end, base + 1)); } else { for (unsigned int i = start; i < base; i++) if (info[i].indic_position () == POS_PRE_M) { @@ -1287,17 +1400,24 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, * before post-base consonant forms, and after post-base consonant forms. */ - /* If there's anything after the Ra that has the REPH pos, it ought to be halant. - * Which means that the font has failed to ligate the Reph. In which case, we - * shouldn't move. */ + /* Two cases: + * + * - If repha is encoded as a sequence of characters (Ra,H or Ra,H,ZWJ), then + * we should only move it if the sequence ligated to the repha form. + * + * - If repha is encoded separately and in the logical position, we should only + * move it if it did NOT ligate. If it ligated, it's probably the font trying + * to make it work without the reordering. + */ if (start + 1 < end && info[start].indic_position() == POS_RA_TO_BECOME_REPH && - info[start + 1].indic_position() != POS_RA_TO_BECOME_REPH) + ((info[start].indic_category() == OT_Repha) ^ + _hb_glyph_info_ligated (&info[start]))) { unsigned int new_reph_pos; reph_position_t reph_pos = indic_plan->config->reph_pos; - /* XXX Figure out old behavior too */ + assert (reph_pos != REPH_POS_DONT_CARE); /* 1. If reph should be positioned after post-base consonant forms, * proceed to step 5. @@ -1339,7 +1459,6 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, if (reph_pos == REPH_POS_AFTER_MAIN) { new_reph_pos = base; - /* XXX Skip potential pre-base reordering Ra. */ while (new_reph_pos + 1 < end && info[new_reph_pos + 1].indic_position() <= POS_AFTER_MAIN) new_reph_pos++; if (new_reph_pos < end) @@ -1412,8 +1531,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, reph_move: { - /* Yay, one big cluster! Merge before moving. */ - buffer->merge_clusters (start, end); + buffer->merge_clusters (start, new_reph_pos + 1); /* Move */ hb_glyph_info_t reph = info[start]; @@ -1433,6 +1551,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, if (indic_plan->mask_array[PREF] && base + 1 < end) /* Otherwise there can't be any pre-base reordering Ra. */ { + unsigned int pref_len = indic_plan->config->pref_len; for (unsigned int i = base + 1; i < end; i++) if ((info[i].mask & indic_plan->mask_array[PREF]) != 0) { @@ -1440,7 +1559,13 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, * of the feature. (Note that a font may shape a Ra consonant with * the feature generally but block it in certain contexts.) */ - if (i + 1 == end || (info[i + 1].mask & indic_plan->mask_array[PREF]) == 0) + /* Note: We just check that something got substituted. We don't check that + * the feature actually did it... + * + * If pref len is longer than one, then only reorder if it ligated. If + * pref len is one, only reorder if it didn't ligate with other things. */ + if (_hb_glyph_info_substituted (&info[i]) && + ((pref_len == 1) ^ _hb_glyph_info_ligated (&info[i]))) { /* * 2. Try to find a target position the same way as for pre-base matra. @@ -1461,7 +1586,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, !(is_one_of (info[new_pos - 1], FLAG(OT_M) | HALANT_OR_COENG_FLAGS))) new_pos--; - /* In Khmer coeng model, a V,Ra can go *after* matras. If it goes after a + /* In Khmer coeng model, a H,Ra can go *after* matras. If it goes after a * split matra, it should be reordered to *before* the left part of such matra. */ if (new_pos > start && info[new_pos - 1].indic_category() == OT_M) { @@ -1511,11 +1636,20 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, */ if (hb_options ().uniscribe_bug_compatible) { - /* Uniscribe merges the entire cluster. - * This means, half forms are submerged into the main consonants cluster. - * This is unnecessary, and makes cursor positioning harder, but that's what - * Uniscribe does. */ - buffer->merge_clusters (start, end); + switch ((hb_tag_t) plan->props.script) + { + case HB_SCRIPT_TAMIL: + case HB_SCRIPT_SINHALA: + break; + + default: + /* Uniscribe merges the entire cluster... Except for Tamil & Sinhala. + * This means, half forms are submerged into the main consonants cluster. + * This is unnecessary, and makes cursor positioning harder, but that's what + * Uniscribe does. */ + buffer->merge_clusters (start, end); + break; + } } } @@ -1539,15 +1673,23 @@ final_reordering (const hb_ot_shape_plan_t *plan, } final_reordering_syllable (plan, buffer, last, count); - /* Zero syllables now... */ - for (unsigned int i = 0; i < count; i++) - info[i].syllable() = 0; - HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category); HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position); } +static void +clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_font_t *font HB_UNUSED, + hb_buffer_t *buffer) +{ + hb_glyph_info_t *info = buffer->info; + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + info[i].syllable() = 0; +} + + static hb_ot_shape_normalization_mode_t normalization_preference_indic (const hb_segment_properties_t *props HB_UNUSED) { @@ -1627,7 +1769,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, if (hb_options ().uniscribe_bug_compatible || (c->font->get_glyph (ab, 0, &glyph) && - indic_plan->pstf.would_substitute (&glyph, 1, true, c->font->face))) + indic_plan->pstf.would_substitute (&glyph, 1, c->font->face))) { /* Ok, safe to use Uniscribe-style decomposition. */ *a = 0x0DD9; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc index 29f29bb556..25ba7264ca 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc @@ -60,6 +60,16 @@ other_features[] = HB_TAG('p','s','t','s'), /* Positioning features, though we don't care about the types. */ HB_TAG('d','i','s','t'), + /* Pre-release version of Windows 8 Myanmar font had abvm,blwm + * features. The released Windows 8 version of the font (as well + * as the released spec) used 'mark' instead. The Windows 8 + * shaper however didn't apply 'mark' but did apply 'mkmk'. + * Perhaps it applied abvm/blwm. This was fixed in a Windows 8 + * update, so now it applies mark/mkmk. We are guessing that + * it still applies abvm/blwm too. + */ + HB_TAG('a','b','v','m'), + HB_TAG('b','l','w','m'), }; static void @@ -109,6 +119,7 @@ override_features_myanmar (hb_ot_shape_planner_t *plan) enum syllable_type_t { consonant_syllable, + punctuation_cluster, broken_cluster, non_myanmar_cluster, }; @@ -133,7 +144,8 @@ enum myanmar_category_t { OT_VBlw = 27, OT_VPre = 28, OT_VPst = 29, - OT_VS = 30 /* Variation selectors */ + OT_VS = 30, /* Variation selectors */ + OT_P = 31 /* Punctuation */ }; @@ -141,7 +153,7 @@ static inline bool is_one_of (const hb_glyph_info_t &info, unsigned int flags) { /* If it ligated, all bets are off. */ - if (is_a_ligature (info)) return false; + if (_hb_glyph_info_ligated (&info)) return false; return !!(FLAG (info.myanmar_category()) & flags); } @@ -176,6 +188,10 @@ set_myanmar_properties (hb_glyph_info_t &info) switch (u) { + case 0x104E: + cat = (indic_category_t) OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */ + break; + case 0x002D: case 0x00A0: case 0x00D7: case 0x2012: case 0x2013: case 0x2014: case 0x2015: case 0x2022: case 0x25CC: case 0x25FB: case 0x25FC: case 0x25FD: @@ -233,6 +249,10 @@ set_myanmar_properties (hb_glyph_info_t &info) case 0x108F: case 0x109A: case 0x109B: case 0x109C: cat = (indic_category_t) OT_SM; break; + + case 0x104A: case 0x104B: + cat = (indic_category_t) OT_P; + break; } if (cat == OT_M) @@ -395,6 +415,16 @@ initial_reordering_broken_cluster (const hb_ot_shape_plan_t *plan, initial_reordering_consonant_syllable (plan, face, buffer, start, end); } +static void +initial_reordering_punctuation_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, + hb_face_t *face HB_UNUSED, + hb_buffer_t *buffer HB_UNUSED, + unsigned int start HB_UNUSED, unsigned int end HB_UNUSED) +{ + /* Nothing to do right now. If we ever switch to using the output + * buffer in the reordering process, we'd need to next_glyph() here. */ +} + static void initial_reordering_non_myanmar_cluster (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_face_t *face HB_UNUSED, @@ -415,6 +445,7 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan, syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); switch (syllable_type) { case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return; + case punctuation_cluster: initial_reordering_punctuation_cluster (plan, face, buffer, start, end); return; case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return; case non_myanmar_cluster: initial_reordering_non_myanmar_cluster (plan, face, buffer, start, end); return; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-private.hh index a099e05d74..ac0072ba56 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-private.hh @@ -279,9 +279,6 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) /* Unicode-3.0 additions */ case HB_SCRIPT_SINHALA: - /* Unicode-4.1 additions */ - case HB_SCRIPT_BUGINESE: - /* Unicode-5.0 additions */ case HB_SCRIPT_BALINESE: @@ -336,6 +333,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) return &_hb_ot_complex_shaper_default; /* Unicode-4.1 additions */ + case HB_SCRIPT_BUGINESE: case HB_SCRIPT_NEW_TAI_LUE: /* Unicode-5.1 additions */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc index 9c0c303e3d..da687ed646 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc @@ -266,7 +266,7 @@ initial_reordering_syllable (const hb_ot_shape_plan_t *plan, switch (syllable_type) { case consonant_syllable: initial_reordering_consonant_syllable (plan, face, buffer, start, end); return; case broken_cluster: initial_reordering_broken_cluster (plan, face, buffer, start, end); return; - case non_sea_cluster: initial_reordering_non_sea_cluster (plan, face, buffer, start, end); return; + case non_sea_cluster: initial_reordering_non_sea_cluster (plan, face, buffer, start, end); return; } } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc index 284d030d5f..449b64e5ca 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc @@ -260,7 +260,13 @@ position_mark (const hb_ot_shape_plan_t *plan, case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT: case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW: - pos.y_offset += base_extents.y_bearing + base_extents.height - mark_extents.y_bearing; + pos.y_offset = base_extents.y_bearing + base_extents.height - mark_extents.y_bearing; + /* Never shift up "below" marks. */ + if ((y_gap > 0) == (pos.y_offset > 0)) + { + base_extents.height -= pos.y_offset; + pos.y_offset = 0; + } base_extents.height += mark_extents.height; break; @@ -274,7 +280,15 @@ position_mark (const hb_ot_shape_plan_t *plan, case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE: case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT: - pos.y_offset += base_extents.y_bearing - (mark_extents.y_bearing + mark_extents.height); + pos.y_offset = base_extents.y_bearing - (mark_extents.y_bearing + mark_extents.height); + /* Don't shift down "above" marks too much. */ + if ((y_gap > 0) != (pos.y_offset > 0)) + { + unsigned int correction = -pos.y_offset / 2; + base_extents.y_bearing += correction; + base_extents.height -= correction; + pos.y_offset += correction; + } base_extents.y_bearing -= mark_extents.height; base_extents.height += mark_extents.height; break; @@ -300,8 +314,8 @@ position_around_base (const hb_ot_shape_plan_t *plan, base_extents.x_bearing += buffer->pos[base].x_offset; base_extents.y_bearing += buffer->pos[base].y_offset; - unsigned int lig_id = get_lig_id (buffer->info[base]); - unsigned int num_lig_components = get_lig_num_comps (buffer->info[base]); + unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[base]); + unsigned int num_lig_components = _hb_glyph_info_get_lig_num_comps (&buffer->info[base]); hb_position_t x_offset = 0, y_offset = 0; if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) { @@ -317,8 +331,8 @@ position_around_base (const hb_ot_shape_plan_t *plan, if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i])) { if (num_lig_components > 1) { - unsigned int this_lig_id = get_lig_id (buffer->info[i]); - unsigned int this_lig_component = get_lig_comp (buffer->info[i]) - 1; + unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[i]); + unsigned int this_lig_component = _hb_glyph_info_get_lig_comp (&buffer->info[i]) - 1; /* Conditions for attaching to the last component. */ if (!lig_id || lig_id != this_lig_id || this_lig_component >= num_lig_components) this_lig_component = num_lig_components - 1; @@ -416,41 +430,52 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { - unsigned int count = buffer->len; hb_mask_t kern_mask = plan->map.get_1_mask (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ? HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n')); + if (!kern_mask) return; + + unsigned int count = buffer->len; OT::hb_apply_context_t c (1, font, buffer); c.set_lookup_mask (kern_mask); c.set_lookup_props (OT::LookupFlag::IgnoreMarks); - for (buffer->idx = 0; buffer->idx < count;) + hb_glyph_info_t *info = buffer->info; + hb_glyph_position_t *pos = buffer->pos; + + for (unsigned int idx = 0; idx < count;) { - OT::hb_apply_context_t::skipping_forward_iterator_t skippy_iter (&c, buffer->idx, 1); + OT::hb_apply_context_t::skipping_forward_iterator_t skippy_iter (&c, idx, 1); if (!skippy_iter.next ()) { - buffer->idx++; + idx++; continue; } - hb_position_t x_kern, y_kern, kern1, kern2; - font->get_glyph_kerning_for_direction (buffer->info[buffer->idx].codepoint, - buffer->info[skippy_iter.idx].codepoint, + hb_position_t x_kern, y_kern; + font->get_glyph_kerning_for_direction (info[idx].codepoint, + info[skippy_iter.idx].codepoint, buffer->props.direction, &x_kern, &y_kern); - kern1 = x_kern >> 1; - kern2 = x_kern - kern1; - buffer->pos[buffer->idx].x_advance += kern1; - buffer->pos[skippy_iter.idx].x_advance += kern2; - buffer->pos[skippy_iter.idx].x_offset += kern2; + if (x_kern) + { + hb_position_t kern1 = x_kern >> 1; + hb_position_t kern2 = x_kern - kern1; + pos[idx].x_advance += kern1; + pos[skippy_iter.idx].x_advance += kern2; + pos[skippy_iter.idx].x_offset += kern2; + } - kern1 = y_kern >> 1; - kern2 = y_kern - kern1; - buffer->pos[buffer->idx].y_advance += kern1; - buffer->pos[skippy_iter.idx].y_advance += kern2; - buffer->pos[skippy_iter.idx].y_offset += kern2; + if (y_kern) + { + hb_position_t kern1 = y_kern >> 1; + hb_position_t kern2 = y_kern - kern1; + pos[idx].y_advance += kern1; + pos[skippy_iter.idx].y_advance += kern2; + pos[skippy_iter.idx].y_offset += kern2; + } - buffer->idx = skippy_iter.idx; + idx = skippy_iter.idx; } } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh index 085d48511d..fb8048caa2 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize-private.hh @@ -29,8 +29,6 @@ #include "hb-private.hh" -#include "hb-font.h" -#include "hb-buffer.h" /* buffer var allocations, used during the normalization process */ #define glyph_index() var1.u32 diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc index 3fee809cf9..6531e1b215 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc @@ -132,17 +132,19 @@ static inline unsigned int decompose (const hb_ot_shape_normalize_context_t *c, bool shortest, hb_codepoint_t ab) { hb_codepoint_t a, b, a_glyph, b_glyph; + hb_buffer_t * const buffer = c->buffer; + hb_font_t * const font = c->font; if (!c->decompose (c, ab, &a, &b) || - (b && !c->font->get_glyph (b, 0, &b_glyph))) + (b && !font->get_glyph (b, 0, &b_glyph))) return 0; - bool has_a = c->font->get_glyph (a, 0, &a_glyph); + bool has_a = font->get_glyph (a, 0, &a_glyph); if (shortest && has_a) { /* Output a and b */ - output_char (c->buffer, a, a_glyph); + output_char (buffer, a, a_glyph); if (likely (b)) { - output_char (c->buffer, b, b_glyph); + output_char (buffer, b, b_glyph); return 2; } return 1; @@ -151,16 +153,16 @@ decompose (const hb_ot_shape_normalize_context_t *c, bool shortest, hb_codepoint unsigned int ret; if ((ret = decompose (c, shortest, a))) { if (b) { - output_char (c->buffer, b, b_glyph); + output_char (buffer, b, b_glyph); return ret + 1; } return ret; } if (has_a) { - output_char (c->buffer, a, a_glyph); + output_char (buffer, a, a_glyph); if (likely (b)) { - output_char (c->buffer, b, b_glyph); + output_char (buffer, b, b_glyph); return 2; } return 1; @@ -214,34 +216,35 @@ static inline void handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end) { hb_buffer_t * const buffer = c->buffer; + hb_font_t * const font = c->font; for (; buffer->idx < end - 1;) { if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) { /* The next two lines are some ugly lines... But work. */ - if (c->font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index())) + if (font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index())) { buffer->replace_glyphs (2, 1, &buffer->cur().codepoint); } else { /* Just pass on the two characters separately, let GSUB do its magic. */ - set_glyph (buffer->cur(), c->font); + set_glyph (buffer->cur(), font); buffer->next_glyph (); - set_glyph (buffer->cur(), c->font); + set_glyph (buffer->cur(), font); buffer->next_glyph (); } /* Skip any further variation selectors. */ while (buffer->idx < end && unlikely (buffer->unicode->is_variation_selector (buffer->cur().codepoint))) { - set_glyph (buffer->cur(), c->font); + set_glyph (buffer->cur(), font); buffer->next_glyph (); } } else { - set_glyph (buffer->cur(), c->font); + set_glyph (buffer->cur(), font); buffer->next_glyph (); } } if (likely (buffer->idx < end)) { - set_glyph (buffer->cur(), c->font); + set_glyph (buffer->cur(), font); buffer->next_glyph (); } } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-private.hh index 817147199f..cbfab5b40c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-private.hh @@ -66,7 +66,7 @@ struct hb_ot_shape_planner_t hb_ot_map_builder_t map; hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan) : - face (master_plan->face), + face (master_plan->face_unsafe), props (master_plan->props), shaper (NULL), map (face, &props) {} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc index c23240c80c..63c36f936f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc @@ -290,16 +290,18 @@ hb_ot_mirror_chars (hb_ot_shape_context_t *c) if (HB_DIRECTION_IS_FORWARD (c->target_direction)) return; - hb_unicode_funcs_t *unicode = c->buffer->unicode; + hb_buffer_t *buffer = c->buffer; + hb_unicode_funcs_t *unicode = buffer->unicode; hb_mask_t rtlm_mask = c->plan->map.get_1_mask (HB_TAG ('r','t','l','m')); - unsigned int count = c->buffer->len; + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) { - hb_codepoint_t codepoint = unicode->mirroring (c->buffer->info[i].codepoint); - if (likely (codepoint == c->buffer->info[i].codepoint)) - c->buffer->info[i].mask |= rtlm_mask; + hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint); + if (likely (codepoint == info[i].codepoint)) + info[i].mask |= rtlm_mask; else - c->buffer->info[i].codepoint = codepoint; + info[i].codepoint = codepoint; } } @@ -307,12 +309,13 @@ static inline void hb_ot_shape_setup_masks (hb_ot_shape_context_t *c) { hb_ot_map_t *map = &c->plan->map; + hb_buffer_t *buffer = c->buffer; hb_mask_t global_mask = map->get_global_mask (); - c->buffer->reset_masks (global_mask); + buffer->reset_masks (global_mask); if (c->plan->shaper->setup_masks) - c->plan->shaper->setup_masks (c->plan, c->buffer, c->font); + c->plan->shaper->setup_masks (c->plan, buffer, c->font); for (unsigned int i = 0; i < c->num_user_features; i++) { @@ -320,7 +323,7 @@ hb_ot_shape_setup_masks (hb_ot_shape_context_t *c) if (!(feature->start == 0 && feature->end == (unsigned int)-1)) { unsigned int shift; hb_mask_t mask = map->get_mask (feature->tag, &shift); - c->buffer->set_masks (feature->value << shift, mask, feature->start, feature->end); + buffer->set_masks (feature->value << shift, mask, feature->start, feature->end); } } } @@ -338,46 +341,53 @@ static inline void hb_synthesize_glyph_classes (hb_ot_shape_context_t *c) { unsigned int count = c->buffer->len; + hb_glyph_info_t *info = c->buffer->info; for (unsigned int i = 0; i < count; i++) - c->buffer->info[i].glyph_props() = _hb_glyph_info_get_general_category (&c->buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ? - HB_OT_LAYOUT_GLYPH_PROPS_MARK : - HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH; + _hb_glyph_info_set_glyph_props (&info[i], + _hb_glyph_info_get_general_category (&info[i]) + == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ? + HB_OT_LAYOUT_GLYPH_PROPS_MARK : + HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH); } static inline void hb_ot_substitute_default (hb_ot_shape_context_t *c) { + hb_buffer_t *buffer = c->buffer; + if (c->plan->shaper->preprocess_text) - c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font); + c->plan->shaper->preprocess_text (c->plan, buffer, c->font); hb_ot_mirror_chars (c); - HB_BUFFER_ALLOCATE_VAR (c->buffer, glyph_index); + HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index); - _hb_ot_shape_normalize (c->plan, c->buffer, c->font); + _hb_ot_shape_normalize (c->plan, buffer, c->font); hb_ot_shape_setup_masks (c); /* This is unfortunate to go here, but necessary... */ if (!hb_ot_layout_has_positioning (c->face)) - _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, c->buffer); + _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer); - hb_ot_map_glyphs_fast (c->buffer); + hb_ot_map_glyphs_fast (buffer); - HB_BUFFER_DEALLOCATE_VAR (c->buffer, glyph_index); + HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_index); } static inline void hb_ot_substitute_complex (hb_ot_shape_context_t *c) { - hb_ot_layout_substitute_start (c->font, c->buffer); + hb_buffer_t *buffer = c->buffer; + + hb_ot_layout_substitute_start (c->font, buffer); if (!hb_ot_layout_has_glyph_classes (c->face)) hb_synthesize_glyph_classes (c); - c->plan->substitute (c->font, c->buffer); + c->plan->substitute (c->font, buffer); - hb_ot_layout_substitute_finish (c->font, c->buffer); + hb_ot_layout_substitute_finish (c->font, buffer); return; } @@ -408,7 +418,7 @@ zero_mark_widths_by_gdef (hb_buffer_t *buffer) { unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) - if ((buffer->info[i].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) + if (_hb_glyph_info_is_mark (&buffer->info[i])) { buffer->pos[i].x_advance = 0; buffer->pos[i].y_advance = 0; @@ -418,21 +428,29 @@ zero_mark_widths_by_gdef (hb_buffer_t *buffer) static inline void hb_ot_position_default (hb_ot_shape_context_t *c) { - hb_ot_layout_position_start (c->font, c->buffer); - + hb_direction_t direction = c->buffer->props.direction; unsigned int count = c->buffer->len; + hb_glyph_info_t *info = c->buffer->info; + hb_glyph_position_t *pos = c->buffer->pos; for (unsigned int i = 0; i < count; i++) { - c->font->get_glyph_advance_for_direction (c->buffer->info[i].codepoint, - c->buffer->props.direction, - &c->buffer->pos[i].x_advance, - &c->buffer->pos[i].y_advance); - c->font->subtract_glyph_origin_for_direction (c->buffer->info[i].codepoint, - c->buffer->props.direction, - &c->buffer->pos[i].x_offset, - &c->buffer->pos[i].y_offset); + c->font->get_glyph_advance_for_direction (info[i].codepoint, + direction, + &pos[i].x_advance, + &pos[i].y_advance); + c->font->subtract_glyph_origin_for_direction (info[i].codepoint, + direction, + &pos[i].x_offset, + &pos[i].y_offset); } +} + +static inline bool +hb_ot_position_complex (hb_ot_shape_context_t *c) +{ + bool ret = false; + unsigned int count = c->buffer->len; switch (c->plan->shaper->zero_width_marks) { @@ -452,32 +470,28 @@ hb_ot_position_default (hb_ot_shape_context_t *c) case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: break; } -} - -static inline bool -hb_ot_position_complex (hb_ot_shape_context_t *c) -{ - bool ret = false; - unsigned int count = c->buffer->len; if (hb_ot_layout_has_positioning (c->face)) { + hb_glyph_info_t *info = c->buffer->info; + hb_glyph_position_t *pos = c->buffer->pos; + /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */ for (unsigned int i = 0; i < count; i++) { - c->font->add_glyph_origin_for_direction (c->buffer->info[i].codepoint, + c->font->add_glyph_origin_for_direction (info[i].codepoint, HB_DIRECTION_LTR, - &c->buffer->pos[i].x_offset, - &c->buffer->pos[i].y_offset); + &pos[i].x_offset, + &pos[i].y_offset); } c->plan->position (c->font, c->buffer); for (unsigned int i = 0; i < count; i++) { - c->font->subtract_glyph_origin_for_direction (c->buffer->info[i].codepoint, + c->font->subtract_glyph_origin_for_direction (info[i].codepoint, HB_DIRECTION_LTR, - &c->buffer->pos[i].x_offset, - &c->buffer->pos[i].y_offset); + &pos[i].x_offset, + &pos[i].y_offset); } ret = true; @@ -500,18 +514,20 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) break; } - hb_ot_layout_position_finish (c->font, c->buffer); - return ret; } static inline void hb_ot_position (hb_ot_shape_context_t *c) { + hb_ot_layout_position_start (c->font, c->buffer); + hb_ot_position_default (c); hb_bool_t fallback = !hb_ot_position_complex (c); + hb_ot_layout_position_finish (c->font, c->buffer); + if (fallback && c->plan->shaper->fallback_position) _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer); @@ -533,22 +549,42 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) if (c->buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) return; - hb_codepoint_t space = 0; + hb_codepoint_t space; + enum { + SPACE_DONT_KNOW, + SPACE_AVAILABLE, + SPACE_UNAVAILABLE + } space_status = SPACE_DONT_KNOW; unsigned int count = c->buffer->len; + hb_glyph_info_t *info = c->buffer->info; + hb_glyph_position_t *pos = c->buffer->pos; + unsigned int j = 0; for (unsigned int i = 0; i < count; i++) - if (unlikely (!is_a_ligature (c->buffer->info[i]) && - _hb_glyph_info_is_default_ignorable (&c->buffer->info[i]))) + { + if (unlikely (!_hb_glyph_info_ligated (&info[i]) && + _hb_glyph_info_is_default_ignorable (&info[i]))) { - if (!space) { - /* We assume that the space glyph is not gid0. */ - if (unlikely (!c->font->get_glyph (' ', 0, &space)) || !space) - return; /* No point! */ + if (space_status == SPACE_DONT_KNOW) + space_status = c->font->get_glyph (' ', 0, &space) ? SPACE_AVAILABLE : SPACE_UNAVAILABLE; + + if (space_status == SPACE_AVAILABLE) + { + info[i].codepoint = space; + pos[i].x_advance = 0; + pos[i].y_advance = 0; } - c->buffer->info[i].codepoint = space; - c->buffer->pos[i].x_advance = 0; - c->buffer->pos[i].y_advance = 0; + else + continue; /* Delete it. */ } + if (j != i) + { + info[j] = info[i]; + pos[j] = pos[i]; + } + j++; + } + c->buffer->len = j; } @@ -562,8 +598,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) /* Save the original direction, we use it later. */ c->target_direction = c->buffer->props.direction; - HB_BUFFER_ALLOCATE_VAR (c->buffer, unicode_props0); - HB_BUFFER_ALLOCATE_VAR (c->buffer, unicode_props1); + _hb_buffer_allocate_unicode_vars (c->buffer); c->buffer->clear_output (); @@ -578,8 +613,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) hb_ot_hide_default_ignorables (c); - HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props1); - HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props0); + _hb_buffer_deallocate_unicode_vars (c->buffer); c->buffer->props.direction = c->target_direction; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc index 91ebec76ee..5594ef5074 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc @@ -27,7 +27,6 @@ */ #include "hb-private.hh" -#include "hb-ot.h" #include @@ -167,9 +166,12 @@ typedef struct { * * Generated by intersecting the OpenType language tag list from * Draft OpenType 1.5 spec, with with the ISO 639-3 codes from - * 2008/08/04, matching on name, and finally adjusted manually. + * 2008-08-04, matching on name, and finally adjusted manually. * - * Updated on 2012/12/07 with more research into remaining codes. + * Updated on 2012-12-07 with more research into remaining codes. + * + * Updated on 2013-11-23 based on usage in SIL and Microsoft fonts, + * the new proposal from Microsoft, and latest ISO 639-3 names. * * Some items still missing. Those are commented out at the end. * Keep sorted for bsearch. @@ -179,57 +181,90 @@ static const LangTag ot_languages[] = { {"aa", HB_TAG('A','F','R',' ')}, /* Afar */ {"ab", HB_TAG('A','B','K',' ')}, /* Abkhazian */ {"abq", HB_TAG('A','B','A',' ')}, /* Abaza */ + {"ach", HB_TAG('A','C','H',' ')}, /* Acoli */ {"ada", HB_TAG('D','N','G',' ')}, /* Dangme */ {"ady", HB_TAG('A','D','Y',' ')}, /* Adyghe */ {"af", HB_TAG('A','F','K',' ')}, /* Afrikaans */ {"aii", HB_TAG('S','W','A',' ')}, /* Swadaya Aramaic */ + {"aio", HB_TAG('A','I','O',' ')}, /* Aiton */ {"aiw", HB_TAG('A','R','I',' ')}, /* Aari */ + {"ak", HB_TAG('T','W','I',' ')}, /* Akan [macrolanguage] */ {"alt", HB_TAG('A','L','T',' ')}, /* [Southern] Altai */ {"am", HB_TAG('A','M','H',' ')}, /* Amharic */ {"amf", HB_TAG('H','B','N',' ')}, /* Hammer-Banna */ - {"ar", HB_TAG('A','R','A',' ')}, /* Arabic */ + {"an", HB_TAG('A','R','G',' ')}, /* Aragonese */ + {"ang", HB_TAG('A','N','G',' ')}, /* Old English (ca. 450-1100) */ + {"ar", HB_TAG('A','R','A',' ')}, /* Arabic [macrolanguage] */ + {"arb", HB_TAG('A','R','A',' ')}, /* Standard Arabic */ {"arn", HB_TAG('M','A','P',' ')}, /* Mapudungun */ + {"ary", HB_TAG('M','O','R',' ')}, /* Moroccan Arabic */ {"as", HB_TAG('A','S','M',' ')}, /* Assamese */ + {"ast", HB_TAG('A','S','T',' ')}, /* Asturian/Asturleonese/Bable/Leonese */ {"ath", HB_TAG('A','T','H',' ')}, /* Athapaskan [family] */ {"atv", HB_TAG('A','L','T',' ')}, /* [Northern] Altai */ {"av", HB_TAG('A','V','R',' ')}, /* Avaric */ {"awa", HB_TAG('A','W','A',' ')}, /* Awadhi */ - {"ay", HB_TAG('A','Y','M',' ')}, /* Aymara */ - {"az", HB_TAG('A','Z','E',' ')}, /* Azerbaijani */ + {"ay", HB_TAG('A','Y','M',' ')}, /* Aymara [macrolanguage] */ + {"az", HB_TAG('A','Z','E',' ')}, /* Azerbaijani [macrolanguage] */ + {"azb", HB_TAG('A','Z','B',' ')}, /* South Azerbaijani */ + {"azj", HB_TAG('A','Z','E',' ')}, /* North Azerbaijani */ {"ba", HB_TAG('B','S','H',' ')}, /* Bashkir */ {"bai", HB_TAG('B','M','L',' ')}, /* Bamileke [family] */ - {"bal", HB_TAG('B','L','I',' ')}, /* Baluchi */ - {"bci", HB_TAG('B','A','U',' ')}, /* Baule */ + {"bal", HB_TAG('B','L','I',' ')}, /* Baluchi [macrolangauge] */ + {"ban", HB_TAG('B','A','N',' ')}, /* Balinese */ + {"bar", HB_TAG('B','A','R',' ')}, /* Bavarian */ + {"bbc", HB_TAG('B','B','C',' ')}, /* Batak Toba */ + {"bci", HB_TAG('B','A','U',' ')}, /* Baoulé */ + {"bcl", HB_TAG('B','I','K',' ')}, /* Central Bikol */ {"bcq", HB_TAG('B','C','H',' ')}, /* Bench */ - {"be", HB_TAG('B','E','L',' ')}, /* Belarussian */ + {"be", HB_TAG('B','E','L',' ')}, /* Belarusian */ {"bem", HB_TAG('B','E','M',' ')}, /* Bemba (Zambia) */ {"ber", HB_TAG('B','E','R',' ')}, /* Berber [family] */ {"bfq", HB_TAG('B','A','D',' ')}, /* Badaga */ {"bft", HB_TAG('B','L','T',' ')}, /* Balti */ {"bfy", HB_TAG('B','A','G',' ')}, /* Baghelkhandi */ {"bg", HB_TAG('B','G','R',' ')}, /* Bulgarian */ + {"bgc", HB_TAG('B','G','C',' ')}, /* Haryanvi */ + {"bgq", HB_TAG('B','G','Q',' ')}, /* Bagri */ {"bhb", HB_TAG('B','H','I',' ')}, /* Bhili */ + {"bhk", HB_TAG('B','I','K',' ')}, /* Albay Bicolano (retired code) */ {"bho", HB_TAG('B','H','O',' ')}, /* Bhojpuri */ - {"bik", HB_TAG('B','I','K',' ')}, /* Bikol */ + {"bi", HB_TAG('B','I','S',' ')}, /* Bislama */ + {"bik", HB_TAG('B','I','K',' ')}, /* Bikol [macrolanguage] */ {"bin", HB_TAG('E','D','O',' ')}, /* Bini */ + {"bjj", HB_TAG('B','J','J',' ')}, /* Kanauji */ {"bjt", HB_TAG('B','L','N',' ')}, /* Balanta-Ganja */ {"bla", HB_TAG('B','K','F',' ')}, /* Blackfoot */ {"ble", HB_TAG('B','L','N',' ')}, /* Balanta-Kentohe */ + {"blk", HB_TAG('B','L','K',' ')}, /* Pa'O/Pa'o Karen */ + {"bln", HB_TAG('B','I','K',' ')}, /* Southern Catanduanes Bikol */ {"bm", HB_TAG('B','M','B',' ')}, /* Bambara */ {"bn", HB_TAG('B','E','N',' ')}, /* Bengali */ {"bo", HB_TAG('T','I','B',' ')}, /* Tibetan */ + {"bpy", HB_TAG('B','P','Y',' ')}, /* Bishnupriya */ + {"bqi", HB_TAG('L','R','C',' ')}, /* Bakhtiari */ {"br", HB_TAG('B','R','E',' ')}, /* Breton */ {"bra", HB_TAG('B','R','I',' ')}, /* Braj Bhasha */ {"brh", HB_TAG('B','R','H',' ')}, /* Brahui */ + {"brx", HB_TAG('B','R','X',' ')}, /* Bodo (India) */ {"bs", HB_TAG('B','O','S',' ')}, /* Bosnian */ {"btb", HB_TAG('B','T','I',' ')}, /* Beti (Cameroon) */ + {"bto", HB_TAG('B','I','K',' ')}, /* Rinconada Bikol */ + {"bts", HB_TAG('B','T','S',' ')}, /* Batak Simalungun */ + {"bug", HB_TAG('B','U','G',' ')}, /* Buginese */ {"bxr", HB_TAG('R','B','U',' ')}, /* Russian Buriat */ {"byn", HB_TAG('B','I','L',' ')}, /* Bilen */ {"ca", HB_TAG('C','A','T',' ')}, /* Catalan */ + {"cbk", HB_TAG('C','B','K',' ')}, /* Chavacano */ {"ce", HB_TAG('C','H','E',' ')}, /* Chechen */ {"ceb", HB_TAG('C','E','B',' ')}, /* Cebuano */ + {"cgg", HB_TAG('C','G','G',' ')}, /* Chiga */ + {"ch", HB_TAG('C','H','A',' ')}, /* Chamorro */ + {"cho", HB_TAG('C','H','O',' ')}, /* Choctaw */ {"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */ {"chr", HB_TAG('C','H','R',' ')}, /* Cherokee */ + {"chy", HB_TAG('C','H','Y',' ')}, /* Cheyenne */ + {"ckb", HB_TAG('K','U','R',' ')}, /* Central Kurdish (Sorani) */ {"ckt", HB_TAG('C','H','K',' ')}, /* Chukchi */ {"cop", HB_TAG('C','O','P',' ')}, /* Coptic */ {"cr", HB_TAG('C','R','E',' ')}, /* Cree */ @@ -239,6 +274,9 @@ static const LangTag ot_languages[] = { {"crm", HB_TAG('M','C','R',' ')}, /* Moose Cree */ {"crx", HB_TAG('C','R','R',' ')}, /* Carrier */ {"cs", HB_TAG('C','S','Y',' ')}, /* Czech */ + {"csb", HB_TAG('C','S','B',' ')}, /* Kashubian */ + {"ctg", HB_TAG('C','T','G',' ')}, /* Chittagonian */ + {"cts", HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol */ {"cu", HB_TAG('C','S','L',' ')}, /* Church Slavic */ {"cv", HB_TAG('C','H','U',' ')}, /* Chuvash */ {"cwd", HB_TAG('D','C','R',' ')}, /* Woods Cree */ @@ -247,34 +285,42 @@ static const LangTag ot_languages[] = { {"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) */ {"dar", HB_TAG('D','A','R',' ')}, /* Dargwa */ {"de", HB_TAG('D','E','U',' ')}, /* German */ - {"din", HB_TAG('D','N','K',' ')}, /* Dinka */ - {"dje", HB_TAG('D','J','R',' ')}, /* Djerma */ + {"dgo", HB_TAG('D','G','O',' ')}, /* Dogri */ + {"dhd", HB_TAG('M','A','W',' ')}, /* Dhundari */ + {"din", HB_TAG('D','N','K',' ')}, /* Dinka [macrolanguage] */ + {"diq", HB_TAG('D','I','Q',' ')}, /* Dimli */ + {"dje", HB_TAG('D','J','R',' ')}, /* Zarma */ {"dng", HB_TAG('D','U','N',' ')}, /* Dungan */ - {"doi", HB_TAG('D','G','R',' ')}, /* Dogri */ + {"doi", HB_TAG('D','G','R',' ')}, /* Dogri [macrolanguage] */ {"dsb", HB_TAG('L','S','B',' ')}, /* Lower Sorbian */ - {"dv", HB_TAG('D','I','V',' ')}, /* Dhivehi */ + {"dv", HB_TAG('D','I','V',' ')}, /* Dhivehi/Divehi/Maldivian */ {"dyu", HB_TAG('J','U','L',' ')}, /* Jula */ {"dz", HB_TAG('D','Z','N',' ')}, /* Dzongkha */ {"ee", HB_TAG('E','W','E',' ')}, /* Ewe */ {"efi", HB_TAG('E','F','I',' ')}, /* Efik */ + {"ekk", HB_TAG('E','T','I',' ')}, /* Standard Estonian */ {"el", HB_TAG('E','L','L',' ')}, /* Modern Greek (1453-) */ + {"emk", HB_TAG('M','N','K',' ')}, /* Eastern Maninkakan */ {"en", HB_TAG('E','N','G',' ')}, /* English */ {"eo", HB_TAG('N','T','O',' ')}, /* Esperanto */ {"eot", HB_TAG('B','T','I',' ')}, /* Beti (Côte d'Ivoire) */ {"es", HB_TAG('E','S','P',' ')}, /* Spanish */ - {"et", HB_TAG('E','T','I',' ')}, /* Estonian */ + {"et", HB_TAG('E','T','I',' ')}, /* Estonian [macrolanguage] */ {"eu", HB_TAG('E','U','Q',' ')}, /* Basque */ {"eve", HB_TAG('E','V','N',' ')}, /* Even */ {"evn", HB_TAG('E','V','K',' ')}, /* Evenki */ - {"fa", HB_TAG('F','A','R',' ')}, /* Persian */ - {"ff", HB_TAG('F','U','L',' ')}, /* Fulah */ + {"fa", HB_TAG('F','A','R',' ')}, /* Persian [macrolanguage] */ + {"ff", HB_TAG('F','U','L',' ')}, /* Fulah [macrolanguage] */ {"fi", HB_TAG('F','I','N',' ')}, /* Finnish */ {"fil", HB_TAG('P','I','L',' ')}, /* Filipino */ {"fj", HB_TAG('F','J','I',' ')}, /* Fijian */ {"fo", HB_TAG('F','O','S',' ')}, /* Faroese */ {"fon", HB_TAG('F','O','N',' ')}, /* Fon */ {"fr", HB_TAG('F','R','A',' ')}, /* French */ + {"frc", HB_TAG('F','R','C',' ')}, /* Cajun French */ + {"frp", HB_TAG('F','R','P',' ')}, /* Arpitan/Francoprovençal */ {"fur", HB_TAG('F','R','L',' ')}, /* Friulian */ + {"fuv", HB_TAG('F','U','V',' ')}, /* Nigerian Fulfulde */ {"fy", HB_TAG('F','R','I',' ')}, /* Western Frisian */ {"ga", HB_TAG('I','R','I',' ')}, /* Irish */ {"gaa", HB_TAG('G','A','D',' ')}, /* Ga */ @@ -282,113 +328,167 @@ static const LangTag ot_languages[] = { {"gbm", HB_TAG('G','A','W',' ')}, /* Garhwali */ {"gd", HB_TAG('G','A','E',' ')}, /* Scottish Gaelic */ {"gez", HB_TAG('G','E','Z',' ')}, /* Ge'ez */ + {"ggo", HB_TAG('G','O','N',' ')}, /* Southern Gondi */ {"gl", HB_TAG('G','A','L',' ')}, /* Galician */ {"gld", HB_TAG('N','A','N',' ')}, /* Nanai */ - {"gn", HB_TAG('G','U','A',' ')}, /* Guarani */ - {"gon", HB_TAG('G','O','N',' ')}, /* Gondi */ + {"glk", HB_TAG('G','L','K',' ')}, /* Gilaki */ + {"gn", HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */ + {"gno", HB_TAG('G','O','N',' ')}, /* Northern Gondi */ + {"gog", HB_TAG('G','O','G',' ')}, /* Gogo */ + {"gon", HB_TAG('G','O','N',' ')}, /* Gondi [macrolanguage] */ {"grt", HB_TAG('G','R','O',' ')}, /* Garo */ {"gru", HB_TAG('S','O','G',' ')}, /* Sodo Gurage */ {"gu", HB_TAG('G','U','J',' ')}, /* Gujarati */ + {"guc", HB_TAG('G','U','C',' ')}, /* Wayuu */ {"guk", HB_TAG('G','M','Z',' ')}, /* Gumuz */ - {"gv", HB_TAG('M','N','X',' ')}, /* Manx Gaelic */ +/*{"guk", HB_TAG('G','U','K',' ')},*/ /* Gumuz (in SIL fonts) */ + {"guz", HB_TAG('G','U','Z',' ')}, /* Ekegusii/Gusii */ + {"gv", HB_TAG('M','N','X',' ')}, /* Manx */ {"ha", HB_TAG('H','A','U',' ')}, /* Hausa */ {"har", HB_TAG('H','R','I',' ')}, /* Harari */ - {"haw", HB_TAG('H','A','W',' ')}, /* Hawaiin */ + {"haw", HB_TAG('H','A','W',' ')}, /* Hawaiian */ + {"hay", HB_TAG('H','A','Y',' ')}, /* Haya */ + {"haz", HB_TAG('H','A','Z',' ')}, /* Hazaragi */ {"he", HB_TAG('I','W','R',' ')}, /* Hebrew */ + {"hz", HB_TAG('H','E','R',' ')}, /* Herero */ {"hi", HB_TAG('H','I','N',' ')}, /* Hindi */ {"hil", HB_TAG('H','I','L',' ')}, /* Hiligaynon */ {"hnd", HB_TAG('H','N','D',' ')}, /* [Southern] Hindko */ {"hne", HB_TAG('C','H','H',' ')}, /* Chattisgarhi */ {"hno", HB_TAG('H','N','D',' ')}, /* [Northern] Hindko */ + {"ho", HB_TAG('H','M','O',' ')}, /* Hiri Motu */ {"hoc", HB_TAG('H','O',' ',' ')}, /* Ho */ {"hoj", HB_TAG('H','A','R',' ')}, /* Harauti */ {"hr", HB_TAG('H','R','V',' ')}, /* Croatian */ {"hsb", HB_TAG('U','S','B',' ')}, /* Upper Sorbian */ - {"ht", HB_TAG('H','A','I',' ')}, /* Haitian */ + {"ht", HB_TAG('H','A','I',' ')}, /* Haitian/Haitian Creole */ {"hu", HB_TAG('H','U','N',' ')}, /* Hungarian */ {"hy", HB_TAG('H','Y','E',' ')}, /* Armenian */ + {"hz", HB_TAG('H','E','R',' ')}, /* Herero */ + {"ia", HB_TAG('I','N','A',' ')}, /* Interlingua (International Auxiliary Language Association) */ + {"ibb", HB_TAG('I','B','B',' ')}, /* Ibibio */ {"id", HB_TAG('I','N','D',' ')}, /* Indonesian */ + {"ie", HB_TAG('I','L','E',' ')}, /* Interlingue/Occidental */ {"ig", HB_TAG('I','B','O',' ')}, /* Igbo */ {"igb", HB_TAG('E','B','I',' ')}, /* Ebira */ + {"ijc", HB_TAG('I','J','O',' ')}, /* Izon */ {"ijo", HB_TAG('I','J','O',' ')}, /* Ijo [family] */ + {"ik", HB_TAG('I','P','K',' ')}, /* Inupiaq [macrolanguage] */ {"ilo", HB_TAG('I','L','O',' ')}, /* Ilokano */ {"inh", HB_TAG('I','N','G',' ')}, /* Ingush */ + {"io", HB_TAG('I','D','O',' ')}, /* Ido */ {"is", HB_TAG('I','S','L',' ')}, /* Icelandic */ {"it", HB_TAG('I','T','A',' ')}, /* Italian */ - {"iu", HB_TAG('I','N','U',' ')}, /* Inuktitut */ + {"iu", HB_TAG('I','N','U',' ')}, /* Inuktitut [macrolanguage] */ {"ja", HB_TAG('J','A','N',' ')}, /* Japanese */ + {"jam", HB_TAG('J','A','M',' ')}, /* Jamaican Creole English */ + {"jbo", HB_TAG('J','B','O',' ')}, /* Lojban */ {"jv", HB_TAG('J','A','V',' ')}, /* Javanese */ {"ka", HB_TAG('K','A','T',' ')}, /* Georgian */ {"kaa", HB_TAG('K','R','K',' ')}, /* Karakalpak */ + {"kab", HB_TAG('K','A','B',' ')}, /* Kabyle */ {"kam", HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */ {"kar", HB_TAG('K','R','N',' ')}, /* Karen [family] */ {"kbd", HB_TAG('K','A','B',' ')}, /* Kabardian */ + {"kde", HB_TAG('K','D','E',' ')}, /* Makonde */ {"kdr", HB_TAG('K','R','M',' ')}, /* Karaim */ {"kdt", HB_TAG('K','U','Y',' ')}, /* Kuy */ {"kex", HB_TAG('K','K','N',' ')}, /* Kokni */ {"kfr", HB_TAG('K','A','C',' ')}, /* Kachchi */ {"kfy", HB_TAG('K','M','N',' ')}, /* Kumaoni */ + {"kg", HB_TAG('K','O','N',' ')}, /* Kongo [macrolanguage] */ {"kha", HB_TAG('K','S','I',' ')}, /* Khasi */ - {"khb", HB_TAG('X','B','D',' ')}, /* Tai Lue */ + {"khb", HB_TAG('X','B','D',' ')}, /* Lü */ + {"kht", HB_TAG('K','H','N',' ')}, /* Khamti (Microsoft fonts) */ +/*{"kht", HB_TAG('K','H','T',' ')},*/ /* Khamti (OpenType spec and SIL fonts) */ {"khw", HB_TAG('K','H','W',' ')}, /* Khowar */ - {"ki", HB_TAG('K','I','K',' ')}, /* Kikuyu */ + {"ki", HB_TAG('K','I','K',' ')}, /* Gikuyu/Kikuyu */ + {"kj", HB_TAG('K','U','A',' ')}, /* Kuanyama/Kwanyama */ {"kjh", HB_TAG('K','H','A',' ')}, /* Khakass */ + {"kjp", HB_TAG('K','J','P',' ')}, /* Pwo Eastern Karen */ {"kk", HB_TAG('K','A','Z',' ')}, /* Kazakh */ {"kl", HB_TAG('G','R','N',' ')}, /* Kalaallisut */ {"kln", HB_TAG('K','A','L',' ')}, /* Kalenjin */ {"km", HB_TAG('K','H','M',' ')}, /* Central Khmer */ - {"kmb", HB_TAG('M','B','N',' ')}, /* [North] Mbundu */ + {"kmb", HB_TAG('M','B','N',' ')}, /* Kimbundu */ {"kmw", HB_TAG('K','M','O',' ')}, /* Komo (Democratic Republic of Congo) */ {"kn", HB_TAG('K','A','N',' ')}, /* Kannada */ + {"knn", HB_TAG('K','O','K',' ')}, /* Konkani */ {"ko", HB_TAG('K','O','R',' ')}, /* Korean */ {"koi", HB_TAG('K','O','P',' ')}, /* Komi-Permyak */ - {"kok", HB_TAG('K','O','K',' ')}, /* Konkani */ - {"kpe", HB_TAG('K','P','L',' ')}, /* Kpelle */ + {"kok", HB_TAG('K','O','K',' ')}, /* Konkani [macrolanguage] */ + {"kpe", HB_TAG('K','P','L',' ')}, /* Kpelle [macrolanguage] */ {"kpv", HB_TAG('K','O','Z',' ')}, /* Komi-Zyrian */ {"kpy", HB_TAG('K','Y','K',' ')}, /* Koryak */ {"kqy", HB_TAG('K','R','T',' ')}, /* Koorete */ - {"kr", HB_TAG('K','N','R',' ')}, /* Kanuri */ + {"kr", HB_TAG('K','N','R',' ')}, /* Kanuri [macrolanguage] */ {"kri", HB_TAG('K','R','I',' ')}, /* Krio */ {"krl", HB_TAG('K','R','L',' ')}, /* Karelian */ {"kru", HB_TAG('K','U','U',' ')}, /* Kurukh */ {"ks", HB_TAG('K','S','H',' ')}, /* Kashmiri */ - {"ku", HB_TAG('K','U','R',' ')}, /* Kurdish */ + {"ksh", HB_TAG('K','S','H',' ')}, /* Kölsch */ +/*{"ksw", HB_TAG('K','R','N',' ')},*/ /* S'gaw Karen (Microsoft fonts?) */ + {"ksw", HB_TAG('K','S','W',' ')}, /* S'gaw Karen (OpenType spec and SIL fonts) */ + {"ku", HB_TAG('K','U','R',' ')}, /* Kurdish [macrolanguage] */ {"kum", HB_TAG('K','U','M',' ')}, /* Kumyk */ + {"kv", HB_TAG('K','O','M',' ')}, /* Komi [macrolanguage] */ {"kvd", HB_TAG('K','U','I',' ')}, /* Kui (Indonesia) */ + {"kw", HB_TAG('C','O','R',' ')}, /* Cornish */ {"kxc", HB_TAG('K','M','S',' ')}, /* Komso */ {"kxu", HB_TAG('K','U','I',' ')}, /* Kui (India) */ - {"ky", HB_TAG('K','I','R',' ')}, /* Kirghiz */ + {"ky", HB_TAG('K','I','R',' ')}, /* Kirghiz/Kyrgyz */ + {"kyu", HB_TAG('K','Y','U',' ')}, /* Western Kayah */ {"la", HB_TAG('L','A','T',' ')}, /* Latin */ {"lad", HB_TAG('J','U','D',' ')}, /* Ladino */ {"lb", HB_TAG('L','T','Z',' ')}, /* Luxembourgish */ {"lbe", HB_TAG('L','A','K',' ')}, /* Lak */ {"lbj", HB_TAG('L','D','K',' ')}, /* Ladakhi */ {"lez", HB_TAG('L','E','Z',' ')}, /* Lezgi */ - {"lg", HB_TAG('L','U','G',' ')}, /* Luganda */ + {"lg", HB_TAG('L','U','G',' ')}, /* Ganda */ + {"li", HB_TAG('L','I','M',' ')}, /* Limburgan/Limburger/Limburgish */ {"lif", HB_TAG('L','M','B',' ')}, /* Limbu */ + {"lij", HB_TAG('L','I','J',' ')}, /* Ligurian */ + {"lis", HB_TAG('L','I','S',' ')}, /* Lisu */ + {"ljp", HB_TAG('L','J','P',' ')}, /* Lampung Api */ + {"lki", HB_TAG('L','K','I',' ')}, /* Laki */ {"lld", HB_TAG('L','A','D',' ')}, /* Ladin */ {"lmn", HB_TAG('L','A','M',' ')}, /* Lambani */ + {"lmo", HB_TAG('L','M','O',' ')}, /* Lombard */ {"ln", HB_TAG('L','I','N',' ')}, /* Lingala */ {"lo", HB_TAG('L','A','O',' ')}, /* Lao */ + {"lrc", HB_TAG('L','R','C',' ')}, /* Northern Luri */ {"lt", HB_TAG('L','T','H',' ')}, /* Lithuanian */ {"lu", HB_TAG('L','U','B',' ')}, /* Luba-Katanga */ {"lua", HB_TAG('L','U','B',' ')}, /* Luba-Kasai */ {"luo", HB_TAG('L','U','O',' ')}, /* Luo (Kenya and Tanzania) */ {"lus", HB_TAG('M','I','Z',' ')}, /* Mizo */ - {"luy", HB_TAG('L','U','H',' ')}, /* Luhya [macrolanguage] */ + {"luy", HB_TAG('L','U','H',' ')}, /* Luyia/Oluluyia [macrolanguage] */ + {"luz", HB_TAG('L','R','C',' ')}, /* Southern Luri */ {"lv", HB_TAG('L','V','I',' ')}, /* Latvian */ {"lzz", HB_TAG('L','A','Z',' ')}, /* Laz */ + {"mad", HB_TAG('M','A','D',' ')}, /* Madurese */ + {"mag", HB_TAG('M','A','G',' ')}, /* Magahi */ {"mai", HB_TAG('M','T','H',' ')}, /* Maithili */ + {"mak", HB_TAG('M','K','R',' ')}, /* Makasar */ + {"man", HB_TAG('M','N','K',' ')}, /* Manding/Mandingo [macrolanguage] */ {"mdc", HB_TAG('M','L','E',' ')}, /* Male (Papua New Guinea) */ {"mdf", HB_TAG('M','O','K',' ')}, /* Moksha */ + {"mdr", HB_TAG('M','D','R',' ')}, /* Mandar */ {"mdy", HB_TAG('M','L','E',' ')}, /* Male (Ethiopia) */ {"men", HB_TAG('M','D','E',' ')}, /* Mende (Sierra Leone) */ - {"mg", HB_TAG('M','L','G',' ')}, /* Malagasy */ + {"mer", HB_TAG('M','E','R',' ')}, /* Meru */ + {"mfe", HB_TAG('M','F','E',' ')}, /* Morisyen */ + {"mg", HB_TAG('M','L','G',' ')}, /* Malagasy [macrolanguage] */ + {"mh", HB_TAG('M','A','H',' ')}, /* Marshallese */ {"mhr", HB_TAG('L','M','A',' ')}, /* Low Mari */ {"mi", HB_TAG('M','R','I',' ')}, /* Maori */ + {"min", HB_TAG('M','I','N',' ')}, /* Minangkabau */ {"mk", HB_TAG('M','K','D',' ')}, /* Macedonian */ + {"mku", HB_TAG('M','N','K',' ')}, /* Konyanka Maninka */ + {"mkw", HB_TAG('M','K','W',' ')}, /* Kituba (Congo) */ {"ml", HB_TAG('M','L','R',' ')}, /* Malayalam */ - {"mn", HB_TAG('M','N','G',' ')}, /* Mongolian */ + {"mlq", HB_TAG('M','N','K',' ')}, /* Western Maninkakan */ + {"mn", HB_TAG('M','N','G',' ')}, /* Mongolian [macrolanguage] */ {"mnc", HB_TAG('M','C','H',' ')}, /* Manchu */ {"mni", HB_TAG('M','N','I',' ')}, /* Manipuri */ {"mnk", HB_TAG('M','N','D',' ')}, /* Mandinka */ @@ -396,72 +496,119 @@ static const LangTag ot_languages[] = { {"mnw", HB_TAG('M','O','N',' ')}, /* Mon */ {"mo", HB_TAG('M','O','L',' ')}, /* Moldavian */ {"moh", HB_TAG('M','O','H',' ')}, /* Mohawk */ + {"mos", HB_TAG('M','O','S',' ')}, /* Mossi */ {"mpe", HB_TAG('M','A','J',' ')}, /* Majang */ {"mr", HB_TAG('M','A','R',' ')}, /* Marathi */ {"mrj", HB_TAG('H','M','A',' ')}, /* High Mari */ - {"ms", HB_TAG('M','L','Y',' ')}, /* Malay */ + {"ms", HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */ + {"msc", HB_TAG('M','N','K',' ')}, /* Sankaran Maninka */ {"mt", HB_TAG('M','T','S',' ')}, /* Maltese */ - {"mwr", HB_TAG('M','A','W',' ')}, /* Marwari */ + {"mtr", HB_TAG('M','A','W',' ')}, /* Mewari */ + {"mus", HB_TAG('M','U','S',' ')}, /* Creek */ + {"mve", HB_TAG('M','A','W',' ')}, /* Marwari (Pakistan) */ + {"mwk", HB_TAG('M','N','K',' ')}, /* Kita Maninkakan */ + {"mwl", HB_TAG('M','W','L',' ')}, /* Mirandese */ + {"mwr", HB_TAG('M','A','W',' ')}, /* Marwari [macrolanguage] */ + {"mww", HB_TAG('M','W','W',' ')}, /* Hmong Daw */ {"my", HB_TAG('B','R','M',' ')}, /* Burmese */ {"mym", HB_TAG('M','E','N',' ')}, /* Me'en */ + {"myq", HB_TAG('M','N','K',' ')}, /* Forest Maninka (retired code) */ {"myv", HB_TAG('E','R','Z',' ')}, /* Erzya */ + {"mzn", HB_TAG('M','Z','N',' ')}, /* Mazanderani */ + {"na", HB_TAG('N','A','U',' ')}, /* Nauru */ {"nag", HB_TAG('N','A','G',' ')}, /* Naga-Assamese */ + {"nah", HB_TAG('N','A','H',' ')}, /* Nahuatl [family] */ + {"nap", HB_TAG('N','A','P',' ')}, /* Neapolitan */ {"nb", HB_TAG('N','O','R',' ')}, /* Norwegian Bokmål */ {"nco", HB_TAG('S','I','B',' ')}, /* Sibe */ {"nd", HB_TAG('N','D','B',' ')}, /* [North] Ndebele */ + {"ndc", HB_TAG('N','D','C',' ')}, /* Ndau */ + {"nds", HB_TAG('N','D','S',' ')}, /* Low German/Low Saxon */ {"ne", HB_TAG('N','E','P',' ')}, /* Nepali */ {"new", HB_TAG('N','E','W',' ')}, /* Newari */ {"ng", HB_TAG('N','D','G',' ')}, /* Ndonga */ + {"nga", HB_TAG('N','G','A',' ')}, /* Ngabaka */ {"ngl", HB_TAG('L','M','W',' ')}, /* Lomwe */ {"niu", HB_TAG('N','I','U',' ')}, /* Niuean */ {"niv", HB_TAG('G','I','L',' ')}, /* Gilyak */ {"nl", HB_TAG('N','L','D',' ')}, /* Dutch */ {"nn", HB_TAG('N','Y','N',' ')}, /* Norwegian Nynorsk */ - {"no", HB_TAG('N','O','R',' ')}, /* Norwegian (deprecated) */ - {"nod", HB_TAG('N','T','A',' ')}, /* Northern Tai */ + {"no", HB_TAG('N','O','R',' ')}, /* Norwegian [macrolanguage] */ + {"nod", HB_TAG('N','T','A',' ')}, /* Northern Thai */ + {"noe", HB_TAG('N','O','E',' ')}, /* Nimadi */ {"nog", HB_TAG('N','O','G',' ')}, /* Nogai */ + {"nov", HB_TAG('N','O','V',' ')}, /* Novial */ {"nqo", HB_TAG('N','K','O',' ')}, /* N'Ko */ {"nr", HB_TAG('N','D','B',' ')}, /* [South] Ndebele */ {"nsk", HB_TAG('N','A','S',' ')}, /* Naskapi */ {"nso", HB_TAG('S','O','T',' ')}, /* [Northern] Sotho */ - {"ny", HB_TAG('C','H','I',' ')}, /* Nyanja */ - {"nyn", HB_TAG('N','K','L',' ')}, /* Nkole */ + {"ny", HB_TAG('C','H','I',' ')}, /* Chewa/Chichwa/Nyanja */ + {"nym", HB_TAG('N','Y','M',' ')}, /* Nyamwezi */ + {"nyn", HB_TAG('N','K','L',' ')}, /* Nyankole */ {"oc", HB_TAG('O','C','I',' ')}, /* Occitan (post 1500) */ - {"oj", HB_TAG('O','J','B',' ')}, /* Ojibwa */ + {"oj", HB_TAG('O','J','B',' ')}, /* Ojibwa [macrolanguage] */ {"ojs", HB_TAG('O','C','R',' ')}, /* Oji-Cree */ - {"om", HB_TAG('O','R','O',' ')}, /* Oromo */ + {"om", HB_TAG('O','R','O',' ')}, /* Oromo [macrolanguage] */ {"or", HB_TAG('O','R','I',' ')}, /* Oriya */ {"os", HB_TAG('O','S','S',' ')}, /* Ossetian */ {"pa", HB_TAG('P','A','N',' ')}, /* Panjabi */ + {"pag", HB_TAG('P','A','G',' ')}, /* Pangasinan */ + {"pam", HB_TAG('P','A','M',' ')}, /* Kapampangan/Pampanga */ + {"pap", HB_TAG('P','A','P',' ')}, /* Papiamento */ + {"pcc", HB_TAG('P','C','C',' ')}, /* Bouyei */ + {"pcd", HB_TAG('P','C','D',' ')}, /* Picard */ {"pce", HB_TAG('P','L','G',' ')}, /* [Ruching] Palaung */ + {"pdc", HB_TAG('P','D','C',' ')}, /* Pennsylvania German */ + {"pes", HB_TAG('F','A','R',' ')}, /* Iranian Persian */ + {"phk", HB_TAG('P','H','K',' ')}, /* Phake */ {"pi", HB_TAG('P','A','L',' ')}, /* Pali */ + {"pih", HB_TAG('P','I','H',' ')}, /* Pitcairn-Norfolk */ {"pl", HB_TAG('P','L','K',' ')}, /* Polish */ {"pll", HB_TAG('P','L','G',' ')}, /* [Shwe] Palaung */ {"plp", HB_TAG('P','A','P',' ')}, /* Palpa */ - {"prs", HB_TAG('D','R','I',' ')}, /* Dari */ - {"ps", HB_TAG('P','A','S',' ')}, /* Pushto */ + {"pms", HB_TAG('P','M','S',' ')}, /* Piemontese */ + {"pnb", HB_TAG('P','N','B',' ')}, /* Western Panjabi */ + {"prs", HB_TAG('D','R','I',' ')}, /* Afghan Persian/Dari */ + {"ps", HB_TAG('P','A','S',' ')}, /* Pashto/Pushto [macrolanguage] */ {"pt", HB_TAG('P','T','G',' ')}, /* Portuguese */ - {"raj", HB_TAG('R','A','J',' ')}, /* Rajasthani */ - {"rbb", HB_TAG('P','L','G',' ')}, /* [Rumai] Palaung */ + {"pwo", HB_TAG('P','W','O',' ')}, /* Pwo Western Karen */ + {"qu", HB_TAG('Q','U','Z',' ')}, /* Quechua [macrolanguage] */ + {"quc", HB_TAG('Q','U','C',' ')}, /* K'iche'/Quiché */ + {"quz", HB_TAG('Q','U','Z',' ')}, /* Cusco Quechua */ + {"raj", HB_TAG('R','A','J',' ')}, /* Rajasthani [macrolanguage] */ + {"rbb", HB_TAG('P','L','G',' ')}, /* Rumai Palaung */ + {"rej", HB_TAG('R','E','J',' ')}, /* Rejang */ {"ria", HB_TAG('R','I','A',' ')}, /* Riang (India) */ {"ril", HB_TAG('R','I','A',' ')}, /* Riang (Myanmar) */ - {"rki", HB_TAG('A','R','K',' ')}, /* Arakanese */ - {"rm", HB_TAG('R','M','S',' ')}, /* Rhaeto-Romanic */ + {"rki", HB_TAG('A','R','K',' ')}, /* Rakhine */ + {"rm", HB_TAG('R','M','S',' ')}, /* Romansh */ + {"rmy", HB_TAG('R','M','Y',' ')}, /* Vlax Romani */ + {"rn", HB_TAG('R','U','N',' ')}, /* Rundi */ {"ro", HB_TAG('R','O','M',' ')}, /* Romanian */ - {"rom", HB_TAG('R','O','Y',' ')}, /* Romany */ + {"rom", HB_TAG('R','O','Y',' ')}, /* Romany [macrolanguage] */ {"ru", HB_TAG('R','U','S',' ')}, /* Russian */ {"rue", HB_TAG('R','S','Y',' ')}, /* Rusyn */ - {"rw", HB_TAG('R','U','A',' ')}, /* Ruanda */ + {"rup", HB_TAG('R','U','P',' ')}, /* Aromanian/Arumanian/Macedo-Romanian */ + {"rw", HB_TAG('R','U','A',' ')}, /* Kinyarwanda */ + {"rwr", HB_TAG('M','A','W',' ')}, /* Marwari (India) */ {"sa", HB_TAG('S','A','N',' ')}, /* Sanskrit */ {"sah", HB_TAG('Y','A','K',' ')}, /* Yakut */ + {"sas", HB_TAG('S','A','S',' ')}, /* Sasak */ {"sat", HB_TAG('S','A','T',' ')}, /* Santali */ {"sck", HB_TAG('S','A','D',' ')}, /* Sadri */ + {"sc", HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */ + {"scn", HB_TAG('S','C','N',' ')}, /* Sicilian */ + {"sco", HB_TAG('S','C','O',' ')}, /* Scots */ {"scs", HB_TAG('S','L','A',' ')}, /* [North] Slavey */ {"sd", HB_TAG('S','N','D',' ')}, /* Sindhi */ {"se", HB_TAG('N','S','M',' ')}, /* Northern Sami */ {"seh", HB_TAG('S','N','A',' ')}, /* Sena */ {"sel", HB_TAG('S','E','L',' ')}, /* Selkup */ {"sg", HB_TAG('S','G','O',' ')}, /* Sango */ + {"sga", HB_TAG('S','G','A',' ')}, /* Old Irish (to 900) */ + {"sgs", HB_TAG('S','G','S',' ')}, /* Samogitian */ + {"sgw", HB_TAG('C','H','G',' ')}, /* Sebat Bet Gurage */ +/*{"sgw", HB_TAG('S','G','W',' ')},*/ /* Sebat Bet Gurage (in SIL fonts) */ {"shn", HB_TAG('S','H','N',' ')}, /* Shan */ {"si", HB_TAG('S','N','H',' ')}, /* Sinhala */ {"sid", HB_TAG('S','I','D',' ')}, /* Sidamo */ @@ -474,60 +621,98 @@ static const LangTag ot_languages[] = { {"smj", HB_TAG('L','S','M',' ')}, /* Lule Sami */ {"smn", HB_TAG('I','S','M',' ')}, /* Inari Sami */ {"sms", HB_TAG('S','K','S',' ')}, /* Skolt Sami */ + {"sn", HB_TAG('S','N','A',' ')}, /* Shona */ {"snk", HB_TAG('S','N','K',' ')}, /* Soninke */ {"so", HB_TAG('S','M','L',' ')}, /* Somali */ - {"sq", HB_TAG('S','Q','I',' ')}, /* Albanian */ + {"sop", HB_TAG('S','O','P',' ')}, /* Songe */ + {"sq", HB_TAG('S','Q','I',' ')}, /* Albanian [macrolanguage] */ {"sr", HB_TAG('S','R','B',' ')}, /* Serbian */ {"srr", HB_TAG('S','R','R',' ')}, /* Serer */ - {"ss", HB_TAG('S','W','Z',' ')}, /* Swazi */ + {"ss", HB_TAG('S','W','Z',' ')}, /* Swati */ {"st", HB_TAG('S','O','T',' ')}, /* [Southern] Sotho */ + {"stq", HB_TAG('S','T','Q',' ')}, /* Saterfriesisch */ + {"stv", HB_TAG('S','I','G',' ')}, /* Silt'e */ + {"su", HB_TAG('S','U','N',' ')}, /* Sundanese */ + {"suk", HB_TAG('S','U','K',' ')}, /* Sukama */ {"suq", HB_TAG('S','U','R',' ')}, /* Suri */ {"sv", HB_TAG('S','V','E',' ')}, /* Swedish */ {"sva", HB_TAG('S','V','A',' ')}, /* Svan */ - {"sw", HB_TAG('S','W','K',' ')}, /* Swahili */ + {"sw", HB_TAG('S','W','K',' ')}, /* Swahili [macrolanguage] */ {"swb", HB_TAG('C','M','R',' ')}, /* Comorian */ - {"syr", HB_TAG('S','Y','R',' ')}, /* Syriac */ + {"swh", HB_TAG('S','W','K',' ')}, /* Kiswahili/Swahili */ + {"swv", HB_TAG('M','A','W',' ')}, /* Shekhawati */ + {"sxu", HB_TAG('S','X','U',' ')}, /* Upper Saxon */ + {"syl", HB_TAG('S','Y','L',' ')}, /* Sylheti */ + {"syr", HB_TAG('S','Y','R',' ')}, /* Syriac [macrolanguage] */ + {"szl", HB_TAG('S','Z','L',' ')}, /* Silesian */ {"ta", HB_TAG('T','A','M',' ')}, /* Tamil */ {"tab", HB_TAG('T','A','B',' ')}, /* Tabasaran */ {"tcy", HB_TAG('T','U','L',' ')}, /* Tulu */ + {"tdd", HB_TAG('T','D','D',' ')}, /* Tai Nüa */ {"te", HB_TAG('T','E','L',' ')}, /* Telugu */ {"tem", HB_TAG('T','M','N',' ')}, /* Temne */ + {"tet", HB_TAG('T','E','T',' ')}, /* Tetum */ {"tg", HB_TAG('T','A','J',' ')}, /* Tajik */ {"th", HB_TAG('T','H','A',' ')}, /* Thai */ {"ti", HB_TAG('T','G','Y',' ')}, /* Tigrinya */ {"tig", HB_TAG('T','G','R',' ')}, /* Tigre */ + {"tiv", HB_TAG('T','I','V',' ')}, /* Tiv */ {"tk", HB_TAG('T','K','M',' ')}, /* Turkmen */ + {"tl", HB_TAG('T','G','L',' ')}, /* Tagalog */ + {"tmh", HB_TAG('t','m','h',' ')}, /* Tamashek [macrolanguage] */ {"tn", HB_TAG('T','N','A',' ')}, /* Tswana */ {"to", HB_TAG('T','G','N',' ')}, /* Tonga (Tonga Islands) */ + {"tpi", HB_TAG('T','P','I',' ')}, /* Tok Pisin */ {"tr", HB_TAG('T','R','K',' ')}, /* Turkish */ {"tru", HB_TAG('T','U','A',' ')}, /* Turoyo Aramaic */ {"ts", HB_TAG('T','S','G',' ')}, /* Tsonga */ {"tt", HB_TAG('T','A','T',' ')}, /* Tatar */ + {"tum", HB_TAG('T','U','M',' ')}, /* Tumbuka */ {"tw", HB_TAG('T','W','I',' ')}, /* Twi */ {"ty", HB_TAG('T','H','T',' ')}, /* Tahitian */ {"tyv", HB_TAG('T','U','V',' ')}, /* Tuvin */ + {"tyz", HB_TAG('T','Y','Z',' ')}, /* Tày */ + {"tzm", HB_TAG('T','Z','M',' ')}, /* Central Atlas Tamazight */ {"udm", HB_TAG('U','D','M',' ')}, /* Udmurt */ {"ug", HB_TAG('U','Y','G',' ')}, /* Uighur */ {"uk", HB_TAG('U','K','R',' ')}, /* Ukrainian */ - {"umb", HB_TAG('M','B','N',' ')}, /* [South] Mbundu */ + {"umb", HB_TAG('U','M','B',' ')}, /* Umbundu */ {"unr", HB_TAG('M','U','N',' ')}, /* Mundari */ {"ur", HB_TAG('U','R','D',' ')}, /* Urdu */ - {"uz", HB_TAG('U','Z','B',' ')}, /* Uzbek */ + {"uz", HB_TAG('U','Z','B',' ')}, /* Uzbek [macrolanguage] */ + {"uzn", HB_TAG('U','Z','B',' ')}, /* Northern Uzbek */ + {"uzs", HB_TAG('U','Z','B',' ')}, /* Southern Uzbek */ {"ve", HB_TAG('V','E','N',' ')}, /* Venda */ + {"vec", HB_TAG('V','E','C',' ')}, /* Venetian */ + {"vls", HB_TAG('F','L','E',' ')}, /* Vlaams */ {"vi", HB_TAG('V','I','T',' ')}, /* Vietnamese */ - {"vmw", HB_TAG('M','A','K',' ')}, /* Makua */ + {"vmw", HB_TAG('M','A','K',' ')}, /* Makhuwa */ + {"vo", HB_TAG('V','O','L',' ')}, /* Volapük */ + {"vro", HB_TAG('V','R','O',' ')}, /* Võro */ + {"wa", HB_TAG('W','L','N',' ')}, /* Walloon */ + {"war", HB_TAG('W','A','R',' ')}, /* Waray (Philippines) */ {"wbm", HB_TAG('W','A',' ',' ')}, /* Wa */ {"wbr", HB_TAG('W','A','G',' ')}, /* Wagdi */ + {"wle", HB_TAG('S','I','G',' ')}, /* Wolane */ + {"wry", HB_TAG('M','A','W',' ')}, /* Merwari */ + {"wtm", HB_TAG('W','T','M',' ')}, /* Mewati */ {"wo", HB_TAG('W','L','F',' ')}, /* Wolof */ {"xal", HB_TAG('K','L','M',' ')}, /* Kalmyk */ {"xh", HB_TAG('X','H','S',' ')}, /* Xhosa */ + {"xog", HB_TAG('X','O','G',' ')}, /* Soga */ {"xom", HB_TAG('K','M','O',' ')}, /* Komo (Sudan) */ {"xsl", HB_TAG('S','S','L',' ')}, /* South Slavey */ - {"yi", HB_TAG('J','I','I',' ')}, /* Yiddish */ + {"xst", HB_TAG('S','I','G',' ')}, /* Silt'e (retired code) */ + {"xwo", HB_TAG('T','O','D',' ')}, /* Written Oirat (Todo) */ + {"yao", HB_TAG('Y','A','O',' ')}, /* Yao */ + {"yi", HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */ {"yo", HB_TAG('Y','B','A',' ')}, /* Yoruba */ {"yso", HB_TAG('N','I','S',' ')}, /* Nisi (China) */ + {"za", HB_TAG('Z','H','A',' ')}, /* Chuang/Zhuang [macrolanguage] */ + {"zea", HB_TAG('Z','E','A',' ')}, /* Zeeuws */ {"zne", HB_TAG('Z','N','D',' ')}, /* Zande */ - {"zu", HB_TAG('Z','U','L',' ')} /* Zulu */ + {"zu", HB_TAG('Z','U','L',' ')}, /* Zulu */ + {"zum", HB_TAG('L','R','C',' ')} /* Kumzari */ /* The corresponding languages IDs for the following IDs are unclear, * overlap, or are architecturally weird. Needs more research. */ @@ -536,13 +721,13 @@ static const LangTag ot_languages[] = { /*{"gsw?/gsw-FR?", HB_TAG('A','L','S',' ')},*/ /* Alsatian */ /*{"krc", HB_TAG('B','A','L',' ')},*/ /* Balkar */ /*{"??", HB_TAG('B','C','R',' ')},*/ /* Bible Cree */ -/*{"sgw?", HB_TAG('C','H','G',' ')},*/ /* Chaha Gurage */ +/*{"zh?", HB_TAG('C','H','N',' ')},*/ /* Chinese (seen in Microsoft fonts) */ /*{"acf/gcf?", HB_TAG('F','A','N',' ')},*/ /* French Antillean */ -/*{"vls/nl-be", HB_TAG('F','L','E',' ')},*/ /* Flemish */ /*{"enf?/yrk?", HB_TAG('F','N','E',' ')},*/ /* Forest Nenets */ /*{"fuf?", HB_TAG('F','T','A',' ')},*/ /* Futa */ /*{"ar-Syrc?", HB_TAG('G','A','R',' ')},*/ /* Garshuni */ /*{"cfm/rnl?", HB_TAG('H','A','L',' ')},*/ /* Halam */ +/*{"fonipa", HB_TAG('I','P','P','H')},*/ /* Phonetic transcription—IPA conventions */ /*{"ga-Latg?/Latg?", HB_TAG('I','R','T',' ')},*/ /* Irish Traditional */ /*{"krc", HB_TAG('K','A','R',' ')},*/ /* Karachay */ /*{"alw?/ktb?", HB_TAG('K','E','B',' ')},*/ /* Kebena */ @@ -559,8 +744,6 @@ static const LangTag ot_languages[] = { /*{"??", HB_TAG('L','C','R',' ')},*/ /* L-Cree */ /*{"??", HB_TAG('M','A','L',' ')},*/ /* Malayalam Traditional */ /*{"mnk?/mlq?/...", HB_TAG('M','L','N',' ')},*/ /* Malinke */ -/*{"man?/myq?/mku?/msc?/...", HB_TAG('M','N','K',' ')},*/ /* Maninka */ -/*{"??", HB_TAG('M','O','R',' ')},*/ /* Moroccan */ /*{"??", HB_TAG('N','C','R',' ')},*/ /* N-Cree */ /*{"??", HB_TAG('N','H','C',' ')},*/ /* Norway House Cree */ /*{"jpa?/sam?", HB_TAG('P','A','A',' ')},*/ /* Palestinian Aramaic */ @@ -569,14 +752,12 @@ static const LangTag ot_languages[] = { /*{"??", HB_TAG('R','C','R',' ')},*/ /* R-Cree */ /*{"chp?", HB_TAG('S','A','Y',' ')},*/ /* Sayisi */ /*{"xan?", HB_TAG('S','E','K',' ')},*/ /* Sekota */ -/*{"stv/wle?/xst?", HB_TAG('S','I','G',' ')},*/ /* Silte Gurage */ /*{"ngo?", HB_TAG('S','X','T',' ')},*/ /* Sutu */ /*{"??", HB_TAG('T','C','R',' ')},*/ /* TH-Cree */ /*{"tnz?/tog?/toi?", HB_TAG('T','N','G',' ')},*/ /* Tonga */ /*{"enh?/yrk?", HB_TAG('T','N','E',' ')},*/ /* Tundra Nenets */ -/*{"??", HB_TAG('T','O','D',' ')},*/ /* Todo */ /*{"??", HB_TAG('W','C','R',' ')},*/ /* West-Cree */ -/*{"??", HB_TAG('Y','C','R',' ')},*/ /* Y-Cree */ +/*{"cre?", HB_TAG('Y','C','R',' ')},*/ /* Y-Cree */ /*{"??", HB_TAG('Y','I','C',' ')},*/ /* Yi Classic */ /*{"ii?/Yiii?", HB_TAG('Y','I','M',' ')},*/ /* Yi Modern */ /*{"??", HB_TAG('Z','H','P',' ')},*/ /* Chinese Phonetic */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-private.hh index 4152e27552..4b72260ed5 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-private.hh @@ -79,6 +79,9 @@ static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; } template static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; } +static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b) +{ return (a + (b - 1)) / b; } + #undef ARRAY_LENGTH template diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-set-private.hh index adfa88f18e..705f554ce6 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-set-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-set-private.hh @@ -28,7 +28,6 @@ #define HB_SET_PRIVATE_HH #include "hb-private.hh" -#include "hb-set.h" #include "hb-object-private.hh" @@ -171,7 +170,7 @@ struct hb_set_t inline void add (hb_codepoint_t g) { if (unlikely (in_error)) return; - if (unlikely (g == SENTINEL)) return; + if (unlikely (g == INVALID)) return; if (unlikely (g > MAX_G)) return; elt (g) |= mask (g); } @@ -256,19 +255,22 @@ struct hb_set_t } inline bool next (hb_codepoint_t *codepoint) const { - if (unlikely (*codepoint == SENTINEL)) { + if (unlikely (*codepoint == INVALID)) { hb_codepoint_t i = get_min (); - if (i != SENTINEL) { + if (i != INVALID) { *codepoint = i; return true; - } else + } else { + *codepoint = INVALID; return false; + } } for (hb_codepoint_t i = *codepoint + 1; i < MAX_G + 1; i++) if (has (i)) { *codepoint = i; return true; } + *codepoint = INVALID; return false; } inline bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const @@ -277,7 +279,10 @@ struct hb_set_t i = *last; if (!next (&i)) + { + *last = *first = INVALID; return false; + } *last = *first = i; while (next (&i) && i == *last + 1) @@ -300,7 +305,7 @@ struct hb_set_t for (unsigned int j = 0; j < BITS; j++) if (elts[i] & (1 << j)) return i * BITS + j; - return SENTINEL; + return INVALID; } inline hb_codepoint_t get_max (void) const { @@ -309,7 +314,7 @@ struct hb_set_t for (unsigned int j = BITS; j; j--) if (elts[i - 1] & (1 << (j - 1))) return (i - 1) * BITS + (j - 1); - return SENTINEL; + return INVALID; } typedef uint32_t elt_t; @@ -318,7 +323,7 @@ struct hb_set_t static const unsigned int BITS = (1 << SHIFT); static const unsigned int MASK = BITS - 1; static const unsigned int ELTS = (MAX_G + 1 + (BITS - 1)) / BITS; - static const hb_codepoint_t SENTINEL = (hb_codepoint_t) -1; + static const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID; elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; } elt_t elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.cc b/src/3rdparty/harfbuzz-ng/src/hb-set.cc index 3c9573fbce..59a0af46ed 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-set.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-set.cc @@ -30,6 +30,13 @@ /* Public API */ +/** + * hb_set_create: (Xconstructor) + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_set_t * hb_set_create (void) { @@ -43,6 +50,13 @@ hb_set_create (void) return set; } +/** + * hb_set_get_empty: + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_set_t * hb_set_get_empty (void) { @@ -56,12 +70,26 @@ hb_set_get_empty (void) return const_cast (&_hb_set_nil); } +/** + * hb_set_reference: (skip) + * @set: a set. + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_set_t * hb_set_reference (hb_set_t *set) { return hb_object_reference (set); } +/** + * hb_set_destroy: (skip) + * @set: a set. + * + * Since: 1.0 + **/ void hb_set_destroy (hb_set_t *set) { @@ -72,6 +100,18 @@ hb_set_destroy (hb_set_t *set) free (set); } +/** + * hb_set_set_user_data: (skip) + * @set: a set. + * @key: + * @data: + * @destroy (closure data): + * @replace: + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_set_set_user_data (hb_set_t *set, hb_user_data_key_t *key, @@ -82,6 +122,15 @@ hb_set_set_user_data (hb_set_t *set, return hb_object_set_user_data (set, key, data, destroy, replace); } +/** + * hb_set_get_user_data: (skip) + * @set: a set. + * @key: + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ void * hb_set_get_user_data (hb_set_t *set, hb_user_data_key_t *key) @@ -90,24 +139,63 @@ hb_set_get_user_data (hb_set_t *set, } +/** + * hb_set_allocation_successful: + * @set: a set. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_set_allocation_successful (const hb_set_t *set HB_UNUSED) { return !set->in_error; } +/** + * hb_set_clear: + * @set: a set. + * + * + * + * Since: 1.0 + **/ void hb_set_clear (hb_set_t *set) { set->clear (); } +/** + * hb_set_is_empty: + * @set: a set. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_set_is_empty (const hb_set_t *set) { return set->is_empty (); } +/** + * hb_set_has: + * @set: a set. + * @codepoint: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_set_has (const hb_set_t *set, hb_codepoint_t codepoint) @@ -115,6 +203,15 @@ hb_set_has (const hb_set_t *set, return set->has (codepoint); } +/** + * hb_set_add: + * @set: a set. + * @codepoint: + * + * + * + * Since: 1.0 + **/ void hb_set_add (hb_set_t *set, hb_codepoint_t codepoint) @@ -122,6 +219,16 @@ hb_set_add (hb_set_t *set, set->add (codepoint); } +/** + * hb_set_add_range: + * @set: a set. + * @first: + * @last: + * + * + * + * Since: 1.0 + **/ void hb_set_add_range (hb_set_t *set, hb_codepoint_t first, @@ -130,6 +237,15 @@ hb_set_add_range (hb_set_t *set, set->add_range (first, last); } +/** + * hb_set_del: + * @set: a set. + * @codepoint: + * + * + * + * Since: 1.0 + **/ void hb_set_del (hb_set_t *set, hb_codepoint_t codepoint) @@ -137,6 +253,16 @@ hb_set_del (hb_set_t *set, set->del (codepoint); } +/** + * hb_set_del_range: + * @set: a set. + * @first: + * @last: + * + * + * + * Since: 1.0 + **/ void hb_set_del_range (hb_set_t *set, hb_codepoint_t first, @@ -145,6 +271,17 @@ hb_set_del_range (hb_set_t *set, set->del_range (first, last); } +/** + * hb_set_is_equal: + * @set: a set. + * @other: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_set_is_equal (const hb_set_t *set, const hb_set_t *other) @@ -152,6 +289,15 @@ hb_set_is_equal (const hb_set_t *set, return set->is_equal (other); } +/** + * hb_set_set: + * @set: a set. + * @other: + * + * + * + * Since: 1.0 + **/ void hb_set_set (hb_set_t *set, const hb_set_t *other) @@ -159,6 +305,15 @@ hb_set_set (hb_set_t *set, set->set (other); } +/** + * hb_set_union: + * @set: a set. + * @other: + * + * + * + * Since: 1.0 + **/ void hb_set_union (hb_set_t *set, const hb_set_t *other) @@ -166,6 +321,15 @@ hb_set_union (hb_set_t *set, set->union_ (other); } +/** + * hb_set_intersect: + * @set: a set. + * @other: + * + * + * + * Since: 1.0 + **/ void hb_set_intersect (hb_set_t *set, const hb_set_t *other) @@ -173,6 +337,15 @@ hb_set_intersect (hb_set_t *set, set->intersect (other); } +/** + * hb_set_subtract: + * @set: a set. + * @other: + * + * + * + * Since: 1.0 + **/ void hb_set_subtract (hb_set_t *set, const hb_set_t *other) @@ -180,6 +353,15 @@ hb_set_subtract (hb_set_t *set, set->subtract (other); } +/** + * hb_set_symmetric_difference: + * @set: a set. + * @other: + * + * + * + * Since: 1.0 + **/ void hb_set_symmetric_difference (hb_set_t *set, const hb_set_t *other) @@ -187,30 +369,79 @@ hb_set_symmetric_difference (hb_set_t *set, set->symmetric_difference (other); } +/** + * hb_set_invert: + * @set: a set. + * + * + * + * Since: 1.0 + **/ void hb_set_invert (hb_set_t *set) { set->invert (); } +/** + * hb_set_get_population: + * @set: a set. + * + * Returns the number of numbers in the set. + * + * Return value: set population. + * + * Since: 1.0 + **/ unsigned int hb_set_get_population (const hb_set_t *set) { return set->get_population (); } +/** + * hb_set_get_min: + * @set: a set. + * + * Finds the minimum number in the set. + * + * Return value: minimum of the set, or %HB_SET_VALUE_INVALID if set is empty. + * + * Since: 1.0 + **/ hb_codepoint_t hb_set_get_min (const hb_set_t *set) { return set->get_min (); } +/** + * hb_set_get_max: + * @set: a set. + * + * Finds the maximum number in the set. + * + * Return value: minimum of the set, or %HB_SET_VALUE_INVALID if set is empty. + * + * Since: 1.0 + **/ hb_codepoint_t hb_set_get_max (const hb_set_t *set) { return set->get_max (); } +/** + * hb_set_next: + * @set: a set. + * @codepoint: (inout): + * + * + * + * Return value: whether there was a next value. + * + * Since: 1.0 + **/ hb_bool_t hb_set_next (const hb_set_t *set, hb_codepoint_t *codepoint) @@ -218,6 +449,19 @@ hb_set_next (const hb_set_t *set, return set->next (codepoint); } +/** + * hb_set_next_range: + * @set: a set. + * @first: (out): output first codepoint in the range. + * @last: (inout): input current last and output last codepoint in the range. + * + * Gets the next consecutive range of numbers in @set that + * are greater than current value of @last. + * + * Return value: whether there was a next range. + * + * Since: 1.0 + **/ hb_bool_t hb_set_next_range (const hb_set_t *set, hb_codepoint_t *first, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.h b/src/3rdparty/harfbuzz-ng/src/hb-set.h index 291e24974e..bafdae9633 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-set.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-set.h @@ -36,6 +36,8 @@ HB_BEGIN_DECLS +#define HB_SET_VALUE_INVALID ((hb_codepoint_t) -1) + typedef struct hb_set_t hb_set_t; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan-private.hh index dd014e38d0..607da5e779 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan-private.hh @@ -28,7 +28,6 @@ #define HB_SHAPE_PLAN_PRIVATE_HH #include "hb-private.hh" -#include "hb-shape-plan.h" #include "hb-object-private.hh" #include "hb-shaper-private.hh" @@ -39,12 +38,15 @@ struct hb_shape_plan_t ASSERT_POD (); hb_bool_t default_shaper_list; - hb_face_t *face; + hb_face_t *face_unsafe; /* We don't carry a reference to face. */ hb_segment_properties_t props; hb_shape_func_t *shaper_func; const char *shaper_name; + hb_feature_t *user_features; + unsigned int num_user_features; + struct hb_shaper_data_t shaper_data; }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc index a6d2d26210..e354f29176 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc @@ -46,7 +46,7 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan, #define HB_SHAPER_PLAN(shaper) \ HB_STMT_START { \ - if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face)) { \ + if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) { \ HB_SHAPER_DATA (shaper, shape_plan) = \ HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, user_features, num_user_features); \ shape_plan->shaper_func = _hb_##shaper##_shape; \ @@ -83,6 +83,20 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan, * hb_shape_plan_t */ +/** + * hb_shape_plan_create: (Xconstructor) + * @face: + * @props: + * @user_features: (array length=num_user_features): + * @num_user_features: + * @shaper_list: (array zero-terminated=1): + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_shape_plan_t * hb_shape_plan_create (hb_face_t *face, const hb_segment_properties_t *props, @@ -93,24 +107,42 @@ hb_shape_plan_create (hb_face_t *face, assert (props->direction != HB_DIRECTION_INVALID); hb_shape_plan_t *shape_plan; + hb_feature_t *features = NULL; if (unlikely (!face)) face = hb_face_get_empty (); if (unlikely (!props || hb_object_is_inert (face))) return hb_shape_plan_get_empty (); - if (!(shape_plan = hb_object_create ())) + if (num_user_features && !(features = (hb_feature_t *) malloc (num_user_features * sizeof (hb_feature_t)))) return hb_shape_plan_get_empty (); + if (!(shape_plan = hb_object_create ())) { + free (features); + return hb_shape_plan_get_empty (); + } hb_face_make_immutable (face); shape_plan->default_shaper_list = shaper_list == NULL; - shape_plan->face = hb_face_reference (face); + shape_plan->face_unsafe = face; shape_plan->props = *props; + shape_plan->num_user_features = num_user_features; + shape_plan->user_features = features; + if (num_user_features) + memcpy (features, user_features, num_user_features * sizeof (hb_feature_t)); hb_shape_plan_plan (shape_plan, user_features, num_user_features, shaper_list); return shape_plan; } +/** + * hb_shape_plan_get_empty: + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_shape_plan_t * hb_shape_plan_get_empty (void) { @@ -124,6 +156,9 @@ hb_shape_plan_get_empty (void) NULL, /* shaper_func */ NULL, /* shaper_name */ + NULL, /* user_features */ + 0, /* num_user_featurs */ + { #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, #include "hb-shaper-list.hh" @@ -134,12 +169,30 @@ hb_shape_plan_get_empty (void) return const_cast (&_hb_shape_plan_nil); } +/** + * hb_shape_plan_reference: (skip) + * @shape_plan: a shape plan. + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_shape_plan_t * hb_shape_plan_reference (hb_shape_plan_t *shape_plan) { return hb_object_reference (shape_plan); } +/** + * hb_shape_plan_destroy: (skip) + * @shape_plan: a shape plan. + * + * + * + * Since: 1.0 + **/ void hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) { @@ -149,11 +202,25 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT - hb_face_destroy (shape_plan->face); + free (shape_plan->user_features); free (shape_plan); } +/** + * hb_shape_plan_set_user_data: (skip) + * @shape_plan: a shape plan. + * @key: + * @data: + * @destroy: + * @replace: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan, hb_user_data_key_t *key, @@ -164,6 +231,17 @@ hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan, return hb_object_set_user_data (shape_plan, key, data, destroy, replace); } +/** + * hb_shape_plan_get_user_data: (skip) + * @shape_plan: a shape plan. + * @key: + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ void * hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan, hb_user_data_key_t *key) @@ -172,6 +250,20 @@ hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan, } +/** + * hb_shape_plan_execute: + * @shape_plan: a shape plan. + * @font: a font. + * @buffer: a buffer. + * @features: (array length=num_features): + * @num_features: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_shape_plan_execute (hb_shape_plan_t *shape_plan, hb_font_t *font, @@ -184,7 +276,7 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan, hb_object_is_inert (buffer))) return false; - assert (shape_plan->face == font->face); + assert (shape_plan->face_unsafe == font->face); assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props)); #define HB_SHAPER_EXECUTE(shaper) \ @@ -221,23 +313,69 @@ hb_shape_plan_hash (const hb_shape_plan_t *shape_plan) } #endif -/* TODO no user-feature caching for now. */ +/* User-feature caching is currently somewhat dumb: + * it only finds matches where the feature array is identical, + * not cases where the feature lists would be compatible for plan purposes + * but have different ranges, for example. + */ struct hb_shape_plan_proposal_t { const hb_segment_properties_t props; const char * const *shaper_list; + const hb_feature_t *user_features; + unsigned int num_user_features; hb_shape_func_t *shaper_func; }; +static inline hb_bool_t +hb_shape_plan_user_features_match (const hb_shape_plan_t *shape_plan, + const hb_shape_plan_proposal_t *proposal) +{ + if (proposal->num_user_features != shape_plan->num_user_features) return false; + for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++) + if (proposal->user_features[i].tag != shape_plan->user_features[i].tag || + proposal->user_features[i].value != shape_plan->user_features[i].value || + proposal->user_features[i].start != shape_plan->user_features[i].start || + proposal->user_features[i].end != shape_plan->user_features[i].end) return false; + return true; +} + static hb_bool_t hb_shape_plan_matches (const hb_shape_plan_t *shape_plan, const hb_shape_plan_proposal_t *proposal) { return hb_segment_properties_equal (&shape_plan->props, &proposal->props) && + hb_shape_plan_user_features_match (shape_plan, proposal) && ((shape_plan->default_shaper_list && proposal->shaper_list == NULL) || (shape_plan->shaper_func == proposal->shaper_func)); } +static inline hb_bool_t +hb_non_global_user_features_present (const hb_feature_t *user_features, + unsigned int num_user_features) +{ + while (num_user_features) + if (user_features->start != 0 || user_features->end != (unsigned int) -1) + return true; + else + num_user_features--, user_features++; + return false; +} + +/** + * hb_shape_plan_create_cached: + * @face: + * @props: + * @user_features: (array length=num_user_features): + * @num_user_features: + * @shaper_list: (array zero-terminated=1): + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_shape_plan_t * hb_shape_plan_create_cached (hb_face_t *face, const hb_segment_properties_t *props, @@ -245,12 +383,11 @@ hb_shape_plan_create_cached (hb_face_t *face, unsigned int num_user_features, const char * const *shaper_list) { - if (num_user_features) - return hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list); - hb_shape_plan_proposal_t proposal = { *props, shaper_list, + user_features, + num_user_features, NULL }; @@ -288,6 +425,11 @@ retry: hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list); + /* Don't add the plan to the cache if there were user features with non-global ranges */ + + if (hb_non_global_user_features_present (user_features, num_user_features)) + return shape_plan; + hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t)); if (unlikely (!node)) return shape_plan; @@ -301,12 +443,19 @@ retry: goto retry; } - /* Release our reference on face. */ - hb_face_destroy (face); - return hb_shape_plan_reference (shape_plan); } +/** + * hb_shape_plan_get_shaper: + * @shape_plan: a shape plan. + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ const char * hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan) { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-shape.cc index 80d8c1306b..c1b752405e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-shape.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-shape.cc @@ -153,6 +153,18 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature) *pp == end; } +/** + * hb_feature_from_string: + * @str: (array length=len): + * @len: + * @feature: (out): + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_feature_from_string (const char *str, int len, hb_feature_t *feature) @@ -163,6 +175,16 @@ hb_feature_from_string (const char *str, int len, return parse_one_feature (&str, str + len, feature); } +/** + * hb_feature_to_string: + * @feature: + * @buf: (array length=size): + * @size: + * + * + * + * Since: 1.0 + **/ void hb_feature_to_string (hb_feature_t *feature, char *buf, unsigned int size) @@ -209,6 +231,15 @@ void free_static_shaper_list (void) free (static_shaper_list); } +/** + * hb_shape_list_shapers: + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ const char ** hb_shape_list_shapers (void) { @@ -244,6 +275,20 @@ retry: } +/** + * hb_shape_full: + * @font: a font. + * @buffer: a buffer. + * @features: (array length=num_features): + * @num_features: + * @shaper_list: (array zero-terminated=1): + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_shape_full (hb_font_t *font, hb_buffer_t *buffer, @@ -265,6 +310,17 @@ hb_shape_full (hb_font_t *font, return res; } +/** + * hb_shape: + * @font: a font. + * @buffer: a buffer. + * @features: (array length=num_features): + * @num_features: + * + * + * + * Since: 1.0 + **/ void hb_shape (hb_font_t *font, hb_buffer_t *buffer, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh index dd4d00138e..779d8ae229 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh @@ -32,8 +32,6 @@ #define HB_UNICODE_PRIVATE_HH #include "hb-private.hh" - -#include "hb-unicode.h" #include "hb-object-private.hh" diff --git a/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc b/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc index b7e098737c..5b44913bd3 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc @@ -150,6 +150,16 @@ hb_unicode_funcs_get_default (void) #pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS.") #endif +/** + * hb_unicode_funcs_create: (Xconstructor) + * @parent: (allow-none): + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_unicode_funcs_t * hb_unicode_funcs_create (hb_unicode_funcs_t *parent) { @@ -187,18 +197,45 @@ const hb_unicode_funcs_t _hb_unicode_funcs_nil = { } }; +/** + * hb_unicode_funcs_get_empty: + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_unicode_funcs_t * hb_unicode_funcs_get_empty (void) { return const_cast (&_hb_unicode_funcs_nil); } +/** + * hb_unicode_funcs_reference: (skip) + * @ufuncs: Unicode functions. + * + * + * + * Return value: (transfer full): + * + * Since: 1.0 + **/ hb_unicode_funcs_t * hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs) { return hb_object_reference (ufuncs); } +/** + * hb_unicode_funcs_destroy: (skip) + * @ufuncs: Unicode functions. + * + * + * + * Since: 1.0 + **/ void hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs) { @@ -214,6 +251,20 @@ hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs) free (ufuncs); } +/** + * hb_unicode_funcs_set_user_data: (skip) + * @ufuncs: Unicode functions. + * @key: + * @data: + * @destroy: + * @replace: + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, hb_user_data_key_t *key, @@ -224,6 +275,17 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, return hb_object_set_user_data (ufuncs, key, data, destroy, replace); } +/** + * hb_unicode_funcs_get_user_data: (skip) + * @ufuncs: Unicode functions. + * @key: + * + * + * + * Return value: (transfer none): + * + * Since: 1.0 + **/ void * hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs, hb_user_data_key_t *key) @@ -232,6 +294,14 @@ hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs, } +/** + * hb_unicode_funcs_make_immutable: + * @ufuncs: Unicode functions. + * + * + * + * Since: 1.0 + **/ void hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs) { @@ -241,12 +311,32 @@ hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs) ufuncs->immutable = true; } +/** + * hb_unicode_funcs_is_immutable: + * @ufuncs: Unicode functions. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs) { return ufuncs->immutable; } +/** + * hb_unicode_funcs_get_parent: + * @ufuncs: Unicode functions. + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_unicode_funcs_t * hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs) { @@ -294,6 +384,19 @@ hb_unicode_##name (hb_unicode_funcs_t *ufuncs, \ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE #undef HB_UNICODE_FUNC_IMPLEMENT +/** + * hb_unicode_compose: + * @ufuncs: Unicode functions. + * @a: + * @b: + * @ab: (out): + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_unicode_compose (hb_unicode_funcs_t *ufuncs, hb_codepoint_t a, @@ -303,6 +406,19 @@ hb_unicode_compose (hb_unicode_funcs_t *ufuncs, return ufuncs->compose (a, b, ab); } +/** + * hb_unicode_decompose: + * @ufuncs: Unicode functions. + * @ab: + * @a: (out): + * @b: (out): + * + * + * + * Return value: + * + * Since: 1.0 + **/ hb_bool_t hb_unicode_decompose (hb_unicode_funcs_t *ufuncs, hb_codepoint_t ab, @@ -312,6 +428,18 @@ hb_unicode_decompose (hb_unicode_funcs_t *ufuncs, return ufuncs->decompose (ab, a, b); } +/** + * hb_unicode_decompose_compatibility: + * @ufuncs: Unicode functions. + * @u: + * @decomposed: (out): + * + * + * + * Return value: + * + * Since: 1.0 + **/ unsigned int hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, hb_codepoint_t u, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-unicode.h b/src/3rdparty/harfbuzz-ng/src/hb-unicode.h index 2e10d98a3b..1c4e097b92 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-unicode.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-unicode.h @@ -248,7 +248,7 @@ typedef hb_bool_t (*hb_unicode_decompose_func_t) (hb_unicode_funcs_t *ufuncs, /** * hb_unicode_decompose_compatibility_func_t: - * @ufuncs: Unicode function structure + * @ufuncs: a Unicode function structure * @u: codepoint to decompose * @decomposed: address of codepoint array (of length %HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into * @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func() @@ -274,44 +274,132 @@ typedef unsigned int (*hb_unicode_decompose_compatibility_func_t) (hb_unicode_ /* setters */ +/** + * hb_unicode_funcs_set_combining_class_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs, - hb_unicode_combining_class_func_t combining_class_func, + hb_unicode_combining_class_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_unicode_funcs_set_eastasian_width_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs, - hb_unicode_eastasian_width_func_t eastasian_width_func, + hb_unicode_eastasian_width_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_unicode_funcs_set_general_category_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs, - hb_unicode_general_category_func_t general_category_func, + hb_unicode_general_category_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_unicode_funcs_set_mirroring_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs, - hb_unicode_mirroring_func_t mirroring_func, + hb_unicode_mirroring_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_unicode_funcs_set_script_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs, - hb_unicode_script_func_t script_func, + hb_unicode_script_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_unicode_funcs_set_compose_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs, - hb_unicode_compose_func_t compose_func, + hb_unicode_compose_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_unicode_funcs_set_decompose_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs, - hb_unicode_decompose_func_t decompose_func, + hb_unicode_decompose_func_t func, void *user_data, hb_destroy_func_t destroy); +/** + * hb_unicode_funcs_set_decompose_compatibility_func: + * @ufuncs: a Unicode function structure + * @func: (closure user_data) (destroy destroy) (scope notified): + * @user_data: + * @destroy: + * + * + * + * Since: 1.0 + **/ void hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs, - hb_unicode_decompose_compatibility_func_t decompose_compatibility_func, + hb_unicode_decompose_compatibility_func_t func, void *user_data, hb_destroy_func_t destroy); /* accessors */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-version.h b/src/3rdparty/harfbuzz-ng/src/hb-version.h index dc07ef794a..790e0ecbae 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-version.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-version.h @@ -38,9 +38,9 @@ HB_BEGIN_DECLS #define HB_VERSION_MAJOR 0 #define HB_VERSION_MINOR 9 -#define HB_VERSION_MICRO 20 +#define HB_VERSION_MICRO 25 -#define HB_VERSION_STRING "0.9.20" +#define HB_VERSION_STRING "0.9.25" #define HB_VERSION_CHECK(major,minor,micro) \ ((major)*10000+(minor)*100+(micro) >= \ -- cgit v1.2.3