diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh index d22e8809e..265651b7f 100644 --- a/src/hb-dsalgs.hh +++ b/src/hb-dsalgs.hh @@ -312,6 +312,27 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) * Sort and search. */ +static inline void * +hb_bsearch (const void *key, const void *base, + size_t nmemb, size_t size, + int (*compar)(const void *_key, const void *_item)) +{ + int min = 0, max = (int) nmemb - 1; + while (min <= max) + { + int mid = (min + max) / 2; + const void *p = (const void *) (((const char *) base) + (mid * size)); + int c = compar (key, p); + if (c < 0) + max = mid - 1; + else if (c > 0) + min = mid + 1; + else + return (void *) p; + } + return nullptr; +} + static inline void * hb_bsearch_r (const void *key, const void *base, size_t nmemb, size_t size, diff --git a/src/hb-ot-name-table.hh b/src/hb-ot-name-table.hh index 8967fcbd8..f2eb49681 100644 --- a/src/hb-ot-name-table.hh +++ b/src/hb-ot-name-table.hh @@ -107,20 +107,31 @@ struct NameRecord }; static int -_hb_ot_name_entry_cmp (const void *pa, const void *pb) +_hb_ot_name_entry_cmp_key (const void *pa, const void *pb) { const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa; const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb; - /* Sort by name_id, then language, then score, then index. */ + /* Compare by name_id, then language. */ if (a->name_id != b->name_id) return a->name_id < b->name_id ? -1 : +1; - int e = strcmp (hb_language_to_string (a->language), - hb_language_to_string (b->language)); - if (e) - return e; + return strcmp (hb_language_to_string (a->language), + hb_language_to_string (b->language)); +} + +static int +_hb_ot_name_entry_cmp (const void *pa, const void *pb) +{ + /* Compare by name_id, then language, then score, then index. */ + + int v = _hb_ot_name_entry_cmp_key (pa, pb); + if (v) + return v; + + const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa; + const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb; if (a->entry_score != b->entry_score) return a->entry_score < b->entry_score ? -1 : +1; @@ -199,13 +210,25 @@ struct name this->names.resize (j); } - inline void fini (void) { this->names.fini (); hb_blob_destroy (this->blob); } + inline int get_index (hb_name_id_t name_id, + hb_language_t language) const + { + const hb_ot_name_entry_t key = {name_id, {0}, language}; + const hb_ot_name_entry_t *entry = (const hb_ot_name_entry_t *) + hb_bsearch (&key, + this->names.arrayZ(), + this->names.len, + sizeof (key), + _hb_ot_name_entry_cmp_key); + return entry ? entry->entry_index : -1; + } + private: hb_blob_t *blob; public: diff --git a/src/hb-ot-name.cc b/src/hb-ot-name.cc index fe1276c32..626e0637a 100644 --- a/src/hb-ot-name.cc +++ b/src/hb-ot-name.cc @@ -105,11 +105,15 @@ hb_ot_name_get_utf (hb_face_t *face, typename utf_t::codepoint_t *text /* OUT */) { const OT::name_accelerator_t &name = _get_name (face); - unsigned int idx = 0; // XXX bsearch and find - hb_bytes_t bytes = name.table->get_name (idx); - if (true /*UTF16-BE*/) - return hb_ot_name_convert_utf (&bytes, text_size, text); + int idx = name.get_index (name_id, language); + if (idx != -1) + { + hb_bytes_t bytes = name.table->get_name (idx); + + if (true /*UTF16-BE*/) + return hb_ot_name_convert_utf (&bytes, text_size, text); + } if (text_size) { diff --git a/src/hb-ot-os2-unicode-ranges.hh b/src/hb-ot-os2-unicode-ranges.hh index 19780088a..b0ccd00d7 100644 --- a/src/hb-ot-os2-unicode-ranges.hh +++ b/src/hb-ot-os2-unicode-ranges.hh @@ -34,7 +34,7 @@ namespace OT { struct OS2Range { static int - cmp (const void *_key, const void *_item, void *_arg) + cmp (const void *_key, const void *_item) { hb_codepoint_t cp = *((hb_codepoint_t *) _key); const OS2Range *range = (OS2Range *) _item; @@ -233,10 +233,10 @@ static const OS2Range _hb_os2_unicode_ranges[] = static unsigned int _hb_ot_os2_get_unicode_range_bit (hb_codepoint_t cp) { - OS2Range *range = (OS2Range*) hb_bsearch_r (&cp, _hb_os2_unicode_ranges, - ARRAY_LENGTH (_hb_os2_unicode_ranges), - sizeof (OS2Range), - OS2Range::cmp, nullptr); + OS2Range *range = (OS2Range*) hb_bsearch (&cp, _hb_os2_unicode_ranges, + ARRAY_LENGTH (_hb_os2_unicode_ranges), + sizeof (OS2Range), + OS2Range::cmp); if (range != nullptr) return range->bit; return -1; diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index 596e76d05..a08f88829 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -576,8 +576,8 @@ _hb_modified_combining_class[256] = bool _hb_unicode_is_emoji_Extended_Pictographic (hb_codepoint_t cp) { - return hb_bsearch_r (&cp, _hb_unicode_emoji_Extended_Pictographic_table, - ARRAY_LENGTH (_hb_unicode_emoji_Extended_Pictographic_table), - sizeof (hb_unicode_range_t), - hb_unicode_range_t::cmp, nullptr); + return hb_bsearch (&cp, _hb_unicode_emoji_Extended_Pictographic_table, + ARRAY_LENGTH (_hb_unicode_emoji_Extended_Pictographic_table), + sizeof (hb_unicode_range_t), + hb_unicode_range_t::cmp); } diff --git a/src/hb-unicode.hh b/src/hb-unicode.hh index 6d6a4fa0c..4326798df 100644 --- a/src/hb-unicode.hh +++ b/src/hb-unicode.hh @@ -369,7 +369,7 @@ DECLARE_NULL_INSTANCE (hb_unicode_funcs_t); struct hb_unicode_range_t { static int - cmp (const void *_key, const void *_item, void *_arg) + cmp (const void *_key, const void *_item) { hb_codepoint_t cp = *((hb_codepoint_t *) _key); const hb_unicode_range_t *range = (hb_unicode_range_t *) _item;