summaryrefslogtreecommitdiff
path: root/Build
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2022-05-21 02:44:01 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2022-05-21 02:44:01 +0000
commit523ea68050bb0a979133708d95cb9ebf43302839 (patch)
tree381c8ccc5f5c102ea6e3dd72f0d30bc19cc1fa51 /Build
parenta6ef6aa084c7849d385575f057cfc19bc732c625 (diff)
harfbuzz 4.3.0
git-svn-id: svn://tug.org/texlive/trunk@63353 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build')
-rw-r--r--Build/source/libs/README4
-rw-r--r--Build/source/libs/harfbuzz/ChangeLog5
-rw-r--r--Build/source/libs/harfbuzz/TLpatches/ChangeLog5
-rw-r--r--Build/source/libs/harfbuzz/TLpatches/TL-Changes4
-rwxr-xr-xBuild/source/libs/harfbuzz/configure26
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/BUILD.md2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog2551
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/Makefile.am15
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/NEWS17
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/configure.ac3
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/meson.build2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py115
-rwxr-xr-xBuild/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py3
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh28
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh26
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh6
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh9
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh9
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh64
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh118
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh17
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff1-interp-cs.hh8
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh89
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.cc20
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.h4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh41
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh13
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh11
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh182
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc45
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh165
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc38
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh30
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh147
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh60
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh266
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh4
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use-table.hh2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag-table.hh3559
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc107
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh16
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-priority-queue.hh32
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh82
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh17
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh26
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh100
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc22
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc28
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc114
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh2
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc87
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh97
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc96
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc8
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc84
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc21
-rw-r--r--Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc25
-rw-r--r--Build/source/libs/harfbuzz/version.ac2
62 files changed, 5847 insertions, 2844 deletions
diff --git a/Build/source/libs/README b/Build/source/libs/README
index 860e33a0698..4998637f3b5 100644
--- a/Build/source/libs/README
+++ b/Build/source/libs/README
@@ -12,7 +12,7 @@ See also comments in ../texk/README.
cairo 1.16.0 - checked 20oct18
http://cairographics.org/releases/
-freetype2 2.11.1 - checked 03dec21
+freetype2 2.12.1 - checked 07may22
http://download.savannah.gnu.org/releases/freetype/
gd 2.3.3 - checked 13sep21
@@ -25,7 +25,7 @@ graphite2 1.3.14 - checked 10apr20
http://sourceforge.net/projects/silgraphite/files/graphite2/
(requires C++11)
-harfbuzz 4.2.1 - checked 25apr22
+harfbuzz 4.3.0 - checked 21may22
https://github.com/harfbuzz/harfbuzz/releases/download/4.2.1/
icu 70.1 - checked 16jan22
diff --git a/Build/source/libs/harfbuzz/ChangeLog b/Build/source/libs/harfbuzz/ChangeLog
index 296b421ac35..be5f24132f5 100644
--- a/Build/source/libs/harfbuzz/ChangeLog
+++ b/Build/source/libs/harfbuzz/ChangeLog
@@ -1,3 +1,8 @@
+2022-05-21 Akira Kakuto <kakuto@jcom.zaq.ne.jp>
+
+ Import harfbuzz-4.3.0.
+ * version.ac: Adjusted.
+
2022-04-25 Akira Kakuto <kakuto@jcom.zaq.ne.jp>
Import harfbuzz-4.2.1.
diff --git a/Build/source/libs/harfbuzz/TLpatches/ChangeLog b/Build/source/libs/harfbuzz/TLpatches/ChangeLog
index a8d0e0d8e22..f7727e9722c 100644
--- a/Build/source/libs/harfbuzz/TLpatches/ChangeLog
+++ b/Build/source/libs/harfbuzz/TLpatches/ChangeLog
@@ -1,3 +1,8 @@
+2022-05-21 Akira Kakuto <kakuto@jcom.zaq.ne.jp>
+
+ Imported harfbuzz-4.3.0 source tree from:
+ https://github.com/harfbuzz/harfbuzz/releases/download/4.3.0/
+
2022-04-25 Akira Kakuto <kakuto@jcom.zaq.ne.jp>
Imported harfbuzz-4.2.1 source tree from:
diff --git a/Build/source/libs/harfbuzz/TLpatches/TL-Changes b/Build/source/libs/harfbuzz/TLpatches/TL-Changes
index aa3c120185a..b610e645aad 100644
--- a/Build/source/libs/harfbuzz/TLpatches/TL-Changes
+++ b/Build/source/libs/harfbuzz/TLpatches/TL-Changes
@@ -1,5 +1,5 @@
-Changes applied to the harfbuzz-4.2.1/ tree as obtained from:
- https://github.com/harfbuzz/harfbuzz/releases/download/4.2.1/
+Changes applied to the harfbuzz-4.3.0/ tree as obtained from:
+ https://github.com/harfbuzz/harfbuzz/releases/download/4.3.0/
Removed:
COPYING
diff --git a/Build/source/libs/harfbuzz/configure b/Build/source/libs/harfbuzz/configure
index d20e622349a..b4e0650d4c2 100755
--- a/Build/source/libs/harfbuzz/configure
+++ b/Build/source/libs/harfbuzz/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.71 for harfbuzz (TeX Live) 4.2.1.
+# Generated by GNU Autoconf 2.71 for harfbuzz (TeX Live) 4.3.0.
#
# Report bugs to <tex-k@tug.org>.
#
@@ -611,8 +611,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='harfbuzz (TeX Live)'
PACKAGE_TARNAME='harfbuzz--tex-live-'
-PACKAGE_VERSION='4.2.1'
-PACKAGE_STRING='harfbuzz (TeX Live) 4.2.1'
+PACKAGE_VERSION='4.3.0'
+PACKAGE_STRING='harfbuzz (TeX Live) 4.3.0'
PACKAGE_BUGREPORT='tex-k@tug.org'
PACKAGE_URL=''
@@ -1346,7 +1346,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures harfbuzz (TeX Live) 4.2.1 to adapt to many kinds of systems.
+\`configure' configures harfbuzz (TeX Live) 4.3.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1418,7 +1418,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of harfbuzz (TeX Live) 4.2.1:";;
+ short | recursive ) echo "Configuration of harfbuzz (TeX Live) 4.3.0:";;
esac
cat <<\_ACEOF
@@ -1523,7 +1523,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-harfbuzz (TeX Live) configure 4.2.1
+harfbuzz (TeX Live) configure 4.3.0
generated by GNU Autoconf 2.71
Copyright (C) 2021 Free Software Foundation, Inc.
@@ -2064,7 +2064,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by harfbuzz (TeX Live) $as_me 4.2.1, which was
+It was created by harfbuzz (TeX Live) $as_me 4.3.0, which was
generated by GNU Autoconf 2.71. Invocation command line was
$ $0$ac_configure_args_raw
@@ -4823,7 +4823,7 @@ fi
# Define the identity of the package.
PACKAGE='harfbuzz--tex-live-'
- VERSION='4.2.1'
+ VERSION='4.3.0'
# Some tools Automake needs.
@@ -5034,9 +5034,9 @@ WARNING_CFLAGS=$kpse_cv_warning_cflags
HB_VERSION_MAJOR=4
-HB_VERSION_MINOR=2
-HB_VERSION_MICRO=1
-HB_VERSION=4.2.1
+HB_VERSION_MINOR=3
+HB_VERSION_MICRO=0
+HB_VERSION=4.3.0
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
@@ -8817,7 +8817,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by harfbuzz (TeX Live) $as_me 4.2.1, which was
+This file was extended by harfbuzz (TeX Live) $as_me 4.3.0, which was
generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -8885,7 +8885,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
-harfbuzz (TeX Live) config.status 4.2.1
+harfbuzz (TeX Live) config.status 4.3.0
configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/BUILD.md b/Build/source/libs/harfbuzz/harfbuzz-src/BUILD.md
index 47681ec865d..20a52cf4f0c 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/BUILD.md
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/BUILD.md
@@ -5,7 +5,7 @@ Cairo, and GLib. For example, on Ubuntu / Debian, you would do:
whereas on Fedora, RHEL, CentOS, and other Red Hat based systems you would do:
- sudo dnf install meson pkgconfig gtk-doc gcc gcc-c++ freetype-devel glib2-devel cairo-dev
+ sudo dnf install meson pkgconfig gtk-doc gcc gcc-c++ freetype-devel glib2-devel cairo-devel
and on ArchLinux and Manjaro:
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog b/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog
index db86a790269..f17b65012f5 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/ChangeLog
@@ -1,3 +1,2554 @@
+commit aee123fc83388b8f5acfb301d87bd92eccc5b843
+Author: Khaled Hosny <khaled@aliftype.com>
+Date: Fri May 20 21:07:25 2022 +0200
+
+ 4.3.0
+
+ NEWS | 17 +++++++++++++++++
+ configure.ac | 2 +-
+ docs/harfbuzz-docs.xml | 1 +
+ meson.build | 2 +-
+ src/hb-map.cc | 2 +-
+ src/hb-version.h | 6 +++---
+ 6 files changed, 24 insertions(+), 6 deletions(-)
+
+commit 975a5f919467c9bc4cad1340ebf07ae32bf07e14
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 20 12:34:49 2022 -0600
+
+ [array] Use hb_memcmp instead of memcmp
+
+ Fixes ubsan error.
+
+ src/hb-array.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 55804e8d68af0685867d20a1796b952c6ff8db60
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 20 11:40:44 2022 -0600
+
+ [hb-ft] Minor rearrange of struct members
+
+ To make clear what members the lock protects.
+
+ src/hb-ft.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 4e11da054d2c527fa64b33d49b33e3aa6b49077c
+Author: Garret Rieger <grieger@google.com>
+Date: Fri May 20 01:42:34 2022 +0000
+
+ [repacker] update repacker test golden file.
+
+ Changed due to removal of Kahn sorting.
+
+ test/api/fonts/repacker_expected.otf | Bin 1400 -> 1400 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit cbf8f44c9b6de43387c61fdd43cf6bf0b89c3c08
+Author: Garret Rieger <grieger@google.com>
+Date: Thu May 19 21:25:21 2022 +0000
+
+ [subset-perf] swap instead of copying vertice's when reordering during sort.
+
+ src/hb-repacker.hh | 22 ++++++++++++++++------
+ src/hb-serialize.hh | 11 ++++++++++-
+ 2 files changed, 26 insertions(+), 7 deletions(-)
+
+commit b32ca2a292f256a40e445990f104f09c5920d0bd
+Author: Garret Rieger <grieger@google.com>
+Date: Thu May 19 20:45:39 2022 +0000
+
+ [subset-perf] remove sort_kahn from repacker.
+
+ Without an optimized FIFO queue implementation it's nearly as slow as the now optimized sort_shortest_distance.
+
+ src/hb-repacker.hh | 53 ---------------------------------
+ src/test-repacker.cc | 84 ----------------------------------------------------
+ 2 files changed, 137 deletions(-)
+
+commit 4266cf3be266aef27a5d60530860915c68ba03e1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 18:15:46 2022 -0600
+
+ [array] Specialize operator== for bytes_t and ubytes_t
+
+ src/hb-array.hh | 17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+commit 6eaa22e9d71d2b09d4bd211026194d618dcc8aad
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 18:00:58 2022 -0600
+
+ [serialize] Reduce link_t size from 16 to 12
+
+ src/hb-serialize.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 30ba9a39e2249b86310c36564373f4f0347012e1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 17:34:58 2022 -0600
+
+ [vector] Add emplacing push implementation
+
+ src/hb-vector.hh | 24 +++++++++++++++++++++---
+ 1 file changed, 21 insertions(+), 3 deletions(-)
+
+commit 25393288f0d6b98355bc4b72bce15ab6f77a5b0e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 17:19:21 2022 -0600
+
+ [test] Fix compiler warning
+
+ test/api/test-set.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+commit 73b8360dcfb57eaa9acffc7967015a113421eeda
+Author: Garret Rieger <grieger@google.com>
+Date: Thu May 19 22:59:51 2022 +0000
+
+ [subset] fix fuzzer found underflow when heap push fails.
+
+ Fixes https://oss-fuzz.com/testcase-detail/5148625505746944.
+
+ src/hb-priority-queue.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit f1bf14ea89ea082e5edd4e9c90738370bffcab1c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 16:42:35 2022 -0600
+
+ Revert "[set] Cache hash value"
+
+ This reverts commit 44952bcc259a906b8875ed62dc40de96ade8b95c.
+
+ While we investivate https://github.com/harfbuzz/harfbuzz/issues/3599
+
+ src/hb-bit-set.hh | 22 +---------------------
+ 1 file changed, 1 insertion(+), 21 deletions(-)
+
+commit b4d1ec310cd2c8a6e250c71f865c45fe7cadd5fa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 16:06:21 2022 -0600
+
+ [algs] Declare coerce() as constexpr
+
+ src/hb-algs.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 2fdb7616f589ebb9fc060fdb88745e0219a78a14
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 16:00:43 2022 -0600
+
+ [map Further adjust hash function
+
+ src/hb-map.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 01fc90b68c023d380f3cd44e13b21972b3a41dcf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 16:00:06 2022 -0600
+
+ [map] Adjust hash function
+
+ src/hb-map.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit a47b0aebf5f8d56dd78ddd651d40727b729a7577
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 15:52:00 2022 -0600
+
+ [vector] Fix remove() implementation
+
+ test-vector under valgrind happy now.
+
+ src/hb-vector.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 3bd755c32dc7c6ba189783daf89e4cde81715483
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 15:51:18 2022 -0600
+
+ [test-vector] Test remove()
+
+ Currently buggy. Valgrind confirms.
+
+ src/test-vector.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 58f848daa8f596007a8dadee3fcb462548def980
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 15:42:54 2022 -0600
+
+ [set/map] Adjust hash function return type
+
+ src/hb-bit-page.hh | 8 ++++----
+ src/hb-bit-set-invertible.hh | 2 +-
+ src/hb-bit-set.hh | 6 +++---
+ src/hb-map.hh | 4 ++--
+ src/hb-set.hh | 2 +-
+ 5 files changed, 11 insertions(+), 11 deletions(-)
+
+commit 6544fc284f55ec1d3199bc610eeac39af935df9c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 15:28:09 2022 -0600
+
+ [vector] Add further copy implementation
+
+ src/hb-vector.hh | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+commit c19f1169521c6fa95c690285a3d24123f387a98e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 15:27:52 2022 -0600
+
+ [meta] Remove non-existing gcc4 trait implementation
+
+ src/hb-meta.hh | 2 --
+ src/hb-vector.hh | 2 +-
+ 2 files changed, 1 insertion(+), 3 deletions(-)
+
+commit 679b900e9b27fdecb9a694c58f71e7bc9e2cd125
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 15:27:32 2022 -0600
+
+ [meta] Fix gcc4 trait implementation
+
+ src/hb-meta.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit fb77f48ffd3fe7fcd17843b9cdc6ca677d36602c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 15:02:10 2022 -0600
+
+ [vector] Optimize vector copy
+
+ src/hb-meta.hh | 4 ++++
+ src/hb-vector.hh | 30 ++++++++++++++++++++++++++++--
+ 2 files changed, 32 insertions(+), 2 deletions(-)
+
+commit 28b44ac46a24f6987d2c2565e0ac72d5b2763d81
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 15:01:56 2022 -0600
+
+ [set] Switch set copy to vector operator =
+
+ Slows it down currently.
+
+ src/hb-bit-set.hh | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+commit 37d3275dec01edfafe2cc744ed85a3febb964594
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 15:01:23 2022 -0600
+
+ [test-vector] Enable disabled test
+
+ This seems to work already.
+
+ src/test-vector.cc | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 544ffb913ea515fae77f26714a1c7c620cdab0ed
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 14:50:12 2022 -0600
+
+ [set] Adjust grow_vector condition
+
+ src/hb-vector.hh | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+commit 0623aa598ba6a7cc14d00091935bc8811b3c6aac
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 14:12:42 2022 -0600
+
+ [benchmark-set] Add benchmark for set copy
+
+ perf/benchmark-set.cc | 23 +++++++++++++++++++++++
+ src/hb-set.hh | 8 ++++----
+ 2 files changed, 27 insertions(+), 4 deletions(-)
+
+commit 44952bcc259a906b8875ed62dc40de96ade8b95c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 14:02:48 2022 -0600
+
+ [set] Cache hash value
+
+ src/hb-bit-set.hh | 26 +++++++++++++++++++++++---
+ 1 file changed, 23 insertions(+), 3 deletions(-)
+
+commit 844ac328e46f9bfcc5481f2dd525603c9a448ffe
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 13:54:31 2022 -0600
+
+ [set] Fix hb_set_t hash stability
+
+ src/hb-bit-page.hh | 2 +-
+ src/hb-bit-set.hh | 6 ++++--
+ 2 files changed, 5 insertions(+), 3 deletions(-)
+
+commit 2d0b1248b23c9eb931c013a35daec62c48ee293f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 13:53:53 2022 -0600
+
+ [test-map] Test hb_set_t hash stability
+
+ Fails currently.
+
+ src/test-map.cc | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit 561e02fefb72be902482fc49dcec66b4c585b798
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 13:38:52 2022 -0600
+
+ [map] Make hb_map_t hashable
+
+ src/hb-map.hh | 8 ++++++++
+ src/test-map.cc | 21 +++++++++++----------
+ 2 files changed, 19 insertions(+), 10 deletions(-)
+
+commit ad176990895963c1b83274d0ef3c5ae148a4f760
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 13:36:12 2022 -0600
+
+ [map] Add is_equal() / towards making hb_map_t hashable
+
+ New API:
+ + hb_map_is_equal()
+
+ docs/harfbuzz-sections.txt | 1 +
+ src/hb-map.cc | 20 ++++++++++++++++++++
+ src/hb-map.h | 4 ++++
+ src/hb-map.hh | 15 +++++++++++++++
+ src/test-map.cc | 24 ++++++++++++++++++++++++
+ 5 files changed, 64 insertions(+)
+
+commit 14a24d8e3f7d9b8379452b1596e4aff6603e1f25
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 13:03:50 2022 -0600
+
+ [vector] Make hb_vector_t hashable
+
+ src/hb-vector.hh | 1 +
+ src/test-map.cc | 26 ++++++++++++++++++++++++++
+ 2 files changed, 27 insertions(+)
+
+commit 124f9aeb9b4c77fe1e2a733c5aceb9172d169f9f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 19 12:58:02 2022 -0600
+
+ [set] Make hb_set_t hashable
+
+ src/hb-bit-page.hh | 7 +++++++
+ src/hb-bit-set-invertible.hh | 2 ++
+ src/hb-bit-set.hh | 6 ++++++
+ src/hb-set.hh | 4 ++++
+ src/test-map.cc | 23 +++++++++++++++++++++++
+ 5 files changed, 42 insertions(+)
+
+commit 3ab2c7935f5b9706e4767a6e28ff1dcd739ac271
+Author: Garret Rieger <grieger@google.com>
+Date: Thu May 19 17:23:36 2022 +0000
+
+ [subset-perf] Signficiantly speed up ClassDef*::subset.
+
+ Eliminates the usage of a glyph -> klass hash map and replaces it with a vector storing the mapping. This allows us to use the vector directly as the iterator driving the serialize. Approximately 1% speedup for Noto Nastaliq.
+
+ src/hb-ot-layout-common.hh | 72 ++++++++++++++++++++++------------------------
+ 1 file changed, 35 insertions(+), 37 deletions(-)
+
+commit e3e685e5eec1cb400e0b4bd371872cb9394c79bc
+Author: David Corbett <corbett.dav@northeastern.edu>
+Date: Wed May 18 15:05:55 2022 -0400
+
+ [ot-tags] Fix `min_subtag_len` calculations
+
+ src/gen-tag-table.py | 12 +++++-------
+ src/hb-ot-tag-table.hh | 3 +--
+ 2 files changed, 6 insertions(+), 9 deletions(-)
+
+commit 0b1c2ff96a333a3e78eeefe54cb9e9509120990a
+Author: Garret Rieger <grieger@google.com>
+Date: Wed May 18 23:32:03 2022 +0000
+
+ [subset-perf] Remove extra map lookup in ClassDef subset methods.
+
+ src/hb-ot-layout-common.hh | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+commit 13ace77f1daaf94d79ad400e3943f71fa5139e70
+Author: Garret Rieger <grieger@google.com>
+Date: Wed May 18 22:38:43 2022 +0000
+
+ [subset-perf] Use glyph_map instead of set in ClassDefFormat.
+
+ src/hb-ot-layout-common.hh | 29 +++++++++++++++--------------
+ 1 file changed, 15 insertions(+), 14 deletions(-)
+
+commit adae2f2272bf51c6b4df2ba5d0e10eb25386e58c
+Author: Garret Rieger <grieger@google.com>
+Date: Wed May 18 21:42:28 2022 +0000
+
+ [subset-perf] Cache a glyph map for gsub.
+
+ This allows us in some cases to avoid using glyph_set_gsub as a filter.
+
+ src/hb-ot-layout-common.hh | 8 +++-----
+ src/hb-subset-plan.cc | 21 +++++++++++++++++++++
+ src/hb-subset-plan.hh | 1 +
+ 3 files changed, 25 insertions(+), 5 deletions(-)
+
+commit 202e6c469963fe76f3320a956be8b194adb9089d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 17:12:43 2022 -0600
+
+ [subset] Remove unnecessary test
+
+ src/hb-ot-layout-gsubgpos.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit cedf739646d67e73c06e2569d4be2d7f32e39fd8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 16:52:35 2022 -0600
+
+ Add some commented-out code
+
+ src/hb-ot-layout-common.hh | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+commit 6b62c10f0228d011526ef41772a65e6f12022ddb
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 16:27:54 2022 -0600
+
+ [priority-queue] Remove old init/fini
+
+ src/hb-priority-queue.hh | 7 -------
+ 1 file changed, 7 deletions(-)
+
+commit bff8248a9d44654d7901150e86e684af0cfa8681
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 16:25:03 2022 -0600
+
+ [repacker] Pre-alloc vertices
+
+ src/hb-repacker.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 39a424caf04392702b62950c832fd1f67204ba62
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 16:17:16 2022 -0600
+
+ [priority-queue] Optimize heap access
+
+ src/hb-priority-queue.hh | 18 ++++++++++++------
+ src/test-priority-queue.cc | 8 --------
+ 2 files changed, 12 insertions(+), 14 deletions(-)
+
+commit 9308659fd76bb400da2c869ca2f945760adfaf56
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 16:14:25 2022 -0600
+
+ [priority-queue] Optimize swap()
+
+ src/hb-priority-queue.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit c7317ef7617a1387c88db19582f1b9879a722d7a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 16:03:41 2022 -0600
+
+ [repacker] Avoid destroying and recreating objects
+
+ src/hb-repacker.hh | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit 864e09a0c460916c06d8becbc3480d06692cd634
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 15:59:29 2022 -0600
+
+ [repacker] Reuse allocated vector
+
+ src/hb-repacker.hh | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+commit ca77f164704c6463b09d973251f6f9995172d8c1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 15:55:49 2022 -0600
+
+ [repacker] Remove unnecessary vector .fini() calls
+
+ src/hb-repacker.hh | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit 4cfc2d668e3df53a6564cef1be65ad0239470123
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 15:32:19 2022 -0600
+
+ [subset] Use a std::move on set_t when feasible
+
+ src/hb-ot-layout-gsubgpos.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 1f578b5a32337011766e078331c0ba8ce4ce8af8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 15:24:40 2022 -0600
+
+ [set] Add pre-allocation internal API
+
+ src/hb-bit-set-invertible.hh | 1 +
+ src/hb-bit-set.hh | 7 +++++++
+ src/hb-set.hh | 1 +
+ 3 files changed, 9 insertions(+)
+
+commit 48dfbd54a3c9876e86bcdbeb47ae42300ee9f08f
+Author: Garret Rieger <grieger@google.com>
+Date: Wed May 18 21:03:56 2022 +0000
+
+ [subset] minor cleanup.
+
+ src/hb-ot-layout-common.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 482c6e5dc41402e60acf609fca0d9d8e8fbc4d9d
+Author: Garret Rieger <grieger@google.com>
+Date: Wed May 18 19:58:55 2022 +0000
+
+ [subset-perf] Speed up Coverage::serialize by caching iterator.
+
+ src/hb-ot-layout-common.hh | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+commit 14b18725f04bba0dac6da943244230c65d3879d4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 15:14:32 2022 -0600
+
+ In Coverage::iter_t, assume iterators are from same Coverage object
+
+ No need to support otherwise.
+
+ src/hb-ot-layout-common.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 27141735c3e8caa807c3528ce9793b8c8f05a556
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 15:12:49 2022 -0600
+
+ [subset] Add Coverage::__end__ implementation
+
+ src/hb-ot-layout-common.hh | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+commit c476f58adba6680c655cb7bcbdd28d3bd4b7ad37
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 14:20:23 2022 -0600
+
+ [subset] Write CoverageFormat2::intersects_coverage() as bsearch()
+
+ src/hb-ot-layout-common.hh | 23 ++++++++++++++---------
+ 1 file changed, 14 insertions(+), 9 deletions(-)
+
+commit 63c6695108ceb19b4b79e00782c3106801d7dc01
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 13:53:52 2022 -0600
+
+ [ot-layout] Cosmetic
+
+ The implementation of HBUINT16 operator == is slower than just
+ comparing to ints.
+
+ src/hb-ot-layout-common.hh | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+commit 777debd748dfd803bbd16bcc1bbf2afd7db2fc82
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 13:46:06 2022 -0600
+
+ [subset] Rewrite CoverageFormat2::intersects as dagger
+
+ src/hb-ot-layout-common.hh | 10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+commit cf5001fac7770286082ced9d3c5c5fefa3b19d79
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 13:38:29 2022 -0600
+
+ [subset] Optimize CoverageFormat2::intersected_coverage_glyphs
+
+ src/hb-ot-layout-common.hh | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+commit 6f37c2079815bc0ac9193c8e9028da4872374402
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 13:25:42 2022 -0600
+
+ [subset] Minor rewrite in CoverageFormat2::serialize()
+
+ src/hb-ot-layout-common.hh | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+commit e91863b7173543b850e1758873f96c76c67f8ce8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 12:39:55 2022 -0600
+
+ [subset-cff] Pre-size map in subr_remap_t::create()
+
+ src/hb-bimap.hh | 6 ++++++
+ src/hb-subset-cff-common.hh | 1 +
+ 2 files changed, 7 insertions(+)
+
+commit ce60462173c7d22f9bad8531a2490a551f004197
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 12:34:27 2022 -0600
+
+ [subset-plan] Pre-size maps in _create_old_gid_to_new_gid_map()
+
+ src/hb-subset-plan.cc | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+commit f82ee17a75dda53ac5c506136221b93eed53aee1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 12:17:43 2022 -0600
+
+ [map] Pre-size map in constructor if we can
+
+ src/hb-map.hh | 13 ++++++++-----
+ src/hb-ot-cmap-table.hh | 4 ++--
+ 2 files changed, 10 insertions(+), 7 deletions(-)
+
+commit b5aa8a27eac851503eaee086912f269b51e68724
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 11:58:58 2022 -0600
+
+ [subset-cff] Cosmetic
+
+ src/hb-subset-cff-common.hh | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+commit 0b201623f54420a898d3538c8673b450923bcac1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 11:58:22 2022 -0600
+
+ [subset-cff] Fix previous commit
+
+ Oops!
+
+ src/hb-subset-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 4792309265ea17aea0c5fd6821ed453fe8427ab4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 11:54:08 2022 -0600
+
+ [subset-cff] Access vector directly
+
+ src/hb-subset-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 7c86f2e763e44b4c96cd26f1ce06225b4aba977f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 11:45:27 2022 -0600
+
+ [subset-cff] Pre-alloc out buffer
+
+ src/hb-subset-cff-common.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 0761e7cdfd00d5347657bdf009c3035be4ebab44
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 11:37:57 2022 -0600
+
+ [subset-cff] Avoid resetting buffer as encoder does
+
+ src/hb-subset-cff-common.hh | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 71aa10a3942081f2c4ce0c2c5d4c3897d13d887c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 11:37:24 2022 -0600
+
+ [subset-cff] Manually grow vector to avoid memset overhead
+
+ src/hb-subset-cff-common.hh | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+commit f455cc53fd4a30682c549fcad6d4112b98688aca
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 11:31:55 2022 -0600
+
+ [subset-cff] Reuse buffer allocation
+
+ src/hb-subset-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 3e4ab2ad9c2de17218c16787b59d63c236262d8f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 11:16:46 2022 -0600
+
+ [perf/benchmark-ot] Add zh-hans
+
+ perf/benchmark-ot.cc | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 6e668a2adefdc186dcd300136b3535c43d6fdffd
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 11:16:11 2022 -0600
+
+ [perf/benchmark-ot] Rename test
+
+ perf/benchmark-ot.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e24797aeac65aaa1edd836bf9708f488044d3939
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 11:10:10 2022 -0600
+
+ [ot-tags] Follow-up to previous commit
+
+ Part of https://github.com/harfbuzz/harfbuzz/issues/3591
+
+ src/gen-tag-table.py | 16 ++++++++--------
+ src/hb-ot-tag-table.hh | 18 +++++++++---------
+ 2 files changed, 17 insertions(+), 17 deletions(-)
+
+commit f5d619be79e9f23f67f23513e60c546fc498f1b8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 18 11:04:52 2022 -0600
+
+ [ot-tags] Further gate the slow complex case, and add more tests
+
+ Part of https://github.com/harfbuzz/harfbuzz/issues/3591
+
+ Still 'zh-trad' is the slowest case.
+
+ --------------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iterations
+ --------------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_trad 136 ns 136 ns 5107838
+ BM_hb_ot_tags_from_script_and_language/COMMON ab_abcd 115 ns 115 ns 6103104
+ BM_hb_ot_tags_from_script_and_language/COMMON ab_abc 25.4 ns 25.3 ns 27674482
+ BM_hb_ot_tags_from_script_and_language/COMMON abcdef_XY 20.2 ns 20.1 ns 34795719
+ BM_hb_ot_tags_from_script_and_language/COMMON abcd_XY 19.4 ns 19.3 ns 36390401
+ BM_hb_ot_tags_from_script_and_language/COMMON cxy_CN 33.5 ns 33.4 ns 20998939
+ BM_hb_ot_tags_from_script_and_language/COMMON exy_CN 25.1 ns 25.0 ns 27705832
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_CN 34.2 ns 34.1 ns 20564356
+ BM_hb_ot_tags_from_script_and_language/COMMON en_US 15.5 ns 15.5 ns 45032204
+ BM_hb_ot_tags_from_script_and_language/LATIN en_US 15.9 ns 15.8 ns 44412379
+ BM_hb_ot_tags_from_script_and_language/COMMON none 4.72 ns 4.71 ns 149101665
+ BM_hb_ot_tags_from_script_and_language/LATIN none 4.72 ns 4.70 ns 149254498
+
+ perf/benchmark-ot.cc | 3 +++
+ src/gen-tag-table.py | 3 +++
+ src/hb-ot-tag-table.hh | 3 +++
+ 3 files changed, 9 insertions(+)
+
+commit 9c64bda21dd4215a3caa32e4127d9f2017e50de2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 17:31:18 2022 -0600
+
+ [ot-tag] Whitespace
+
+ src/hb-ot-tag.cc | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+commit 3df8017e9b7ea2b72477294133563b4ff304a007
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 17:29:39 2022 -0600
+
+ [ot-tag] Optimize subtag_matches() more
+
+ src/gen-tag-table.py | 2 +-
+ src/hb-ot-tag-table.hh | 112 ++++++++++++++++++++++++-------------------------
+ src/hb-ot-tag.cc | 5 +--
+ 3 files changed, 59 insertions(+), 60 deletions(-)
+
+commit b231fc2dbcee402d1cff578371f9ad89ff594bb2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 17:02:48 2022 -0600
+
+ [perf/benchmark-ot] Add a couple more test cases
+
+ perf/benchmark-ot.cc | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 3524b14fa06dbf9caddef1d2f598e2f4f46315c1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 17:02:48 2022 -0600
+
+ [perf/benchmark-ot] Add a couple more test cases
+
+ perf/benchmark-ot.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 7f6e8c5536fd13a56b4bd030233960aa1af38d05
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 16:58:35 2022 -0600
+
+ [ot-tags] Optimize subtag_matches() further
+
+ Part of https://github.com/harfbuzz/harfbuzz/issues/3591
+
+ Comparing before to after
+ Benchmark Time CPU Time Old Time New CPU Old CPU New
+ ----------------------------------------------------------------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON abcd_XY -0.3371 -0.3371 71 47 71 47
+
+ src/hb-ot-tag.cc | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit 27c11405a263ad43d24e2ed460e15f247ac06d17
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 16:51:51 2022 -0600
+
+ [ot-tag] Optimize subtag_matches
+
+ Part of https://github.com/harfbuzz/harfbuzz/issues/3591
+
+ src/hb-ot-tag.cc | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit a07d818597385c6d83265f8320b9c1334c539758
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 16:46:10 2022 -0600
+
+ [ot-tag] Add a likely() to the cache hit case
+
+ src/hb-ot-tag.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 0ff5d36cd451dffe51a8c0637b4a544882663a1d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 16:34:52 2022 -0600
+
+ [perf/benchmark-ot] Fix benchmark
+
+ Part of https://github.com/harfbuzz/harfbuzz/issues/3591
+
+ Ouch!
+
+ These are the current numbers:
+
+ ------------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iterations
+ ------------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON abcd_XY 78.0 ns 77.7 ns 8917912
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_CN 44.9 ns 44.8 ns 15475318
+ BM_hb_ot_tags_from_script_and_language/COMMON en_US 17.6 ns 17.5 ns 39812340
+ BM_hb_ot_tags_from_script_and_language/LATIN en_US 18.2 ns 18.1 ns 38356204
+ BM_hb_ot_tags_from_script_and_language/COMMON none 4.76 ns 4.74 ns 148746131
+ BM_hb_ot_tags_from_script_and_language/LATIN none 4.73 ns 4.71 ns 148421349
+
+ perf/benchmark-ot.cc | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+commit dfca47f419b6ef5c6df813822e4b10a7cec92434
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 16:21:02 2022 -0600
+
+ [ot-tag] Cache last bsearch result
+
+ Part of https://github.com/harfbuzz/harfbuzz/issues/3591
+
+ Humm. Looks like not all of the fat is bsearch overhead now. I cached
+ the last bsearch result, but most of the time is still there. I'm
+ baffled.
+
+ Before:
+ ------------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iterations
+ ------------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON abcd_XY 8.08 ns 8.05 ns 84500482
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_CN 42.2 ns 42.1 ns 16722006
+ BM_hb_ot_tags_from_script_and_language/COMMON en_US 16.1 ns 16.0 ns 43461527
+ BM_hb_ot_tags_from_script_and_language/LATIN en_US 16.5 ns 16.5 ns 42448505
+ BM_hb_ot_tags_from_script_and_language/COMMON none 4.34 ns 4.33 ns 161290530
+ BM_hb_ot_tags_from_script_and_language/LATIN none 4.34 ns 4.33 ns 162339799
+
+ After:
+ ------------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iterations
+ ------------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON abcd_XY 8.13 ns 8.11 ns 80438134
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_CN 40.0 ns 39.9 ns 17487939
+ BM_hb_ot_tags_from_script_and_language/COMMON en_US 12.7 ns 12.7 ns 55124394
+ BM_hb_ot_tags_from_script_and_language/LATIN en_US 13.1 ns 13.0 ns 53660125
+ BM_hb_ot_tags_from_script_and_language/COMMON none 4.61 ns 4.60 ns 151394104
+ BM_hb_ot_tags_from_script_and_language/LATIN none 4.70 ns 4.68 ns 150402847
+
+ src/hb-ot-tag.cc | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+commit 909f00ac6e6b3eb459f0553b84fe508bb697e9af
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 15:51:41 2022 -0600
+
+ [ot-tags] Further speed up language bsearch()
+
+ Using an integer tag to bsearch, instead of string.
+
+ Part of: https://github.com/harfbuzz/harfbuzz/issues/3591
+
+ Before:
+ ------------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iterations
+ ------------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON abcd_XY 8.11 ns 8.08 ns 87067795
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_CN 53.6 ns 53.5 ns 13042418
+ BM_hb_ot_tags_from_script_and_language/COMMON en_US 24.2 ns 24.1 ns 29052731
+ BM_hb_ot_tags_from_script_and_language/LATIN en_US 24.4 ns 24.3 ns 28736769
+ BM_hb_ot_tags_from_script_and_language/COMMON none 4.43 ns 4.41 ns 160370413
+ BM_hb_ot_tags_from_script_and_language/LATIN none 4.35 ns 4.34 ns 160578191
+
+ After:
+ ------------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iterations
+ ------------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON abcd_XY 7.97 ns 7.95 ns 85208363
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_CN 41.7 ns 41.6 ns 16945817
+ BM_hb_ot_tags_from_script_and_language/COMMON en_US 16.1 ns 16.0 ns 43613523
+ BM_hb_ot_tags_from_script_and_language/LATIN en_US 16.5 ns 16.4 ns 42568107
+ BM_hb_ot_tags_from_script_and_language/COMMON none 4.30 ns 4.29 ns 164055469
+ BM_hb_ot_tags_from_script_and_language/LATIN none 4.29 ns 4.27 ns 163793591
+
+ src/gen-tag-table.py | 2 +-
+ src/hb-ot-tag-table.hh | 3206 ++++++++++++++++++++++++------------------------
+ src/hb-ot-tag.cc | 29 +-
+ 3 files changed, 1622 insertions(+), 1615 deletions(-)
+
+commit c460cf74ce2a3ebe5d285e03dc122fb60ff70e01
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 15:30:11 2022 -0600
+
+ [ot-tags] Cosmetic
+
+ src/hb-ot-tag.cc | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 1c8226ed14c1ac7d82ea5482bdf2a7d019dd38a2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 15:28:50 2022 -0600
+
+ Fix compiler warning
+
+ On Mac compiler:
+
+ FAILED: src/libharfbuzz.0.dylib.p/hb-ot-tag.cc.o
+ c++ -Isrc/libharfbuzz.0.dylib.p -Isrc -I../src -I. -I.. -I/usr/local/opt/freetype/include/freetype2 -I/usr/local/Cellar/graphite2/1.3.14/include -I/usr/local/Cellar/glib/2.72.1/include/glib-2.0 -I/usr/local/Cellar/glib/2.72.1/lib/glib-2.0/include -I/usr/local/opt/gettext/include -I/usr/local/Cellar/pcre/8.45/include -Xclang -fcolor-diagnostics --coverage -pipe -Wall -Winvalid-pch -Wnon-virtual-dtor -std=c++11 -fno-rtti -O2 -g -fno-exceptions -fno-rtti -fno-threadsafe-statics -fvisibility-inlines-hidden -DHAVE_CONFIG_H -Wno-non-virtual-dtor -MD -MQ src/libharfbuzz.0.dylib.p/hb-ot-tag.cc.o -MF src/libharfbuzz.0.dylib.p/hb-ot-tag.cc.o.d -o src/libharfbuzz.0.dylib.p/hb-ot-tag.cc.o -c ../src/hb-ot-tag.cc
+ In file included from ../src/hb-ot-tag.cc:29:
+ In file included from ../src/hb.hh:481:
+ ../src/hb-array.hh:359:14: error: missing default argument on parameter 'ds'
+ Ts... ds) const
+ ^
+ ../src/hb-ot-tag.cc:292:58: note: in instantiation of function template specialization 'hb_sorted_array_t<const LangTag>::bfind<const char *, unsigned int>' requested here
+ if (hb_sorted_array (ot_languages, ot_languages_len).bfind (lang_str, &tag_idx,
+ ^
+ 1 error generated.
+
+ src/hb-array.hh | 9 ++++-----
+ src/hb-ot-tag.cc | 4 +---
+ 2 files changed, 5 insertions(+), 8 deletions(-)
+
+commit c1f4b57c064d41a291976e6d126f7bf0f6e66bc9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 15:19:40 2022 -0600
+
+ [ot-tags] Optimize language comparison
+
+ Now that we know both strings are of equal len of 2 or 3, optimize.
+
+ Part of https://github.com/harfbuzz/harfbuzz/issues/3591
+
+ Before:
+ ------------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iterations
+ ------------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON abcd_XY 8.50 ns 8.47 ns 81221549
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_CN 79.6 ns 79.3 ns 8785804
+ BM_hb_ot_tags_from_script_and_language/COMMON en_US 40.0 ns 39.9 ns 17462768
+ BM_hb_ot_tags_from_script_and_language/LATIN en_US 39.2 ns 39.1 ns 17886793
+ BM_hb_ot_tags_from_script_and_language/COMMON none 4.31 ns 4.30 ns 162805417
+ BM_hb_ot_tags_from_script_and_language/LATIN none 4.32 ns 4.31 ns 162656688
+
+ After:
+ ------------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iterations
+ ------------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON abcd_XY 8.27 ns 8.24 ns 81868701
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_CN 56.1 ns 56.0 ns 12353284
+ BM_hb_ot_tags_from_script_and_language/COMMON en_US 24.3 ns 24.2 ns 28955030
+ BM_hb_ot_tags_from_script_and_language/LATIN en_US 24.5 ns 24.4 ns 28664868
+ BM_hb_ot_tags_from_script_and_language/COMMON none 4.35 ns 4.34 ns 161190014
+ BM_hb_ot_tags_from_script_and_language/LATIN none 4.36 ns 4.34 ns 161319000
+
+ src/hb-array.hh | 14 ++++++++------
+ src/hb-ot-tag.cc | 19 ++++++-------------
+ 2 files changed, 14 insertions(+), 19 deletions(-)
+
+commit dde48d78c1e1c11f3c770491a1d618386b3d92f8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 15:07:49 2022 -0600
+
+ Fix compiler warning
+
+ src/hb-ot-tag.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 15be0deda03f68c0260d07bdc67c8952aa6ccfa7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 14:57:08 2022 -0600
+
+ [ot-tags] Optimize lang_matches()
+
+ Part of https://github.com/harfbuzz/harfbuzz/issues/3591
+
+ Before:
+ ------------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iterations
+ ------------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON abcd_XY 8.67 ns 8.64 ns 80324382
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_CN 91.2 ns 90.9 ns 7674131
+ BM_hb_ot_tags_from_script_and_language/COMMON en_US 41.1 ns 41.0 ns 17174093
+ BM_hb_ot_tags_from_script_and_language/LATIN en_US 41.3 ns 41.2 ns 17000876
+ BM_hb_ot_tags_from_script_and_language/COMMON none 4.56 ns 4.55 ns 153914130
+ BM_hb_ot_tags_from_script_and_language/LATIN none 4.53 ns 4.52 ns 153830303
+
+ After:
+ ------------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iterations
+ ------------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON abcd_XY 8.24 ns 8.21 ns 84078465
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_CN 77.5 ns 77.2 ns 9059230
+ BM_hb_ot_tags_from_script_and_language/COMMON en_US 38.8 ns 38.7 ns 17790692
+ BM_hb_ot_tags_from_script_and_language/LATIN en_US 37.6 ns 37.5 ns 18648293
+ BM_hb_ot_tags_from_script_and_language/COMMON none 4.50 ns 4.49 ns 155573267
+ BM_hb_ot_tags_from_script_and_language/LATIN none 4.49 ns 4.47 ns 156456653
+
+ src/gen-tag-table.py | 2 +-
+ src/hb-ot-tag-table.hh | 126 ++++++++++++++++++++++++-------------------------
+ src/hb-ot-tag.cc | 11 +++--
+ 3 files changed, 70 insertions(+), 69 deletions(-)
+
+commit 407a135baf8ccd53cf1bc3502f3216f3dbcf3328
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 14:45:45 2022 -0600
+
+ [perf/benchmark-ot] Add one more test
+
+ perf/benchmark-ot.cc | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit dd3c858f84105021cf1e427399b971bf26dde8b3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 14:28:28 2022 -0600
+
+ [ot-tags] Speed up hb_ot_tags_from_language()
+
+ Part of https://github.com/harfbuzz/harfbuzz/issues/3591
+
+ "After that, bulk of the time I suppose is spent in binary-searching the
+ language table. I suggest we split the language table in 2-letter and
+ 3-letter tags, to speed-up the vast majority of cases that are
+ 2-letter."
+
+ benchmark-ot, before:
+
+ ----------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iterations
+ ----------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_CN 112 ns 111 ns 6286271
+ BM_hb_ot_tags_from_script_and_language/COMMON en_US 60.6 ns 60.4 ns 11671176
+ BM_hb_ot_tags_from_script_and_language/LATIN en_US 61.3 ns 61.1 ns 11442645
+ BM_hb_ot_tags_from_script_and_language/COMMON none 4.75 ns 4.74 ns 146997235
+ BM_hb_ot_tags_from_script_and_language/LATIN none 4.65 ns 4.64 ns 150938747
+
+ After:
+
+ ----------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iterations
+ ----------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_CN 89.5 ns 89.2 ns 7747649
+ BM_hb_ot_tags_from_script_and_language/COMMON en_US 38.5 ns 38.4 ns 18199432
+ BM_hb_ot_tags_from_script_and_language/LATIN en_US 39.0 ns 38.9 ns 18049238
+ BM_hb_ot_tags_from_script_and_language/COMMON none 4.53 ns 4.52 ns 154895110
+ BM_hb_ot_tags_from_script_and_language/LATIN none 4.54 ns 4.52 ns 154762105
+
+ src/gen-tag-table.py | 55 +++----
+ src/hb-ot-tag-table.hh | 409 +++++++++++++++++++++++++------------------------
+ src/hb-ot-tag.cc | 45 ++++--
+ 3 files changed, 270 insertions(+), 239 deletions(-)
+
+commit 9baccb986087319ae56e77624082036063d67d90
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 13:34:34 2022 -0600
+
+ [ot-tags] Speed up hb_ot_tags_from_complex_language()
+
+ Part of https://github.com/harfbuzz/harfbuzz/issues/3591
+
+ 2. All the subtag_matches outside the switch match long strings (>= 6 or so).
+ As such, check the tag for such length before going into any of them.
+
+ benchmark-ot, before:
+
+ ----------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iterations
+ ----------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_CN 172 ns 171 ns 4083155
+ BM_hb_ot_tags_from_script_and_language/COMMON en_US 120 ns 119 ns 5849947
+ BM_hb_ot_tags_from_script_and_language/LATIN en_US 113 ns 112 ns 5840326
+ BM_hb_ot_tags_from_script_and_language/COMMON none 4.66 ns 4.64 ns 151396224
+ BM_hb_ot_tags_from_script_and_language/LATIN none 4.66 ns 4.64 ns 149019593
+
+ After:
+
+ ----------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iterations
+ ----------------------------------------------------------------------------------------------
+ BM_hb_ot_tags_from_script_and_language/COMMON zh_CN 112 ns 112 ns 6357763
+ BM_hb_ot_tags_from_script_and_language/COMMON en_US 60.5 ns 60.3 ns 11475091
+ BM_hb_ot_tags_from_script_and_language/LATIN en_US 54.9 ns 54.8 ns 12575690
+ BM_hb_ot_tags_from_script_and_language/COMMON none 4.61 ns 4.59 ns 152388450
+ BM_hb_ot_tags_from_script_and_language/LATIN none 4.66 ns 4.64 ns 151497600
+
+ src/gen-tag-table.py | 41 +++++++++++-----
+ src/hb-ot-tag-table.hh | 126 +++++++++++++++++++++++++------------------------
+ 2 files changed, 95 insertions(+), 72 deletions(-)
+
+commit 26d906b88b324ea953f42acf1b82086cc4ad3642
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 17 13:12:17 2022 -0600
+
+ [perf] Add benchmark-ot
+
+ perf/Makefile.am | 1 +
+ perf/benchmark-ot.cc | 35 +++++++++++++++++++++++++++++++++++
+ perf/meson.build | 10 ++++++++++
+ 3 files changed, 46 insertions(+)
+
+commit 629fa8ee87a419c3a2f6b1477d7ecd81571f0d7e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 16 17:44:50 2022 -0600
+
+ [perf/benchmark-font] Test Roboto as variable even though it's not
+
+ perf/benchmark-font.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 71a0cda869f55c00727fdbbf079b671f7fe374ff
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 16 17:43:48 2022 -0600
+
+ [perf/benchmark-font] Only certain fonts are variable
+
+ Don't test every font as variable.
+
+ perf/benchmark-font.cc | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+commit fb413f52022aa2edb8a5b64e9d28f826a161d0aa
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 16 17:08:43 2022 -0600
+
+ [subset/cff] Don't use bitfields for hot bools
+
+ The struct has room because of alignment, and these bools are hot.
+
+ src/hb-subset-cff-common.hh | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit a4d98b63ea59f17ef5e4795f6048f9cd6baa4340
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 16 17:02:40 2022 -0600
+
+ [subset/cff1] Collect glyph-to-sid map to avoid an O(n^2) algorithm
+
+ Saves 13 for largest benchmark:
+
+ BM_subset/subset_glyphs/SourceHanSans-Regular_subset.otf/10000 -0.1313 -0.1308 75 65 75 65
+
+ BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/4096 -0.1009 -0.1004 54 48 54 48
+ BM_subset/subset_codepoints/SourceHanSans-Regular_subset.otf/10000 -0.1067 -0.1066 70 62 69 62
+
+ src/hb-ot-cff1-table.hh | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
+ src/hb-subset-cff1.cc | 8 +++++++-
+ 2 files changed, 53 insertions(+), 2 deletions(-)
+
+commit b87f48e948077297b823ac929e950d4188ec627d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 16 16:33:31 2022 -0600
+
+ [cff1] get_sid() move bounds check into each implementation
+
+ src/hb-ot-cff1-table.hh | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+commit e1e359b4daac86cea0a4f02f7f175e93ea9440d7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 16 15:53:28 2022 -0600
+
+ [cff1] Tighten up range_list_t a bit
+
+ src/hb-subset-cff1.cc | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+commit 3fbac0942da80457f8c226105f5a4a1bdfe502f5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 16 15:41:11 2022 -0600
+
+ [cff1] Lazy-load & sort glyph names
+
+ Improves subset benchmarks by up to 70% for small CFF1 subset of
+ non-CID fonts!
+
+ BM_subset/subset_glyphs/SourceSansPro-Regular.otf/10 -0.7067 -0.7071 1 0 1 0
+ BM_subset/subset_glyphs/SourceSansPro-Regular.otf/64 -0.4817 -0.4824 1 0 1 0
+ BM_subset/subset_glyphs/SourceSansPro-Regular.otf/512 -0.1948 -0.1956 2 2 2 2
+ BM_subset/subset_glyphs/SourceSansPro-Regular.otf/2000 -0.0767 -0.0761 6 6 6 6
+
+ src/hb-ot-cff1-table.hh | 74 +++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 53 insertions(+), 21 deletions(-)
+
+commit b58bfd9818243fc1178ecad0731fa24a5aa3f235
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 16 11:21:45 2022 -0600
+
+ [font] Minor move of code to silence gcc-12 warning
+
+ See mailing list discussion.
+
+ src/hb-font.cc | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 602e0ca79d1a651fee0cd23d2fa3580621006c87
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 16 10:14:34 2022 -0600
+
+ [cff] Minor restructure of struct
+
+ Surprisingly this shows tiny benchmark improvement consistently.
+
+ src/hb-cff-interp-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit acdab17ed3507bc9524cb57bef703a983e1031cf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 13 14:14:36 2022 -0600
+
+ [cff] Cosmetic in parsed_values_t
+
+ src/hb-cff-interp-common.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit b46c7faa9c77e288d16869b9ac609524e0f89468
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 13 14:02:54 2022 -0600
+
+ [cff] Check buf_len, not buf
+
+ Ouch!
+
+ src/hb-ot-cff1-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 19a8db85458f02f5be268747b85a2c4fab1319b9
+Author: Garret Rieger <grieger@google.com>
+Date: Fri May 13 18:05:05 2022 +0000
+
+ [subset] fix potential integer overflow in gname_t::cmp.
+
+ src/hb-ot-cff-common.hh | 3 ++-
+ src/hb-ot-cff1-table.hh | 2 +-
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+commit 2d2f66e1a300e14aac16120f2dc193717502129e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 13 13:53:17 2022 -0600
+
+ [cff-common] In INDEX, return empty bytes if length is zero
+
+ Before it was possible to return non-null arrayZ.
+
+ src/hb-ot-cff-common.hh | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit a2f132f1fc5ed1c8426dea1b1e27aa1eaf8eeb04
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 13 13:49:17 2022 -0600
+
+ [cff] Check glyph-name's length, not arrayZ
+
+ As the latter can be non-null while still zero-length.
+
+ src/hb-ot-cff1-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit dc09053f1924a486058a8737fda22567e6d95213
+Author: jeremiazhao <jeremiazhao@tencent.com>
+Date: Fri May 13 17:54:11 2022 +0800
+
+ fix build requirements for fedora/centos in buiding document
+
+ BUILD.md | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit c657c4e1f8e6f23828fefbc441b01f7bee685c79
+Author: Thomas Devoogdt <thomas.devoogdt@barco.com>
+Date: Tue May 10 10:00:06 2022 +0200
+
+ [meta] fix type traits on gcc 4.9 #3526
+
+ Signed-off-by: Thomas Devoogdt <thomas.devoogdt@barco.com>
+
+ src/hb-meta.hh | 11 +++++++++++
+ src/hb-open-type.hh | 11 ++++++-----
+ src/hb-vector.hh | 17 +++++++++--------
+ 3 files changed, 26 insertions(+), 13 deletions(-)
+
+commit e4e053c8b3a72295c7f414726085aaa01c137c6f
+Author: Garret Rieger <grieger@google.com>
+Date: Fri May 13 17:00:57 2022 +0000
+
+ [perf] fix typo in perf Makefile.
+
+ perf/Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e61234c5f75e21901a81df08945daddca5cbfde3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 12 13:20:10 2022 -0600
+
+ [vector] Add tests for move constructor/assignment
+
+ src/test-vector.cc | 17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+commit 7fa580bc4f83f5440b23531f53b546d52af0f69b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 12 13:05:32 2022 -0600
+
+ [map] Fix map copy/move constructors to actually work
+
+ Ouch!
+
+ src/hb-map.hh | 5 +++--
+ src/hb-set.hh | 3 +--
+ src/test-map.cc | 22 ++++++++++++++++++----
+ src/test-set.cc | 4 +++-
+ 4 files changed, 25 insertions(+), 9 deletions(-)
+
+commit a09dd87ca373c1629c05803e3b8611274cb15a6c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 12 12:58:07 2022 -0600
+
+ [set] Fix set copy/move constructors to actually work
+
+ Ouch!
+
+ src/hb-set.hh | 16 ++++++++++------
+ src/test-set.cc | 19 ++++++++++++++-----
+ 2 files changed, 24 insertions(+), 11 deletions(-)
+
+commit 76fc27713f52cc338f0325650c2c7798f5cfa2ce
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 12 12:14:07 2022 -0600
+
+ [vector] Remove explicit std::move
+
+ Was confusing compilers. Let them figure it out themselves.
+
+ Makes NotoNastaliqu subsetting/1000 benchmark more than twice faster:
+
+ Benchmark Time CPU Time Old Time New CPU Old CPU New
+ ------------------------------------------------------------------------------------------------------------------------------------------------------------
+ BM_subset/subset_glyphs/NotoNastaliqUrdu-Regular.ttf/1000 -0.5064 -0.5065 111 55 110 55
+ BM_subset/subset_codepoints/NotoNastaliqUrdu-Regular.ttf/1000 -0.5494 -0.5493 132 59 131 59
+
+ src/hb-vector.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit c81198b5bc7d5d0990752b36ad2b1fcdec963abf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 12 11:58:37 2022 -0600
+
+ [set] Tweak move operators a bit
+
+ Should be equivalent.
+
+ src/hb-bit-set-invertible.hh | 6 +++---
+ src/hb-set.hh | 4 ++--
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+commit 8dc072d20d87d2986cd58797bc1993c372e5d4d6
+Merge: bff78e651 175319cd8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 11 16:45:40 2022 -0600
+
+ Merge pull request #3579 from harfbuzz/subset-retain-buffer
+
+ Subset retain buffer
+
+commit 175319cd89fbab431616eb83d4d7c569fe4e8800
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 11 13:47:17 2022 -0600
+
+ [gsubgpos] Clean up OT::ClassDefFormat2::intersected_class_glyphs 0 case
+
+ src/hb-ot-layout-common.hh | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+commit 137af3612bcf038103bfc315f445d6574cba8d2c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 11 13:39:30 2022 -0600
+
+ [gsubgpos] Simplify OT::ClassDefFormat2::intersected_class_glyphs()
+
+ src/hb-ot-layout-common.hh | 39 +++++++++++++++++++--------------------
+ 1 file changed, 19 insertions(+), 20 deletions(-)
+
+commit 3261e05bdbb067cb9411a38a585bb04be1fb2542
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 11 13:16:31 2022 -0600
+
+ [subset] Optimize ClassDef1::intersected_class_glyphs() for class0
+
+ src/hb-ot-layout-common.hh | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+commit c78d8ba60b49013e3ca98a2d7b030dc5d8c569d8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 11 13:05:41 2022 -0600
+
+ [subset] Allocate same size as source table for GSUB/GPOS/name
+
+ src/hb-subset.cc | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+commit 2e7f1ae48feaa2db8248b7ae01e46ef70e461a31
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 11 12:49:16 2022 -0600
+
+ [subset] Use vector.allocated size instead of tracking buf_size
+
+ src/hb-subset.cc | 10 +++++-----
+ src/hb-vector.hh | 3 +--
+ 2 files changed, 6 insertions(+), 7 deletions(-)
+
+commit f08537963b5157cd9e7a02f6e1695ff6bd27cc1b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 11 12:10:03 2022 -0600
+
+ [cff-subset] Pre-alloc vector for operator decoding
+
+ src/hb-cff-interp-common.hh | 5 +++++
+ src/hb-subset-cff-common.hh | 1 +
+ 2 files changed, 6 insertions(+)
+
+commit 7edd54f3ddadc10307577575f47e943b86198e9d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 10 18:44:14 2022 -0600
+
+ [perf/benchmark-subset] Minor cleanup
+
+ perf/benchmark-subset.cc | 32 +++++++++++++++++++-------------
+ 1 file changed, 19 insertions(+), 13 deletions(-)
+
+commit aeb50b8942b92cda2b1d5bb03d685f97f79faf5d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 10 18:06:53 2022 -0600
+
+ [subset] Retain buffer across table subset operations
+
+ src/hb-subset.cc | 61 +++++++++++++++++++++++++++++---------------------------
+ 1 file changed, 32 insertions(+), 29 deletions(-)
+
+commit bff78e651555e6376d2a4b49c323cf5e9fe3a25c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 10 16:33:37 2022 -0600
+
+ [cff] Convert interpretation environment to use constructor
+
+ src/hb-cff-interp-common.hh | 29 ++++++++---------------------
+ src/hb-cff-interp-cs-common.hh | 13 +++++--------
+ src/hb-cff-interp-dict-common.hh | 2 ++
+ src/hb-cff1-interp-cs.hh | 8 +++-----
+ src/hb-cff2-interp-cs.hh | 9 ++++-----
+ src/hb-ot-cff1-table.cc | 16 ++++++++--------
+ src/hb-ot-cff1-table.hh | 19 ++++++++++---------
+ src/hb-ot-cff2-table.cc | 8 ++++----
+ src/hb-ot-cff2-table.hh | 24 ++++++++++--------------
+ src/hb-subset-cff-common.hh | 8 ++++----
+ 10 files changed, 58 insertions(+), 78 deletions(-)
+
+commit de053e2efbcf0166590868c993bfbe7cc3453a06
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 10 15:38:37 2022 -0600
+
+ [cff] Convert subr_subset_param_t to use constructor
+
+ src/hb-subset-cff-common.hh | 59 ++++++++++++++++++++++++---------------------
+ 1 file changed, 31 insertions(+), 28 deletions(-)
+
+commit 96140db485b61995b0fe9528b6323a5ea928e5a8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 10 15:34:33 2022 -0600
+
+ [cff] Convert cff2_extents_param_t to use constructor
+
+ src/hb-ot-cff2-table.cc | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+commit 54544f2a57373b2d74bda55d4a48f58a0121c22c
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 10 15:31:49 2022 -0600
+
+ [cff] Convert cff1_extents_param_t to use constructor
+
+ src/hb-ot-cff1-table.cc | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+commit 377befd0c72071190029112ee04ab0a06fea60b6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 10 15:29:12 2022 -0600
+
+ [cff] Convert get_seac_param_t to use constructor
+
+ src/hb-ot-cff1-table.cc | 14 ++++----------
+ 1 file changed, 4 insertions(+), 10 deletions(-)
+
+commit 8fd70362fa4c0f411fc67b15b67b69a7c43431e3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 10 15:15:49 2022 -0600
+
+ [cff] Use hb_ubytes_t() instead of Null(hb_ubytes_t)
+
+ src/hb-cff-interp-cs-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9033c7f99d5ffe80c349a2ed5e4ef68ca4bed434
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 10 14:58:53 2022 -0600
+
+ [cff-common] Optimize INDEX::operator[]
+
+ Previous try showed slowdown in benchmarks, suprisingly.
+
+ Rewrite it keeping the function, hopefully allowing better optimization.
+
+ src/hb-ot-cff-common.hh | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit 3aace2431b9bd503cb706760d831ae313d059107
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 10 14:54:04 2022 -0600
+
+ Revert "[cff-common] Optimize INDEX::operator[]"
+
+ This reverts commit 9edb03ac7ac4b4d0814f3fd1f20cc8d2be99e971.
+
+ src/hb-ot-cff-common.hh | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+commit b31ef081db0d91fd6d3e72a59fc97248ab28a904
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 10 14:52:40 2022 -0600
+
+ Revert "[cff] Add an unlikely()"
+
+ This reverts commit 9ba9adb7ed6d48504e97a2af117b7da1fdb28450.
+
+ This shows slowdown in benchmarks.
+
+ src/hb-cff-interp-cs-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9ba9adb7ed6d48504e97a2af117b7da1fdb28450
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 10 14:42:50 2022 -0600
+
+ [cff] Add an unlikely()
+
+ src/hb-cff-interp-cs-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 9edb03ac7ac4b4d0814f3fd1f20cc8d2be99e971
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 10 14:25:08 2022 -0600
+
+ [cff-common] Optimize INDEX::operator[]
+
+ src/hb-ot-cff-common.hh | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+commit 52d59bf150b2a6312fe4c3b6f2ec882febe814d9
+Author: Garret Rieger <grieger@google.com>
+Date: Tue May 10 19:40:37 2022 +0000
+
+ [perf] Make subset benchmark data driven.
+
+ perf/benchmark-subset.cc | 153 +++++++--------------
+ .../data}/fonts/NotoSansDevanagari-Regular.ttf | Bin
+ 2 files changed, 52 insertions(+), 101 deletions(-)
+
+commit 0a42410dc8a8457f49b94a0b533f0b83191ce8d5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Tue May 10 12:05:19 2022 -0600
+
+ [cff2] Change extents/shape stack to be just a number
+
+ Do the blending immediately.
+
+ Fixes https://github.com/harfbuzz/harfbuzz/issues/3559
+
+ Benchmark on AdobeVFPrototype shows 35% speedup. Now we're faster
+ than FreeType:
+
+ Benchmark Time CPU Time Old Time New CPU Old CPU New
+ ------------------------------------------------------------------------------------------------------------------------------------------------
+ BM_Font/glyph_extents/AdobeVFPrototype.otf/hb -0.3792 -0.3792 1584 983 1581 982
+ BM_Font/glyph_extents/AdobeVFPrototype.otf/ft +0.0228 +0.0224 1220 1248 1218 1245
+ BM_Font/glyph_extents/AdobeVFPrototype.otf/var/hb -0.3513 -0.3518 1616 1048 1613 1046
+ BM_Font/glyph_extents/AdobeVFPrototype.otf/var/ft +0.0172 +0.0169 1232 1254 1230 1251
+
+ src/hb-cff-interp-common.hh | 4 +--
+ src/hb-cff2-interp-cs.hh | 82 +++++++++++++++++++++++++++------------------
+ src/hb-ot-cff2-table.cc | 24 ++++++-------
+ src/hb-subset-cff2.cc | 28 ++++++++--------
+ 4 files changed, 77 insertions(+), 61 deletions(-)
+
+commit 5277a5772b0b9ebbbcdec0eae7f1b13d41a8d170
+Author: Garret Rieger <grieger@google.com>
+Date: Tue May 10 18:14:25 2022 +0000
+
+ [perf] Add benchmarks for CFF subsetting.
+
+ perf/benchmark-subset.cc | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+commit 8f9f0c494b9ea516903e8142e8aba391ddcb581c
+Author: Garret Rieger <grieger@google.com>
+Date: Tue May 10 17:47:08 2022 +0000
+
+ [subset] Enforce cmap12 group ordering constraints in collect_mapping.
+
+ Fixes fuzzer issue: https://oss-fuzz.com/testcase-detail/6365271012540416
+
+ src/hb-ot-cmap-table.hh | 8 ++++++++
+ ...estcase-minimized-hb-subset-fuzzer-6365271012540416 | Bin 0 -> 161424 bytes
+ 2 files changed, 8 insertions(+)
+
+commit c99ad0f015d1328cbb9803777f66ca491b2cb115
+Merge: c941ece60 1b14d2ff1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 18:52:19 2022 -0600
+
+ Merge pull request #3572 from harfbuzz/cff-stack
+
+ Cff stack
+
+commit 1b14d2ff136a9f7522995393fda6f6644377657f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 18:15:31 2022 -0600
+
+ [cff] Fix arg-stack peek() impl
+
+ src/hb-cff-interp-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 6106ef8c0f61453c38c58f71a045481bf5546f2d
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 18:12:09 2022 -0600
+
+ [cff] Tighten up arg-stack access
+
+ src/hb-cff-interp-common.hh | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+commit 8c616a6efe7370e110d6a2f822bb1a38bf768ea6
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 17:49:54 2022 -0600
+
+ [cff] Allocate stack inline instead of using hb_vector_t
+
+ Speeds up glyph_extents and glyph_shape benchmarks for CFF by 10
+ to 16 percent!
+
+ src/hb-cff-interp-common.hh | 18 +++++++-----------
+ 1 file changed, 7 insertions(+), 11 deletions(-)
+
+commit c941ece60fe791b58697a0ac9d92cd27682f0698
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 16:20:22 2022 -0600
+
+ [cff] Use using instead of typedef
+
+ src/hb-cff-interp-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 64d63cebe2968bc8d9882991b5402c7d626ecf90
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 16:16:07 2022 -0600
+
+ [cff-common] Use existing types for str_buff_vec_t
+
+ src/hb-ot-cff-common.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit e1838ec1f863758bdd3fa33dce8bf8bfb7fa1518
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 16:14:13 2022 -0600
+
+ [cff-common] Remove unused method
+
+ src/hb-ot-cff-common.hh | 11 +----------
+ 1 file changed, 1 insertion(+), 10 deletions(-)
+
+commit 8aa54aaca250e2934bd2c97047db8b40bf027908
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 16:09:56 2022 -0600
+
+ [cff] Replace byte_str_t with hb_bytes_t use
+
+ src/hb-cff-interp-common.hh | 25 ++++++++++---------------
+ src/hb-cff-interp-cs-common.hh | 6 +++---
+ src/hb-cff1-interp-cs.hh | 2 +-
+ src/hb-cff2-interp-cs.hh | 2 +-
+ src/hb-ot-cff-common.hh | 14 +++++++-------
+ src/hb-ot-cff1-table.cc | 6 +++---
+ src/hb-ot-cff1-table.hh | 12 ++++++------
+ src/hb-ot-cff2-table.cc | 4 ++--
+ src/hb-ot-cff2-table.hh | 8 ++++----
+ src/hb-subset-cff-common.hh | 6 +++---
+ src/hb-subset-cff1.cc | 2 +-
+ 11 files changed, 41 insertions(+), 46 deletions(-)
+
+commit fe1d85a55a53797f0808d1f473475b7ce15eeb92
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 16:04:52 2022 -0600
+
+ [cff] Remove custom byte_str_t impl
+
+ src/hb-cff-interp-common.hh | 35 ++++++++++-------------------------
+ src/hb-ot-cff1-table.hh | 4 ++--
+ src/hb-ot-cff2-table.hh | 4 ++--
+ 3 files changed, 14 insertions(+), 29 deletions(-)
+
+commit c8a5f1e3c0cb8b2c0c546e89134cb66b9af2b53a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 15:49:47 2022 -0600
+
+ [cff-common] Indent
+
+ src/hb-ot-cff-common.hh | 49 +++++++++++++++++++++++++------------------------
+ 1 file changed, 25 insertions(+), 24 deletions(-)
+
+commit be7b2905cb118a5d4d08f42e870fe5f5f5ee9b0e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 15:48:18 2022 -0600
+
+ [cff-common] Remove unused INDEX::serialize() method
+
+ src/hb-ot-cff-common.hh | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+commit 60390169b65632406391f3492efdbd66c688555f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 15:44:09 2022 -0600
+
+ [cff-common] Write str_buf_t::total_size() as dagger
+
+ src/hb-ot-cff-common.hh | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+commit 258afb45b7fefa42e36f74731d56862b9367f91e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 15:40:55 2022 -0600
+
+ [cff-common] Use range-based loop in str_buff_vec_t
+
+ src/hb-ot-cff-common.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 8bb1a3ce9ae8a24c168a51c6faf16779561138ae
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 15:38:40 2022 -0600
+
+ [cff-common] Write INDEX offset-size calc using hb_bit_storage()
+
+ src/hb-ot-cff-common.hh | 15 +--------------
+ 1 file changed, 1 insertion(+), 14 deletions(-)
+
+commit 2ccfe84eff7f72159c87012d7e10e9c8ecdbc956
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 15:35:04 2022 -0600
+
+ [cff-common] Add assert to INDEX::set_offset_at()
+
+ src/hb-ot-cff-common.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 4bcab9e99a7fb7456f5788e2da6fae8fc5b14584
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 15:30:42 2022 -0600
+
+ [cff-common] Use byte_str_t() instead of Null(byte_str_t)
+
+ src/hb-ot-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 94f7a263228a120754ca31600cabb15de0652501
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 15:29:14 2022 -0600
+
+ [cff-common] Fix get_size() for Null object
+
+ The special-casing didn't make sense.
+
+ src/hb-ot-cff-common.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit c9cc7d5d21dc2550e820de841f5d24f5c94dcc7e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 15:27:27 2022 -0600
+
+ [cff-common] Inline once-used method in INDEX
+
+ src/hb-ot-cff-common.hh | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+commit 11482a3a3927eff8e408f825082f61a202c9be9b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 15:25:21 2022 -0600
+
+ [cff-common] Remove unused method from INDEX
+
+ src/hb-ot-cff-common.hh | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit d1bb3b08f65965bfc07b11becc3e344554c398cc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 15:23:59 2022 -0600
+
+ [cff-common] Hide more INDEX internals
+
+ src/hb-ot-cff-common.hh | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit d3b21387fde2923a624903915a58c9745d2602af
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 15:22:55 2022 -0600
+
+ [cff-common] Remove redundant operator implementation
+
+ src/hb-ot-cff-common.hh | 7 -------
+ 1 file changed, 7 deletions(-)
+
+commit a96b408d805c53c051764b66a7e19aa902c82546
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 9 15:20:16 2022 -0600
+
+ [cff-common] Hide INDEX internals
+
+ src/hb-ot-cff-common.hh | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 335b1d83cf61d1d712e9343a2217594f37018880
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 6 13:37:11 2022 -0600
+
+ [cff-common] No need to check max-offset in INDEX
+
+ The length_at() function makes sure out-of-range offsets
+ are discarded. We just need to check the last offset.
+
+ src/hb-ot-cff-common.hh | 19 ++++---------------
+ 1 file changed, 4 insertions(+), 15 deletions(-)
+
+commit b051f3fa8388d25c7023a7f48dfea415bde1c94c
+Author: Garret Rieger <grieger@google.com>
+Date: Thu May 5 23:27:34 2022 +0000
+
+ [subset] Fix cpal subsetting when there are partial palette overlaps.
+
+ The existing code doesn't correctly handle the case where palettes partially overlap in the color record array. This changes the subsetting to only share entries in the color record array when palettes have the same first color index. Partially overlapping palettes will be converted to disjoint segments in the color record array.
+
+ Updates one of the color tests to use multiple palettes.
+
+ Also fixes fuzzer: https://oss-fuzz.com/testcase-detail/5568200165687296.
+
+ src/hb-ot-color-cpal-table.hh | 60 +++++++++++++--------
+ ...ase-minimized-hb-subset-fuzzer-5568200165687296 | Bin 0 -> 220551 bytes
+ .../colr_with_components/colr-table.default.6B.ttf | Bin 4260 -> 4320 bytes
+ .../colr-table.drop-hints-retain-gids.6B.ttf | Bin 4984 -> 5044 bytes
+ .../colr-table.drop-hints.6B.ttf | Bin 4260 -> 4320 bytes
+ .../colr-table.retain-gids.6B.ttf | Bin 4984 -> 5044 bytes
+ test/subset/data/fonts/colr-table.ttf | Bin 26952 -> 27328 bytes
+ 7 files changed, 37 insertions(+), 23 deletions(-)
+
+commit 2884eb97bf448448c8c06f51e1a60acbff33bcbf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 6 12:54:02 2022 -0600
+
+ [cff-common] Remove special-casing of count=0 in INDEX serialize
+
+ The generic code-path now can handle count=0.
+
+ src/hb-ot-cff-common.hh | 15 +++------------
+ 1 file changed, 3 insertions(+), 12 deletions(-)
+
+commit fc7f51aecea6b7a66772d4f759f52447f34197f1
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 6 12:53:19 2022 -0600
+
+ [cff-common] Reduce iterator calls
+
+ src/hb-ot-cff-common.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit c857b8e3c642476aedea634c294ee101d6ce39f3
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 6 12:50:37 2022 -0600
+
+ [cff-common] Set INDEX min_size to 2
+
+ That is what it is, for an empty INDEX.
+
+ src/hb-ot-cff-common.hh | 21 ++++++++++++---------
+ 1 file changed, 12 insertions(+), 9 deletions(-)
+
+commit dd71d2c1c30ca85ddd7b1d7e3a9e2bbdacd6ae7a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 6 13:02:26 2022 -0600
+
+ [gvar] Protect against offset underflow
+
+ src/hb-ot-var-gvar-table.hh | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 9a6dabd61a1af848abbab21b0152e58875604a37
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 6 12:01:37 2022 -0600
+
+ [gvar] Remove sanitize check for data array
+
+ We are not checking in sanitize that offset array is ascending,
+ so this check was bogus.
+
+ src/hb-ot-var-gvar-table.hh | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit 38478d1061d4971c6f10910db1b8988aab900bcf
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 6 12:00:01 2022 -0600
+
+ [gvar] DEFINE_SIZE_ARRAY instead of DEFINE_SIZE_MIN
+
+ src/hb-ot-var-gvar-table.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 90d278c92e2ef076d2b239fed56a9dc11f4b6c12
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 6 11:58:53 2022 -0600
+
+ [gvar] Remove requirement that num_glyphs matches the font's
+
+ src/hb-ot-var-gvar-table.hh | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit ca8a0f3ea32af8fdaf2f99ad87a43e82be854f62
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri May 6 11:54:38 2022 -0600
+
+ [gvar] Protect against out-of-range access
+
+ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=47281
+ Fixes https://oss-fuzz.com/testcase-detail/5508865908670464
+
+ src/hb-ot-var-gvar-table.hh | 5 ++++-
+ ...usterfuzz-testcase-hb-subset-fuzzer-5508865908670464 | Bin 0 -> 17004 bytes
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+commit f10ddb8dd870fd691c8876c1c7151e607aab0625
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 5 11:21:24 2022 -0600
+
+ [cmap] Use -1 as Unicode sentinel, not U+FFFF in Format12 serialize
+
+ src/hb-ot-cmap-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 8a19968c8b8f8118e6247489a65edfb707bc838e
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 5 11:17:23 2022 -0600
+
+ [cmap] Use iterator bool operator
+
+ src/hb-ot-cmap-table.hh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 8bfeea482838a0c4f678c7f666f4520f4f2e8dd9
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 5 10:48:24 2022 -0600
+
+ [subset] Compute set max using previous()
+
+ src/hb-subset-plan.cc | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+commit 00cb8c629d8f5615d316ac6541d6652dfa2d3145
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 5 10:33:50 2022 -0600
+
+ [subset] Don't go into glyf table if it's empty
+
+ src/hb-ot-glyf-table.hh | 2 ++
+ src/hb-subset-plan.cc | 17 ++++++++++-------
+ 2 files changed, 12 insertions(+), 7 deletions(-)
+
+commit 4fe69bc41327596af540a2f683062b41a4f37f45
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu May 5 10:19:16 2022 -0600
+
+ [subset] Use del_range in _remove_invalid_gids
+
+ src/hb-subset-plan.cc | 9 ++-------
+ 1 file changed, 2 insertions(+), 7 deletions(-)
+
+commit 2a42edccbe55ede9ed7bbf643b7bec41698078ed
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 4 17:06:18 2022 -0600
+
+ [subset] Cosmetic; use set bulk array population instead of for loop
+
+ src/hb-subset-plan.cc | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+commit bc5129d7fa6fae7ce4c653b699944dd9416eca68
+Author: Garret Rieger <grieger@google.com>
+Date: Wed May 4 22:16:03 2022 +0000
+
+ [perf] use option_t in subset benchmark to select between glyphs and codepoint subset.
+
+ perf/benchmark-subset.cc | 134 ++++++++++++++++++++++-------------------------
+ 1 file changed, 62 insertions(+), 72 deletions(-)
+
+commit 43938ecdc2b5cda45f9499f8c3360a0a3ac0842b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 4 16:59:28 2022 -0600
+
+ [subset] Remove outdated comment
+
+ I tried something like that. It was slower because of the allocations.
+
+ src/hb-subset-plan.cc | 3 ---
+ 1 file changed, 3 deletions(-)
+
+commit 6212856ce80d1cbdb5ebbd6d8f899e2b1e45d611
+Author: Garret Rieger <grieger@google.com>
+Date: Wed May 4 22:16:03 2022 +0000
+
+ [perf] benchmark subsetting via glyphs.
+
+ perf/benchmark-subset.cc | 78 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 78 insertions(+)
+
+commit 6829dd30ad9058170674760f3795fcafe3ed6f27
+Merge: 052812b6b 50db78ba8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 4 16:49:45 2022 -0600
+
+ Merge pull request #3562 from harfbuzz/subset-cmap-no-qsort
+
+ [subset] In cmap planning, remove a qsort()
+
+commit 50db78ba834b35b96a808c07e550a50b3e1fa5ec
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 4 15:48:18 2022 -0600
+
+ [subset] In cmap planning, remove a qsort()
+
+ src/hb-subset-plan.cc | 30 ++++++++++--------------------
+ 1 file changed, 10 insertions(+), 20 deletions(-)
+
+commit 052812b6ba424b4be677d60a722375f69decb89f
+Merge: f67e6bf79 7cb36e422
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed May 4 15:38:30 2022 -0600
+
+ Merge pull request #3561 from googlefonts/cmap_opt
+
+ [subset] Further cmap subsetting speed optimizations
+
+commit 7cb36e422218305329102849c156ab94db91cbef
+Author: Garret Rieger <grieger@google.com>
+Date: Wed May 4 21:22:26 2022 +0000
+
+ [subset] Re-introduce size threshold in choosing unicode collection method.
+
+ Threshold is needed since the unicodes set might be an inverted set.
+
+ src/hb-subset-plan.cc | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+commit 42c54eba839f510c885fe1a63732b0f706af1bff
+Author: Garret Rieger <grieger@google.com>
+Date: Wed May 4 20:21:43 2022 +0000
+
+ [subset] Presize unicode to gid list to unicodes + glyphs size.
+
+ src/hb-subset-plan.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 7c7c01d28cee221f1c64684539c8e6160f144f61
+Author: Garret Rieger <grieger@google.com>
+Date: Tue May 3 22:40:56 2022 +0000
+
+ [subset] Remove switch to alternate unicode collection at large subset sizes.
+
+ Benchmarks show that the first path is always faster even at large subset sizes:
+
+ BM_subset_codepoints/subset_roboto/10_median +0.0324 +0.0325 0 0 0 0
+ BM_subset_codepoints/subset_roboto/64_median +0.0253 +0.0255 0 1 0 1
+ BM_subset_codepoints/subset_roboto/512_median +0.0126 +0.0128 1 1 1 1
+ BM_subset_codepoints/subset_roboto/4000_median +0.0500 +0.0491 6 7 6 7
+ BM_subset_codepoints/subset_amiri/10_median +0.0338 +0.0332 1 1 1 1
+ BM_subset_codepoints/subset_amiri/64_median +0.0238 +0.0234 1 1 1 1
+ BM_subset_codepoints/subset_amiri/512_median +0.0066 +0.0063 8 8 8 8
+ BM_subset_codepoints/subset_amiri/4000_median -0.0011 -0.0012 13 13 13 13
+ BM_subset_codepoints/subset_noto_nastaliq_urdu/10_median +0.0226 +0.0226 0 0 0 0
+ BM_subset_codepoints/subset_noto_nastaliq_urdu/64_median +0.0047 +0.0044 20 20 20 20
+ BM_subset_codepoints/subset_noto_nastaliq_urdu/512_median +0.0022 +0.0021 165 166 165 166
+ BM_subset_codepoints/subset_noto_nastaliq_urdu/1000_median -0.0021 -0.0023 166 166 166 165
+ BM_subset_codepoints/subset_noto_devangari/10_median +0.0054 +0.0054 0 0 0 0
+ BM_subset_codepoints/subset_noto_devangari/64_median +0.0024 +0.0019 0 0 0 0
+ BM_subset_codepoints/subset_noto_devangari/512_median +0.0089 +0.0090 5 5 5 5
+ BM_subset_codepoints/subset_noto_devangari/1000_median -0.0028 -0.0019 5 5 5 5
+ BM_subset_codepoints/subset_mplus1p/10_median +0.0001 +0.0002 0 0 0 0
+ BM_subset_codepoints/subset_mplus1p/64_median +0.0073 +0.0075 1 1 1 1
+ BM_subset_codepoints/subset_mplus1p/512_median +0.0034 +0.0034 1 1 1 1
+ BM_subset_codepoints/subset_mplus1p/4096_median -0.1248 -0.1248 7 6 7 6
+ BM_subset_codepoints/subset_mplus1p/10000_median -0.0885 -0.0885 13 12 13 12
+ BM_subset_codepoints/subset_notocjk/10_median +0.0031 +0.0032 2 2 2 2
+ BM_subset_codepoints/subset_notocjk/64_median -0.0010 -0.0010 2 2 2 2
+ BM_subset_codepoints/subset_notocjk/512_median -0.0023 -0.0023 9 9 9 9
+ BM_subset_codepoints/subset_notocjk/4096_median -0.1725 -0.1726 28 23 28 23
+ BM_subset_codepoints/subset_notocjk/32768_median -0.0277 -0.0287 140 137 140 136
+ BM_subset_codepoints/subset_notocjk/100000_median -0.0929 -0.0926 162 147 162 147
+
+ src/hb-subset-plan.cc | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+commit f0c04114bc229b3b519ed2242689959ccec64098
+Author: Garret Rieger <grieger@google.com>
+Date: Tue May 3 22:02:59 2022 +0000
+
+ [subset] Embed unicode to gid list vector in subset plan.
+
+ src/hb-ot-cmap-table.hh | 2 +-
+ src/hb-subset-plan.cc | 35 ++++++++++++++++-------------------
+ src/hb-subset-plan.hh | 2 +-
+ 3 files changed, 18 insertions(+), 21 deletions(-)
+
+commit f67e6bf79cd1ac3892a2d6dfe6e479483290bd41
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 16:59:48 2022 -0600
+
+ [perf/benchmark-font] Add benchmark for glyph_h_advance
+
+ perf/benchmark-font.cc | 26 +++++++++++++++++++++++---
+ 1 file changed, 23 insertions(+), 3 deletions(-)
+
+commit 1c0a3d4d16b3ff6864c701fc94aa6878ea82a5c4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 16:50:54 2022 -0600
+
+ [perf/benchmark-font] Add a couple Noto fonts
+
+ perf/benchmark-font.cc | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 15fa8afb217582bce4d360c43ad7674861dc1278
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 16:46:41 2022 -0600
+
+ Add fast-path for big-endian 32-bit byteswap
+
+ Speeds up cmap format-12 decoding by some 40% as measured by
+ the newly added test in perf/benchmark-font!
+
+ src/hb-algs.hh | 24 ++++++++++++++++++++----
+ 1 file changed, 20 insertions(+), 4 deletions(-)
+
+commit 3fff2e9182fc6c3cd8ade0336fa67e71967e82c5
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 16:31:59 2022 -0600
+
+ [perf/benchmark-font] Cosmetic
+
+ perf/benchmark-font.cc | 2 +-
+ src/hb-ot-cmap-table.hh | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit 307d2d8bb6e74ad974207d3b9f706568a6a87e75
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 16:30:22 2022 -0600
+
+ [cmap] Sprinkle some 'unlikely's
+
+ src/hb-ot-cmap-table.hh | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+commit 85ec5cbcefeb2361536031f2e05518c2d817d98a
+Author: Garret Rieger <grieger@google.com>
+Date: Mon May 2 22:29:43 2022 +0000
+
+ [subset] In _populate_unicodes_to_retain populate unicodes in order.
+
+ Allows the set insert to take advantage of page lookup cache.
+
+ src/hb-subset-plan.cc | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+commit 0d1f8dcaf3a45dc8ed61dde370df0874af008870
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 16:18:53 2022 -0600
+
+ [perf/benchmark-font] Actually make nominal_glyph bench work
+
+ perf/benchmark-font.cc | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+commit 6cf69d10e710cfa7282509c2a43e12618d4673bc
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 16:07:32 2022 -0600
+
+ [perf/benchmark-font] Add back testing of is_variable
+
+ perf/benchmark-font.cc | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+commit 3aa2ff7988583a7c078032e762cd2bde006fc896
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 16:01:22 2022 -0600
+
+ [perf/benchmark-font] Fix build without freetype
+
+ perf/benchmark-font.cc | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+commit 58a0988b576f915a21f4171f71d6d2603d6f3414
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 15:57:19 2022 -0600
+
+ [perf/benchmark-font] Benchmark get_nominal_glyph
+
+ perf/benchmark-font.cc | 37 ++++++++++++++++++++++++++++++-------
+ 1 file changed, 30 insertions(+), 7 deletions(-)
+
+commit 03f16fab585e57f184642398172bb2e17aa57635
+Merge: a4522df37 6d29903e8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 15:44:41 2022 -0600
+
+ Merge pull request #3560 from harfbuzz/perf-cleanup
+
+ Perf cleanup
+
+commit 088133d939d8bc4ce3d97eed7d835c1831e68766
+Author: Garret Rieger <grieger@google.com>
+Date: Mon May 2 21:29:16 2022 +0000
+
+ [subset] cache cp to new gid list in subset plan.
+
+ This avoids having to recompute the ordered list multiple times during cmap generation.
+
+ src/hb-ot-cmap-table.hh | 9 +--------
+ src/hb-subset-plan.cc | 30 ++++++++++++++++++++++++++++++
+ src/hb-subset-plan.hh | 1 +
+ 3 files changed, 32 insertions(+), 8 deletions(-)
+
+commit 6d29903e86d1f6b0fe7ca884a071d047f0ee130b
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 14:03:15 2022 -0600
+
+ [perf/benchmark-font] Parametrize test
+
+ perf/benchmark-font.cc | 115 +++++++++++++++++++++++++-----------------------
+ perf/benchmark-shape.cc | 2 +
+ 2 files changed, 63 insertions(+), 54 deletions(-)
+
+commit 636c90e81c2eb9a907a1c14d0f3450902d95f65a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 13:41:49 2022 -0600
+
+ [perf/perf] Rename to benchmark-font
+
+ perf/Makefile.am | 3 +-
+ perf/{perf-draw.hh => benchmark-font.cc} | 0
+ perf/meson.build | 7 ++--
+ perf/perf-extents.hh | 65 --------------------------------
+ perf/perf.cc | 3 --
+ 5 files changed, 4 insertions(+), 74 deletions(-)
+
+commit 036d03d2e91fc20133150696c405d3281326a552
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 13:39:54 2022 -0600
+
+ [perf/perf] Move all logic to perf-draw, for now
+
+ To be renamed.
+
+ perf/Makefile.am | 1 -
+ perf/perf-draw.hh | 124 +++++++++++++++++++++++++++++++++++++++++-------------
+ perf/perf.cc | 10 -----
+ 3 files changed, 94 insertions(+), 41 deletions(-)
+
+commit 746c3c03c5017b4e1404c65a04a5a6122a6cd831
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 13:26:41 2022 -0600
+
+ [perf/perf] Remove ttf-parser backend
+
+ perf/meson.build | 11 +------
+ perf/perf-draw.hh | 91 +++++++++++-----------------------------------------
+ perf/perf-extents.hh | 50 ++++-------------------------
+ perf/perf.cc | 2 +-
+ 4 files changed, 28 insertions(+), 126 deletions(-)
+
+commit 4aaa0af7d99f7a44a02542ab8a8d467e3f6a3f64
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Mon May 2 13:06:27 2022 -0600
+
+ [perf/perf] Rely on hb-draw to measure ft performance
+
+ perf/perf-draw.hh | 50 +++++++-------------------------------------------
+ 1 file changed, 7 insertions(+), 43 deletions(-)
+
+commit a4522df378259653f6cdda535980c4acee4d3021
+Merge: 4de5352a3 6922a2561
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri Apr 29 18:34:00 2022 -0600
+
+ Merge pull request #3558 from harfbuzz/set-optimize
+
+ [perf] hb_set_t optimizations and perf suite improvements
+
+commit 6922a2561f75468c328fa158fef289a0b4156d87
+Author: Garret Rieger <grieger@google.com>
+Date: Fri Apr 29 23:30:32 2022 +0000
+
+ [subset] Change serialize_rangeoffset_glyid back to using iterator.
+
+ src/hb-ot-cmap-table.hh | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+commit c66fd50c269a7ab8ab22c404354c783ab5419bcc
+Author: Garret Rieger <grieger@google.com>
+Date: Fri Apr 29 23:18:53 2022 +0000
+
+ [subset] in cmap4 serialization save cp to gid iter to memory.
+
+ Iterator accesses are slow and it's iterated multiple times.
+
+ src/hb-ot-cmap-table.hh | 21 +++++++++++++--------
+ 1 file changed, 13 insertions(+), 8 deletions(-)
+
+commit 17b98563dc426674d633b79194ce591c8dd38e01
+Author: Garret Rieger <grieger@google.com>
+Date: Fri Apr 29 22:49:02 2022 +0000
+
+ [subset] In cmap4 serialization reduce unnessecary calls into the iterator.
+
+ Gives ~20% speedup for large subsets.
+
+ src/hb-ot-cmap-table.hh | 30 +++++++++++++++++-------------
+ 1 file changed, 17 insertions(+), 13 deletions(-)
+
+commit 5e241094bfa72840a4142c33264d128b60f12330
+Author: Garret Rieger <grieger@google.com>
+Date: Fri Apr 29 22:44:43 2022 +0000
+
+ [subset] In unicodes cache cleanup if set insert fails.
+
+ src/hb-ot-cmap-table.hh | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+commit 217d38dfc7b7b1152b74ceb46472bf6a05d35f1a
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri Apr 29 16:18:17 2022 -0600
+
+ Try to fix distcheck
+
+ Makefile.am | 15 +--------------
+ configure.ac | 1 +
+ perf/Makefile.am | 24 ++++++++++++++++++++++++
+ 3 files changed, 26 insertions(+), 14 deletions(-)
+
+commit a424a92ce5e47b35d3128be1a612d3130c4c85b0
+Author: Garret Rieger <grieger@google.com>
+Date: Fri Apr 29 22:14:03 2022 +0000
+
+ [subset] s/void */intptr_t.
+
+ src/hb-ot-cmap-table.hh | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+commit aad67f5629b1407df1b3152dfce0aefafbfb4132
+Author: Garret Rieger <grieger@google.com>
+Date: Fri Apr 29 22:01:06 2022 +0000
+
+ [subset] cache results of collect_unicodes.
+
+ src/hb-ot-cmap-table.hh | 45 +++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 37 insertions(+), 8 deletions(-)
+
+commit 35681b3edb79b1286f1aa0ece2f6ae99e0363190
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri Apr 29 16:02:55 2022 -0600
+
+ [benchmark-shape] Break lines and shape separately
+
+ perf/benchmark-shape.cc | 23 +++++++++++++++++------
+ 1 file changed, 17 insertions(+), 6 deletions(-)
+
+commit be1ac9c57232317647e59983e72b6a86f93151a2
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri Apr 29 15:55:19 2022 -0600
+
+ [benchmark-shape] Data-driven test sets
+
+ perf/benchmark-shape.cc | 78 ++++++++++++++++++++++++++++---------------------
+ 1 file changed, 44 insertions(+), 34 deletions(-)
+
+commit ae3efc64248f46478fe9ad3863a5dfb0a362fe5f
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri Apr 29 15:37:11 2022 -0600
+
+ [perf] Spawn off benchmark-shape from perf runner
+
+ perf/{perf-shaping.hh => benchmark-shape.cc} | 2 ++
+ perf/meson.build | 10 ++++++++++
+ perf/perf.cc | 1 -
+ 3 files changed, 12 insertions(+), 1 deletion(-)
+
+commit 5f43ce825afbedb1edbbc6610d1c017aa0f5fe27
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri Apr 29 13:37:46 2022 -0600
+
+ [benchmark-set] Split SetLookup into an ordered and random version
+
+ perf/benchmark-set.cc | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+commit ae9c7b861b257897a7ff0044d38e70f95df3eec7
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri Apr 29 13:39:04 2022 -0600
+
+ [benchmark-set] At least increase needle by one in lookup benchmark
+
+ perf/benchmark-set.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 68a9b83d157c2c2ece2c49732f5bf68d843a77a8
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri Apr 29 13:27:42 2022 -0600
+
+ [benchmark-set] At least increase needle by one in lookup benchmark
+
+ perf/benchmark-set.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit b4236b7de6bb2823a4561357342309b0f6d7d264
+Author: Garret Rieger <grieger@google.com>
+Date: Fri Apr 29 19:21:13 2022 +0000
+
+ [subset] Optimize Cmap4 collect_unicodes.
+
+ Use set add_range() instead of individual add() calls.
+
+ src/hb-ot-cmap-table.hh | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+commit 5866ec05f5a2a613501095e1de64d641ad898021
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri Apr 29 13:14:41 2022 -0600
+
+ [benchmark-map] Remove rand() overhead from benchmark
+
+ perf/benchmark-map.cc | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+commit 067225a86d4309020b950661ef9de6cb0c51eb98
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri Apr 29 13:04:36 2022 -0600
+
+ [set] Optimize const page_for() using last_page_lookup caching
+
+ Similar to previous commit.
+
+ This speeds up SetLookup benchmark by 50%, but that's because that
+ lookup always hits the same page...
+
+ src/hb-bit-set.hh | 24 +++++++++++++++++++-----
+ 1 file changed, 19 insertions(+), 5 deletions(-)
+
+commit c283e41ce39bb3740417bed4f240cf625fb38cd4
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri Apr 29 12:45:48 2022 -0600
+
+ [set] Optimize non-const page_for() using last_page_lookup caching
+
+ This speeds up SetOrderedInsert tests by 15 to 40 percent, and the
+ subset_mplus1p benchmarks by 9 to 27 percent.
+
+ src/hb-bit-set.hh | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+commit dd005911b955da49a11aa755acb9addc0c8a2a24
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Fri Apr 29 12:23:53 2022 -0600
+
+ [benchmark-set] Reduce lookup benchmark overhead
+
+ Turnsout 90% was overhead... Now lookup is in the 4ns ballpark.
+
+ perf/benchmark-set.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 4de5352a3d4f501b68907fa419a4fed70676e720
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Thu Apr 28 14:40:33 2022 -0600
+
+ [test] Add test
+
+ From https://github.com/harfbuzz/harfbuzz/issues/3545
+
+ Dropped the CFF table.
+
+ .../fonts/a59fd13f1525a91cbe529c882e93d9d1fbb80463.ttf | Bin 0 -> 1180 bytes
+ test/shape/data/in-house/tests/context-matching.tests | 1 +
+ 2 files changed, 1 insertion(+)
+
+commit d8292b8446b7875281a0d6fc8cb90e96b2f8d156
+Author: Behdad Esfahbod <behdad@behdad.org>
+Date: Wed Apr 27 12:38:35 2022 -0600
+
+ [CFF] Fix parsing of empty Index
+
+ https://github.com/harfbuzz/harfbuzz/issues/3545#issuecomment-1111047941
+
+ src/hb-ot-cff-common.hh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 6454cec085ba51cefcd12b1f8027bc4a647347d5
+Author: David Corbett <corbett.dav@northeastern.edu>
+Date: Sun Apr 24 11:10:17 2022 -0400
+
+ [USE] Classify U+10A38 as CONS_MOD_BELOW
+
+ src/gen-use-table.py | 3 +++
+ src/hb-ot-shape-complex-use-table.hh | 2 +-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
commit f7aee78e90bc53b3a95eb56d7550c9effe569ea2
Author: Khaled Hosny <khaled@aliftype.com>
Date: Sun Apr 24 05:47:57 2022 +0200
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/Makefile.am b/Build/source/libs/harfbuzz/harfbuzz-src/Makefile.am
index 3055e5a77f1..42015295344 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/Makefile.am
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/Makefile.am
@@ -4,7 +4,7 @@ NULL =
ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = src util test docs
+SUBDIRS = src util test perf docs
EXTRA_DIST = \
autogen.sh \
@@ -26,19 +26,6 @@ EXTRA_DIST = \
subprojects/ragel.wrap \
subprojects/packagefiles/ragel/meson.build \
subprojects/ttf-parser.wrap \
- perf/meson.build \
- perf/perf-draw.hh \
- perf/perf-extents.hh \
- perf/perf-shaping.hh \
- perf/perf.cc \
- perf/fonts/Amiri-Regular.ttf \
- perf/fonts/NotoNastaliqUrdu-Regular.ttf \
- perf/fonts/NotoSansDevanagari-Regular.ttf \
- perf/fonts/Roboto-Regular.ttf \
- perf/texts/en-thelittleprince.txt \
- perf/texts/en-words.txt \
- perf/texts/fa-monologue.txt \
- perf/texts/fa-thelittleprince.txt \
mingw-configure.sh \
$(NULL)
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/NEWS b/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
index 0559840cf35..e52dc21ba79 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/NEWS
@@ -1,3 +1,20 @@
+Overview of changes leading to 4.3.0
+Friday, May 20, 2022
+====================================
+- Major speed up in loading and subsetting fonts, especially in
+ handling CFF table. Subsetting some fonts is now 3 times faster.
+ (Behdad Esfahbod, Garret Rieger)
+- Speed up blending CFF2 table. (Behdad Esfahbod)
+- Speed up hb_ot_tags_from_language(). (Behdad Esfahbod, David Corbett)
+- Fix USE classification of U+10A38 to fix multiple marks on single Kharoshthi
+ base. (David Corbett)
+- Fix parsing of empty CFF Index. (Behdad Esfahbod)
+- Fix subsetting CPAL table with partial palette overlaps. (Garret Rieger)
+
+- New API
++hb_map_is_equal() (Behdad Esfahbod)
+
+
Overview of changes leading to 4.2.1
Sunday, April 24, 2022
====================================
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac b/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac
index c353567d4bb..ae7b0b5b30d 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/configure.ac
@@ -1,6 +1,6 @@
AC_PREREQ([2.64])
AC_INIT([HarfBuzz],
- [4.2.1],
+ [4.3.0],
[https://github.com/harfbuzz/harfbuzz/issues/new],
[harfbuzz],
[http://harfbuzz.org/])
@@ -437,6 +437,7 @@ test/shape/data/text-rendering-tests/Makefile
test/subset/Makefile
test/subset/data/Makefile
test/subset/data/repack_tests/Makefile
+perf/Makefile
docs/Makefile
docs/version.xml
])
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/meson.build b/Build/source/libs/harfbuzz/harfbuzz-src/meson.build
index ed59489bea7..6e9d7693a5d 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/meson.build
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/meson.build
@@ -1,6 +1,6 @@
project('harfbuzz', 'c', 'cpp',
meson_version: '>= 0.55.0',
- version: '4.2.1',
+ version: '4.3.0',
default_options: [
'cpp_rtti=false', # Just to support msvc, we are passing -fno-exceptions also anyway
'cpp_std=c++11',
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py
index f8fb05f1133..b8718360418 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-tag-table.py
@@ -894,7 +894,6 @@ print ()
print ('#ifndef HB_OT_TAG_TABLE_HH')
print ('#define HB_OT_TAG_TABLE_HH')
print ()
-print ('static const LangTag ot_languages[] = {')
def hb_tag (tag):
"""Convert a tag to ``HB_TAG`` form.
@@ -944,33 +943,35 @@ def get_matching_language_name (intersection, candidates):
def same_tag (bcp_47_tag, ot_tags):
return len (bcp_47_tag) == 3 and len (ot_tags) == 1 and bcp_47_tag == ot_tags[0].lower ()
-for language, tags in sorted (ot.from_bcp_47.items ()):
- if language == '' or '-' in language:
- continue
- commented_out = same_tag (language, tags)
- for i, tag in enumerate (tags, start=1):
- print ('%s{\"%s\",\t%s},' % ('/*' if commented_out else ' ', language, hb_tag (tag)), end='')
- if commented_out:
- print ('*/', end='')
- print ('\t/* ', end='')
- bcp_47_name = bcp_47.names.get (language, '')
- bcp_47_name_candidates = bcp_47_name.split ('\n')
- ot_name = ot.names[tag]
- scope = bcp_47.scopes.get (language, '')
- if tag == DEFAULT_LANGUAGE_SYSTEM:
- write (f'{bcp_47_name_candidates[0]}{scope} != {ot.names[language.upper ()]}')
- else:
- intersection = language_name_intersection (bcp_47_name, ot_name)
- if not intersection:
- write ('%s%s -> %s' % (bcp_47_name_candidates[0], scope, ot_name))
+for language_len in (2, 3):
+ print ('static const LangTag ot_languages%d[] = {' % language_len)
+ for language, tags in sorted (ot.from_bcp_47.items ()):
+ if language == '' or '-' in language:
+ continue
+ if len(language) != language_len: continue
+ commented_out = same_tag (language, tags)
+ for i, tag in enumerate (tags, start=1):
+ print ('%s{%s,\t%s},' % ('/*' if commented_out else ' ', hb_tag (language), hb_tag (tag)), end='')
+ if commented_out:
+ print ('*/', end='')
+ print ('\t/* ', end='')
+ bcp_47_name = bcp_47.names.get (language, '')
+ bcp_47_name_candidates = bcp_47_name.split ('\n')
+ ot_name = ot.names[tag]
+ scope = bcp_47.scopes.get (language, '')
+ if tag == DEFAULT_LANGUAGE_SYSTEM:
+ write (f'{bcp_47_name_candidates[0]}{scope} != {ot.names[language.upper ()]}')
else:
- name = get_matching_language_name (intersection, bcp_47_name_candidates)
- bcp_47.names[language] = name
- write ('%s%s' % (name if len (name) > len (ot_name) else ot_name, scope))
- print (' */')
-
-print ('};')
-print ()
+ intersection = language_name_intersection (bcp_47_name, ot_name)
+ if not intersection:
+ write ('%s%s -> %s' % (bcp_47_name_candidates[0], scope, ot_name))
+ else:
+ name = get_matching_language_name (intersection, bcp_47_name_candidates)
+ bcp_47.names[language] = name
+ write ('%s%s' % (name if len (name) > len (ot_name) else ot_name, scope))
+ print (' */')
+ print ('};')
+ print ()
print ('/**')
print (' * hb_ot_tags_from_complex_language:')
@@ -993,12 +994,12 @@ print ('\t\t\t\t unsigned int *count /* IN/OUT */,')
print ('\t\t\t\t hb_tag_t *tags /* OUT */)')
print ('{')
-def print_subtag_matches (subtag, new_line):
+def print_subtag_matches (subtag, string, new_line):
if subtag:
if new_line:
print ()
print ('\t&& ', end='')
- print ('subtag_matches (lang_str, limit, "-%s")' % subtag, end='')
+ print ('subtag_matches (%s, limit, "-%s", %i)' % (string, subtag, 1 + len (subtag)), end='')
complex_tags = collections.defaultdict (list)
for initial, group in itertools.groupby ((lt_tags for lt_tags in [
@@ -1009,6 +1010,24 @@ for initial, group in itertools.groupby ((lt_tags for lt_tags in [
key=lambda lt_tags: lt_tags[0].get_group ()):
complex_tags[initial] += group
+# Calculate the min length of the subtags outside the switch
+min_subtag_len = 100
+for initial, items in sorted (complex_tags.items ()):
+ if initial != 'und':
+ continue
+ for lt, tags in items:
+ if not tags:
+ continue
+ subtag_len = 0
+ subtag_len += 1 + len (lt.script) if lt.script is not None else 0
+ subtag_len += 1 + len (lt.region) if lt.region is not None else 0
+ subtag_len += 1 + len (lt.variant) if lt.variant is not None else 0
+ min_subtag_len = min(subtag_len, min_subtag_len)
+
+print (' if (limit - lang_str >= %d)' % (min_subtag_len + 2))
+print (' {')
+print (" const char *p = strchr (lang_str, '-');")
+print (" if (!p || p >= limit || limit - p < %i) goto out;" % min_subtag_len)
for initial, items in sorted (complex_tags.items ()):
if initial != 'und':
continue
@@ -1018,29 +1037,31 @@ for initial, items in sorted (complex_tags.items ()):
if lt.variant in bcp_47.prefixes:
expect (next (iter (bcp_47.prefixes[lt.variant])) == lt.language,
'%s is not a valid prefix of %s' % (lt.language, lt.variant))
- print (' if (', end='')
- print_subtag_matches (lt.script, False)
- print_subtag_matches (lt.region, False)
- print_subtag_matches (lt.variant, False)
+ print (' if (', end='')
+ print_subtag_matches (lt.script, 'p', False)
+ print_subtag_matches (lt.region, 'p', False)
+ print_subtag_matches (lt.variant, 'p', False)
print (')')
- print (' {')
- write (' /* %s */' % bcp_47.get_name (lt))
+ print (' {')
+ write (' /* %s */' % bcp_47.get_name (lt))
print ()
if len (tags) == 1:
- write (' tags[0] = %s; /* %s */' % (hb_tag (tags[0]), ot.names[tags[0]]))
+ write (' tags[0] = %s; /* %s */' % (hb_tag (tags[0]), ot.names[tags[0]]))
print ()
- print (' *count = 1;')
+ print (' *count = 1;')
else:
print (' hb_tag_t possible_tags[] = {')
for tag in tags:
write (' %s, /* %s */' % (hb_tag (tag), ot.names[tag]))
print ()
- print (' };')
- print (' for (i = 0; i < %s && i < *count; i++)' % len (tags))
- print (' tags[i] = possible_tags[i];')
- print (' *count = i;')
- print (' return true;')
- print (' }')
+ print (' };')
+ print (' for (i = 0; i < %s && i < *count; i++)' % len (tags))
+ print ('\ttags[i] = possible_tags[i];')
+ print (' *count = i;')
+ print (' return true;')
+ print (' }')
+print (' }')
+print ('out:')
print (' switch (lang_str[0])')
print (' {')
@@ -1067,10 +1088,10 @@ for initial, items in sorted (complex_tags.items ()):
if string_literal[-1] == '-':
print ('0 == strncmp (&lang_str[1], "%s", %i)' % (string_literal, len (string_literal)), end='')
else:
- print ('lang_matches (&lang_str[1], "%s")' % string_literal, end='')
- print_subtag_matches (script, True)
- print_subtag_matches (region, True)
- print_subtag_matches (lt.variant, True)
+ print ('lang_matches (&lang_str[1], limit, "%s", %i)' % (string_literal, len (string_literal)), end='')
+ print_subtag_matches (script, 'lang_str', True)
+ print_subtag_matches (region, 'lang_str', True)
+ print_subtag_matches (lt.variant, 'lang_str', True)
print (')')
print (' {')
write (' /* %s */' % bcp_47.get_name (lt))
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py
index 1c75584473d..48fd3889d38 100755
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/gen-use-table.py
@@ -377,6 +377,9 @@ def map_to_use(data):
if U in [0x11302, 0x11303, 0x114C1]: UIPC = Top
if 0x1CF8 <= U <= 0x1CF9: UIPC = Top
+ # TODO: https://github.com/harfbuzz/harfbuzz/issues/3550
+ if U == 0x10A38: UIPC = Bottom
+
# TODO: https://github.com/harfbuzz/harfbuzz/pull/982
# also https://github.com/harfbuzz/harfbuzz/issues/1012
if 0x1112A <= U <= 0x1112B: UIPC = Top
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh
index c40a55cd1fa..05b4df52f15 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-algs.hh
@@ -150,10 +150,26 @@ struct BEInt<Type, 4>
uint8_t ((V >> 16) & 0xFF),
uint8_t ((V >> 8) & 0xFF),
uint8_t ((V ) & 0xFF)} {}
- constexpr operator Type () const { return (v[0] << 24)
- + (v[1] << 16)
- + (v[2] << 8)
- + (v[3] ); }
+
+ struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
+ constexpr operator Type () const {
+#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
+ defined(__BYTE_ORDER) && \
+ (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
+ /* Spoon-feed the compiler a big-endian integer with alignment 1.
+ * https://github.com/harfbuzz/harfbuzz/pull/1398 */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ return __builtin_bswap32 (((packed_uint32_t *) this)->v);
+#else /* __BYTE_ORDER == __BIG_ENDIAN */
+ return ((packed_uint32_t *) this)->v;
+#endif
+#else
+ return (v[0] << 24)
+ + (v[1] << 16)
+ + (v[2] << 8)
+ + (v[3] );
+#endif
+ }
private: uint8_t v[4];
};
@@ -213,11 +229,11 @@ HB_FUNCOBJ (hb_bool);
template <typename T>
static inline
-T hb_coerce (const T v) { return v; }
+constexpr T hb_coerce (const T v) { return v; }
template <typename T, typename V,
hb_enable_if (!hb_is_same (hb_decay<T>, hb_decay<V>) && std::is_pointer<V>::value)>
static inline
-T hb_coerce (const V v) { return *v; }
+constexpr T hb_coerce (const V v) { return *v; }
struct
{
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh
index 1d1476d7cda..1963698cf7f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-array.hh
@@ -346,7 +346,7 @@ struct hb_sorted_array_t :
unsigned int i;
return bfind (x, &i) ? &this->arrayZ[i] : not_found;
}
- template <typename T>
+ template <typename T, typename ...Ts>
const Type *bsearch (const T &x, const Type *not_found = nullptr) const
{
unsigned int i;
@@ -384,15 +384,16 @@ struct hb_sorted_array_t :
}
return false;
}
- template <typename T>
- bool bsearch_impl (const T &x, unsigned *pos) const
+ template <typename T, typename ...Ts>
+ bool bsearch_impl (const T &x, unsigned *pos, Ts... ds) const
{
return hb_bsearch_impl (pos,
x,
this->arrayZ,
this->length,
sizeof (Type),
- _hb_cmp_method<T, Type>);
+ _hb_cmp_method<T, Type, Ts...>,
+ ds...);
}
};
template <typename T> inline hb_sorted_array_t<T>
@@ -403,7 +404,7 @@ hb_sorted_array (T (&array_)[length_])
{ return hb_sorted_array_t<T> (array_); }
template <typename T>
-bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
+inline bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
{
if (o.length != this->length) return false;
for (unsigned int i = 0; i < this->length; i++) {
@@ -411,8 +412,18 @@ bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
}
return true;
}
-
-/* TODO Specialize operator== for hb_bytes_t and hb_ubytes_t. */
+template <>
+inline bool hb_array_t<const char>::operator == (const hb_array_t<const char> &o) const
+{
+ if (o.length != this->length) return false;
+ return 0 == hb_memcmp (arrayZ, o.arrayZ, length);
+}
+template <>
+inline bool hb_array_t<const unsigned char>::operator == (const hb_array_t<const unsigned char> &o) const
+{
+ if (o.length != this->length) return false;
+ return 0 == hb_memcmp (arrayZ, o.arrayZ, length);
+}
template <>
inline uint32_t hb_array_t<const char>::hash () const {
@@ -421,7 +432,6 @@ inline uint32_t hb_array_t<const char>::hash () const {
current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u);
return current;
}
-
template <>
inline uint32_t hb_array_t<const unsigned char>::hash () const {
uint32_t current = 0;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh
index a9e1278de70..5b313bf59c7 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bimap.hh
@@ -39,6 +39,12 @@ struct hb_bimap_t
back_map.reset ();
}
+ void resize (unsigned pop)
+ {
+ forw_map.resize (pop);
+ back_map.resize (pop);
+ }
+
bool in_error () const { return forw_map.in_error () || back_map.in_error (); }
void set (hb_codepoint_t lhs, hb_codepoint_t rhs)
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh
index 97598366544..cbe918ee401 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-page.hh
@@ -40,11 +40,18 @@ struct hb_bit_page_t
bool is_empty () const
{
- for (unsigned int i = 0; i < len (); i++)
+ for (unsigned i = 0; i < len (); i++)
if (v[i])
return false;
return true;
}
+ uint32_t hash () const
+ {
+ uint32_t h = 0;
+ for (unsigned i = 0; i < len (); i++)
+ h = h * 31 + hb_hash (v[i]);
+ return h;
+ }
void add (hb_codepoint_t g) { elt (g) |= mask (g); }
void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh
index 4a4ce340537..caea47d8d3f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set-invertible.hh
@@ -38,10 +38,10 @@ struct hb_bit_set_invertible_t
bool inverted = false;
hb_bit_set_invertible_t () = default;
- hb_bit_set_invertible_t (hb_bit_set_invertible_t& o) = default;
- hb_bit_set_invertible_t (hb_bit_set_invertible_t&& o) = default;
+ hb_bit_set_invertible_t (const hb_bit_set_invertible_t& o) = default;
+ hb_bit_set_invertible_t (hb_bit_set_invertible_t&& other) : hb_bit_set_invertible_t () { hb_swap (*this, other); }
hb_bit_set_invertible_t& operator= (const hb_bit_set_invertible_t& o) = default;
- hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& o) = default;
+ hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& other) { hb_swap (*this, other); return *this; }
friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b)
{
if (likely (!a.s.successful || !b.s.successful))
@@ -56,6 +56,7 @@ struct hb_bit_set_invertible_t
bool in_error () const { return s.in_error (); }
explicit operator bool () const { return !is_empty (); }
+ void alloc (unsigned sz) { s.alloc (sz); }
void reset ()
{
s.reset ();
@@ -79,6 +80,8 @@ struct hb_bit_set_invertible_t
next (&v);
return v == INVALID;
}
+ uint32_t hash () const { return s.hash () ^ inverted; }
+
hb_codepoint_t get_min () const
{
hb_codepoint_t v = INVALID;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh
index fcaff9f3be3..11a4359dc90 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-bit-set.hh
@@ -97,6 +97,13 @@ struct hb_bit_set_t
return true;
}
+ void alloc (unsigned sz)
+ {
+ sz >>= (page_t::PAGE_BITS_LOG_2 - 1);
+ pages.alloc (sz);
+ page_map.alloc (sz);
+ }
+
void reset ()
{
successful = true;
@@ -119,6 +126,14 @@ struct hb_bit_set_t
}
explicit operator bool () const { return !is_empty (); }
+ uint32_t hash () const
+ {
+ uint32_t h = 0;
+ for (auto &map : page_map)
+ h = h * 31 + hb_hash (map.major) + hb_hash (pages[map.index]);
+ return h;
+ }
+
private:
void dirty () { population = UINT_MAX; }
public:
@@ -341,15 +356,14 @@ struct hb_bit_set_t
return;
population = other.population;
- /* TODO switch to vector operator =. */
- hb_memcpy ((void *) pages, (const void *) other.pages, count * pages.item_size);
- hb_memcpy ((void *) page_map, (const void *) other.page_map, count * page_map.item_size);
+ page_map = other.page_map;
+ pages = other.pages;
}
bool is_equal (const hb_bit_set_t &other) const
{
if (has_population () && other.has_population () &&
- get_population () != other.get_population ())
+ population != other.population)
return false;
unsigned int na = pages.length;
@@ -377,7 +391,7 @@ struct hb_bit_set_t
bool is_subset (const hb_bit_set_t &larger_set) const
{
if (has_population () && larger_set.has_population () &&
- get_population () != larger_set.get_population ())
+ population != larger_set.population)
return false;
uint32_t spi = 0;
@@ -874,7 +888,19 @@ struct hb_bit_set_t
page_t *page_for (hb_codepoint_t g, bool insert = false)
{
- page_map_t map = {get_major (g), pages.length};
+ unsigned major = get_major (g);
+
+ /* The extra page_map length is necessary; can't just rely on vector here,
+ * since the next check would be tricked because a null page also has
+ * major==0, which we can't distinguish from an actualy major==0 page... */
+ if (likely (last_page_lookup < page_map.length))
+ {
+ auto &cached_page = page_map.arrayZ[last_page_lookup];
+ if (cached_page.major == major)
+ return &pages[cached_page.index];
+ }
+
+ page_map_t map = {major, pages.length};
unsigned int i;
if (!page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST))
{
@@ -890,15 +916,31 @@ struct hb_bit_set_t
(page_map.length - 1 - i) * page_map.item_size);
page_map[i] = map;
}
+
+ last_page_lookup = i;
return &pages[page_map[i].index];
}
const page_t *page_for (hb_codepoint_t g) const
{
- page_map_t key = {get_major (g)};
- const page_map_t *found = page_map.bsearch (key);
- if (found)
- return &pages[found->index];
- return nullptr;
+ unsigned major = get_major (g);
+
+ /* The extra page_map length is necessary; can't just rely on vector here,
+ * since the next check would be tricked because a null page also has
+ * major==0, which we can't distinguish from an actualy major==0 page... */
+ if (likely (last_page_lookup < page_map.length))
+ {
+ auto &cached_page = page_map.arrayZ[last_page_lookup];
+ if (cached_page.major == major)
+ return &pages[cached_page.index];
+ }
+
+ page_map_t key = {major};
+ unsigned int i;
+ if (!page_map.bfind (key, &i))
+ return nullptr;
+
+ last_page_lookup = i;
+ return &pages[page_map[i].index];
}
page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh
index 641de0eff2b..5c2cb060a41 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-common.hh
@@ -248,6 +248,9 @@ struct number_t
/* byte string */
struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
{
+ hb_ubytes_t as_ubytes (unsigned l) const
+ { return hb_ubytes_t ((const unsigned char *) this, l); }
+
// encode 2-byte int (Dict/CharString) or 4-byte int (Dict)
template <typename T, typename V>
static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, V value)
@@ -274,33 +277,10 @@ struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
/* Defining null_size allows a Null object may be created. Should be safe because:
* A descendent struct Dict uses a Null pointer to indicate a missing table,
* checked before access.
- * byte_str_t, a wrapper struct pairing a byte pointer along with its length, always
- * checks the length before access. A Null pointer is used as the initial pointer
- * along with zero length by the default ctor.
*/
DEFINE_SIZE_MIN(0);
};
-/* Holder of a section of byte string within a CFFIndex entry */
-struct byte_str_t : hb_ubytes_t
-{
- byte_str_t ()
- : hb_ubytes_t () {}
- byte_str_t (const UnsizedByteStr& s, unsigned int l)
- : hb_ubytes_t ((const unsigned char*)&s, l) {}
- byte_str_t (const unsigned char *s, unsigned int l)
- : hb_ubytes_t (s, l) {}
- byte_str_t (const hb_ubytes_t &ub) /* conversion from hb_ubytes_t */
- : hb_ubytes_t (ub) {}
-
- /* sub-string */
- byte_str_t sub_str (unsigned int offset, unsigned int len_) const
- { return byte_str_t (hb_ubytes_t::sub_array (offset, len_)); }
-
- bool check_limit (unsigned int offset, unsigned int count) const
- { return (offset + count <= length); }
-};
-
/* A byte string associated with the current offset and an error condition */
struct byte_str_ref_t
{
@@ -308,17 +288,17 @@ struct byte_str_ref_t
void init ()
{
- str = byte_str_t ();
+ str = hb_ubytes_t ();
offset = 0;
error = false;
}
void fini () {}
- byte_str_ref_t (const byte_str_t &str_, unsigned int offset_ = 0)
+ byte_str_ref_t (const hb_ubytes_t &str_, unsigned int offset_ = 0)
: str (str_), offset (offset_), error (false) {}
- void reset (const byte_str_t &str_, unsigned int offset_ = 0)
+ void reset (const hb_ubytes_t &str_, unsigned int offset_ = 0)
{
str = str_;
offset = offset_;
@@ -334,14 +314,14 @@ struct byte_str_ref_t
return str[offset + i];
}
- /* Conversion to byte_str_t */
- operator byte_str_t () const { return str.sub_str (offset, str.length - offset); }
+ /* Conversion to hb_ubytes_t */
+ operator hb_ubytes_t () const { return str.sub_array (offset, str.length - offset); }
- byte_str_t sub_str (unsigned int offset_, unsigned int len_) const
- { return str.sub_str (offset_, len_); }
+ hb_ubytes_t sub_array (unsigned int offset_, unsigned int len_) const
+ { return str.sub_array (offset_, len_); }
bool avail (unsigned int count=1) const
- { return (!in_error () && str.check_limit (offset, count)); }
+ { return (!in_error () && offset + count <= str.length); }
void inc (unsigned int count=1)
{
if (likely (!in_error () && (offset <= str.length) && (offset + count <= str.length)))
@@ -358,44 +338,39 @@ struct byte_str_ref_t
void set_error () { error = true; }
bool in_error () const { return error; }
- byte_str_t str;
+ hb_ubytes_t str;
unsigned int offset; /* beginning of the sub-string within str */
protected:
bool error;
};
-typedef hb_vector_t<byte_str_t> byte_str_array_t;
+using byte_str_array_t = hb_vector_t<hb_ubytes_t>;
/* stack */
template <typename ELEM, int LIMIT>
struct cff_stack_t
{
- void init ()
- {
- error = false;
- count = 0;
- elements.init ();
- elements.resize (kSizeLimit);
- }
- void fini () { elements.fini (); }
-
ELEM& operator [] (unsigned int i)
{
- if (unlikely (i >= count)) set_error ();
+ if (unlikely (i >= count))
+ {
+ set_error ();
+ return Crap (ELEM);
+ }
return elements[i];
}
void push (const ELEM &v)
{
- if (likely (count < elements.length))
+ if (likely (count < LIMIT))
elements[count++] = v;
else
set_error ();
}
ELEM &push ()
{
- if (likely (count < elements.length))
+ if (likely (count < LIMIT))
return elements[count++];
else
{
@@ -424,7 +399,7 @@ struct cff_stack_t
const ELEM& peek ()
{
- if (unlikely (count < 0))
+ if (unlikely (count == 0))
{
set_error ();
return Null (ELEM);
@@ -434,7 +409,7 @@ struct cff_stack_t
void unpop ()
{
- if (likely (count < elements.length))
+ if (likely (count < LIMIT))
count++;
else
set_error ();
@@ -442,18 +417,19 @@ struct cff_stack_t
void clear () { count = 0; }
- bool in_error () const { return (error || elements.in_error ()); }
+ bool in_error () const { return (error); }
void set_error () { error = true; }
unsigned int get_count () const { return count; }
bool is_empty () const { return !count; }
- static constexpr unsigned kSizeLimit = LIMIT;
+ hb_array_t<const ELEM> sub_array (unsigned start, unsigned length) const
+ { return hb_array_t<const ELEM> (elements).sub_array (start, length); }
- protected:
- bool error;
- unsigned int count;
- hb_vector_t<ELEM> elements;
+ private:
+ bool error = false;
+ unsigned int count = 0;
+ ELEM elements[LIMIT];
};
/* argument stack */
@@ -508,9 +484,6 @@ struct arg_stack_t : cff_stack_t<ARG, 513>
return true;
}
- hb_array_t<const ARG> get_subarray (unsigned int start) const
- { return S::elements.sub_array (start); }
-
private:
typedef cff_stack_t<ARG, 513> S;
};
@@ -518,8 +491,8 @@ struct arg_stack_t : cff_stack_t<ARG, 513>
/* an operator prefixed by its operands in a byte string */
struct op_str_t
{
+ hb_ubytes_t str;
op_code_t op;
- byte_str_t str;
};
/* base of OP_SERIALIZER */
@@ -547,11 +520,16 @@ struct parsed_values_t
}
void fini () { values.fini (); }
+ void alloc (unsigned n)
+ {
+ values.alloc (n);
+ }
+
void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t ())
{
VAL *val = values.push ();
val->op = op;
- val->str = str_ref.str.sub_str (opStart, str_ref.offset - opStart);
+ val->str = str_ref.str.sub_array (opStart, str_ref.offset - opStart);
opStart = str_ref.offset;
}
@@ -559,14 +537,14 @@ struct parsed_values_t
{
VAL *val = values.push (v);
val->op = op;
- val->str = str_ref.sub_str ( opStart, str_ref.offset - opStart);
+ val->str = str_ref.sub_array ( opStart, str_ref.offset - opStart);
opStart = str_ref.offset;
}
bool has_op (op_code_t op) const
{
- for (unsigned int i = 0; i < get_count (); i++)
- if (get_value (i).op == op) return true;
+ for (const auto& v : values)
+ if (v.op == op) return true;
return false;
}
@@ -581,14 +559,11 @@ struct parsed_values_t
template <typename ARG=number_t>
struct interp_env_t
{
- void init (const byte_str_t &str_)
+ interp_env_t () {}
+ interp_env_t (const hb_ubytes_t &str_)
{
str_ref.reset (str_);
- argStack.init ();
- error = false;
}
- void fini () { argStack.fini (); }
-
bool in_error () const
{ return error || str_ref.in_error () || argStack.in_error (); }
@@ -622,10 +597,10 @@ struct interp_env_t
arg_stack_t<ARG>
argStack;
protected:
- bool error;
+ bool error = false;
};
-typedef interp_env_t<> num_interp_env_t;
+using num_interp_env_t = interp_env_t<>;
template <typename ARG=number_t>
struct opset_t
@@ -668,11 +643,8 @@ struct opset_t
template <typename ENV>
struct interpreter_t
{
- ~interpreter_t() { fini (); }
-
- void fini () { env.fini (); }
-
- ENV env;
+ interpreter_t (ENV& env_) : env (env_) {}
+ ENV& env;
};
} /* namespace CFF */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh
index ef299369b5e..2983ae54a1e 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-cs-common.hh
@@ -79,10 +79,10 @@ struct biased_subrs_t
unsigned int get_count () const { return subrs ? subrs->count : 0; }
unsigned int get_bias () const { return bias; }
- byte_str_t operator [] (unsigned int index) const
+ hb_ubytes_t operator [] (unsigned int index) const
{
if (unlikely (!subrs || index >= subrs->count))
- return Null (byte_str_t);
+ return hb_ubytes_t ();
else
return (*subrs)[index];
}
@@ -112,10 +112,9 @@ struct point_t
template <typename ARG, typename SUBRS>
struct cs_interp_env_t : interp_env_t<ARG>
{
- void init (const byte_str_t &str, const SUBRS *globalSubrs_, const SUBRS *localSubrs_)
+ cs_interp_env_t (const hb_ubytes_t &str, const SUBRS *globalSubrs_, const SUBRS *localSubrs_) :
+ interp_env_t<ARG> (str)
{
- interp_env_t<ARG>::init (str);
-
context.init (str, CSType_CharString);
seen_moveto = true;
seen_hintmask = false;
@@ -123,15 +122,11 @@ struct cs_interp_env_t : interp_env_t<ARG>
vstem_count = 0;
hintmask_size = 0;
pt.set_int (0, 0);
- callStack.init ();
globalSubrs.init (globalSubrs_);
localSubrs.init (localSubrs_);
}
- void fini ()
+ ~cs_interp_env_t ()
{
- interp_env_t<ARG>::fini ();
-
- callStack.fini ();
globalSubrs.fini ();
localSubrs.fini ();
}
@@ -880,6 +875,8 @@ struct path_procs_t
template <typename ENV, typename OPSET, typename PARAM>
struct cs_interpreter_t : interpreter_t<ENV>
{
+ cs_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
+
bool interpret (PARAM& param)
{
SUPER::env.set_endchar (false);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh
index a520ca3bce5..79fe9b42c5f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff-interp-dict-common.hh
@@ -179,6 +179,8 @@ struct top_dict_opset_t : dict_opset_t
template <typename OPSET, typename PARAM, typename ENV=num_interp_env_t>
struct dict_interpreter_t : interpreter_t<ENV>
{
+ dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
+
bool interpret (PARAM& param)
{
param.init ();
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff1-interp-cs.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff1-interp-cs.hh
index 1c8762c172b..b306c2ecc9a 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff1-interp-cs.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff1-interp-cs.hh
@@ -38,17 +38,15 @@ typedef biased_subrs_t<CFF1Subrs> cff1_biased_subrs_t;
struct cff1_cs_interp_env_t : cs_interp_env_t<number_t, CFF1Subrs>
{
template <typename ACC>
- void init (const byte_str_t &str, ACC &acc, unsigned int fd)
+ cff1_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd)
+ : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs)
{
- SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs);
processed_width = false;
has_width = false;
arg_start = 0;
in_seac = false;
}
- void fini () { SUPER::fini (); }
-
void set_width (bool has_width_)
{
if (likely (!processed_width && (SUPER::argStack.get_count () > 0)))
@@ -154,7 +152,7 @@ struct cff1_cs_opset_t : cs_opset_t<number_t, OPSET, cff1_cs_interp_env_t, PARAM
};
template <typename OPSET, typename PARAM>
-struct cff1_cs_interpreter_t : cs_interpreter_t<cff1_cs_interp_env_t, OPSET, PARAM> {};
+using cff1_cs_interpreter_t = cs_interpreter_t<cff1_cs_interp_env_t, OPSET, PARAM>;
} /* namespace CFF */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh
index 766183760e0..d0b9e7b0863 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-cff2-interp-cs.hh
@@ -64,14 +64,14 @@ struct blend_arg_t : number_t
typedef interp_env_t<blend_arg_t> BlendInterpEnv;
typedef biased_subrs_t<CFF2Subrs> cff2_biased_subrs_t;
-struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
+template <typename ELEM>
+struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
{
template <typename ACC>
- void init (const byte_str_t &str, ACC &acc, unsigned int fd,
- const int *coords_=nullptr, unsigned int num_coords_=0)
+ cff2_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd,
+ const int *coords_=nullptr, unsigned int num_coords_=0)
+ : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs)
{
- SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs);
-
coords = coords_;
num_coords = num_coords_;
varStore = acc.varStore;
@@ -100,18 +100,14 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
return OpCode_return;
}
- const blend_arg_t& eval_arg (unsigned int i)
+ const ELEM& eval_arg (unsigned int i)
{
- blend_arg_t &arg = argStack[i];
- blend_arg (arg);
- return arg;
+ return SUPER::argStack[i];
}
- const blend_arg_t& pop_arg ()
+ const ELEM& pop_arg ()
{
- blend_arg_t &arg = argStack.pop ();
- blend_arg (arg);
- return arg;
+ return SUPER::argStack.pop ();
}
void process_blend ()
@@ -122,7 +118,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
if (do_blend)
{
if (unlikely (!scalars.resize (region_count)))
- set_error ();
+ SUPER::set_error ();
else
varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
&scalars[0], region_count);
@@ -133,10 +129,10 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
void process_vsindex ()
{
- unsigned int index = argStack.pop_uint ();
+ unsigned int index = SUPER::argStack.pop_uint ();
if (unlikely (seen_vsindex () || seen_blend))
{
- set_error ();
+ SUPER::set_error ();
}
else
{
@@ -151,22 +147,18 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
void set_ivs (unsigned int ivs_) { ivs = ivs_; }
bool seen_vsindex () const { return seen_vsindex_; }
- protected:
- void blend_arg (blend_arg_t &arg)
+ double blend_deltas (hb_array_t<const ELEM> deltas) const
{
- if (do_blend && arg.blending ())
+ double v = 0;
+ if (do_blend)
{
- if (likely (scalars.length == arg.deltas.length))
+ if (likely (scalars.length == deltas.length))
{
- double v = arg.to_real ();
for (unsigned int i = 0; i < scalars.length; i++)
- {
- v += (double)scalars[i] * arg.deltas[i].to_real ();
- }
- arg.set_real (v);
- arg.deltas.resize (0);
+ v += (double) scalars[i] * deltas[i].to_real ();
}
}
+ return v;
}
protected:
@@ -180,22 +172,24 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
bool seen_vsindex_;
bool seen_blend;
- typedef cs_interp_env_t<blend_arg_t, CFF2Subrs> SUPER;
+ typedef cs_interp_env_t<ELEM, CFF2Subrs> SUPER;
};
-template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t, PARAM>>
-struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH>
+template <typename OPSET, typename PARAM, typename ELEM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t<ELEM>, PARAM>>
+struct cff2_cs_opset_t : cs_opset_t<ELEM, OPSET, cff2_cs_interp_env_t<ELEM>, PARAM, PATH>
{
- static void process_op (op_code_t op, cff2_cs_interp_env_t &env, PARAM& param)
+ static void process_op (op_code_t op, cff2_cs_interp_env_t<ELEM> &env, PARAM& param)
{
switch (op) {
case OpCode_callsubr:
case OpCode_callgsubr:
/* a subroutine number shouldn't be a blended value */
+#if 0
if (unlikely (env.argStack.peek ().blending ()))
{
env.set_error ();
break;
}
+#endif
SUPER::process_op (op, env, param);
break;
@@ -204,11 +198,13 @@ struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PA
break;
case OpCode_vsindexcs:
+#if 0
if (unlikely (env.argStack.peek ().blending ()))
{
env.set_error ();
break;
}
+#endif
OPSET::process_vsindex (env, param);
break;
@@ -217,7 +213,26 @@ struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PA
}
}
- static void process_blend (cff2_cs_interp_env_t &env, PARAM& param)
+ template <typename T = ELEM,
+ hb_enable_if (hb_is_same (T, blend_arg_t))>
+ static void process_arg_blend (cff2_cs_interp_env_t<ELEM> &env,
+ ELEM &arg,
+ const hb_array_t<const ELEM> blends,
+ unsigned n, unsigned i)
+ {
+ arg.set_blends (n, i, blends.length, blends);
+ }
+ template <typename T = ELEM,
+ hb_enable_if (!hb_is_same (T, blend_arg_t))>
+ static void process_arg_blend (cff2_cs_interp_env_t<ELEM> &env,
+ ELEM &arg,
+ const hb_array_t<const ELEM> blends,
+ unsigned n, unsigned i)
+ {
+ arg.set_real (arg.to_real () + env.blend_deltas (blends));
+ }
+
+ static void process_blend (cff2_cs_interp_env_t<ELEM> &env, PARAM& param)
{
unsigned int n, k;
@@ -234,26 +249,26 @@ struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PA
}
for (unsigned int i = 0; i < n; i++)
{
- const hb_array_t<const blend_arg_t> blends = env.argStack.get_subarray (start + n + (i * k));
- env.argStack[start + i].set_blends (n, i, k, blends);
+ const hb_array_t<const ELEM> blends = env.argStack.sub_array (start + n + (i * k), k);
+ process_arg_blend (env, env.argStack[start + i], blends, n, i);
}
/* pop off blend values leaving default values now adorned with blend values */
env.argStack.pop (k * n);
}
- static void process_vsindex (cff2_cs_interp_env_t &env, PARAM& param)
+ static void process_vsindex (cff2_cs_interp_env_t<ELEM> &env, PARAM& param)
{
env.process_vsindex ();
env.clear_args ();
}
private:
- typedef cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH> SUPER;
+ typedef cs_opset_t<ELEM, OPSET, cff2_cs_interp_env_t<ELEM>, PARAM, PATH> SUPER;
};
-template <typename OPSET, typename PARAM>
-struct cff2_cs_interpreter_t : cs_interpreter_t<cff2_cs_interp_env_t, OPSET, PARAM> {};
+template <typename OPSET, typename PARAM, typename ELEM>
+using cff2_cs_interpreter_t = cs_interpreter_t<cff2_cs_interp_env_t<ELEM>, OPSET, PARAM>;
} /* namespace CFF */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc
index db05f017a5e..5700e06271c 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-font.cc
@@ -2596,12 +2596,14 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
return;
}
+ /* Since we pass it to two destroying functions. */
+ trampoline_reference (&trampoline->closure);
+
hb_font_funcs_set_nominal_glyph_func (ffuncs,
hb_font_get_nominal_glyph_trampoline,
trampoline,
trampoline_destroy);
- trampoline_reference (&trampoline->closure);
hb_font_funcs_set_variation_glyph_func (ffuncs,
hb_font_get_variation_glyph_trampoline,
trampoline,
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc
index 0cfbb22e31d..d3c5d3db93a 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ft.cc
@@ -80,12 +80,12 @@
struct hb_ft_font_t
{
- mutable hb_mutex_t lock;
- FT_Face ft_face;
int load_flags;
bool symbol; /* Whether selected cmap is symbol cmap. */
bool unref; /* Whether to destroy ft_face when done. */
+ mutable hb_mutex_t lock;
+ FT_Face ft_face;
mutable int cached_x_scale;
mutable hb_advance_cache_t advance_cache;
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.cc
index 9f1ac42846d..6c83c670c93 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.cc
@@ -289,3 +289,23 @@ hb_map_get_population (const hb_map_t *map)
{
return map->get_population ();
}
+
+/**
+ * hb_map_is_equal:
+ * @map: A map
+ * @other: Another map
+ *
+ * Tests whether @map and @other are equal (contain the same
+ * elements).
+ *
+ * Return value: %true if the two maps are equal, %false otherwise.
+ *
+ * Since: 4.3.0
+ **/
+hb_bool_t
+hb_map_is_equal (const hb_map_t *map,
+ const hb_map_t *other)
+{
+ return map->is_equal (*other);
+}
+
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.h b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.h
index 6a45a7bdd52..3f67c50b92e 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.h
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.h
@@ -91,6 +91,10 @@ hb_map_is_empty (const hb_map_t *map);
HB_EXTERN unsigned int
hb_map_get_population (const hb_map_t *map);
+HB_EXTERN hb_bool_t
+hb_map_is_equal (const hb_map_t *map,
+ const hb_map_t *other);
+
HB_EXTERN void
hb_map_set (hb_map_t *map,
hb_codepoint_t key,
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh
index 9341637eac0..aec7d87f426 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-map.hh
@@ -42,11 +42,12 @@ template <typename K, typename V,
struct hb_hashmap_t
{
hb_hashmap_t () { init (); }
+ hb_hashmap_t (std::nullptr_t) : hb_hashmap_t () {}
~hb_hashmap_t () { fini (); }
- hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { hb_copy (o, *this); }
+ hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (population); hb_copy (o, *this); }
hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); }
- hb_hashmap_t& operator= (const hb_hashmap_t& o) { hb_copy (o, *this); return *this; }
+ hb_hashmap_t& operator= (const hb_hashmap_t& o) { resize (population); hb_copy (o, *this); return *this; }
hb_hashmap_t& operator= (hb_hashmap_t&& o) { hb_swap (*this, o); return *this; }
hb_hashmap_t (std::initializer_list<hb_pair_t<K, V>> lst) : hb_hashmap_t ()
@@ -58,7 +59,10 @@ struct hb_hashmap_t
hb_requires (hb_is_iterable (Iterable))>
hb_hashmap_t (const Iterable &o) : hb_hashmap_t ()
{
- hb_copy (o, *this);
+ auto iter = hb_iter (o);
+ if (iter.is_random_access_iterator)
+ resize (hb_len (iter));
+ hb_copy (iter, *this);
}
struct item_t
@@ -154,11 +158,11 @@ struct hb_hashmap_t
bool in_error () const { return !successful; }
- bool resize ()
+ bool resize (unsigned new_population = 0)
{
if (unlikely (!successful)) return false;
- unsigned int power = hb_bit_storage (population * 2 + 8);
+ unsigned int power = hb_bit_storage (hb_max (population, new_population) * 2 + 8);
unsigned int new_size = 1u << power;
item_t *new_items = (item_t *) hb_malloc ((size_t) new_size * sizeof (item_t));
if (unlikely (!new_items))
@@ -235,6 +239,27 @@ struct hb_hashmap_t
bool is_empty () const { return population == 0; }
explicit operator bool () const { return !is_empty (); }
+ uint32_t hash () const
+ {
+ uint32_t h = 0;
+ for (auto pair : iter ())
+ h ^= (hb_hash (pair.first) * 31) + hb_hash (pair.second);
+ return h;
+ }
+
+ bool is_equal (const hb_hashmap_t &other) const
+ {
+ if (population != other.population) return false;
+
+ for (auto pair : iter ())
+ if (get (pair.first) != pair.second)
+ return false;
+
+ return true;
+ }
+ bool operator == (const hb_hashmap_t &other) const { return is_equal (other); }
+ bool operator != (const hb_hashmap_t &other) const { return !is_equal (other); }
+
unsigned int get_population () const { return population; }
/*
@@ -389,9 +414,11 @@ struct hb_map_t : hb_hashmap_t<hb_codepoint_t,
HB_MAP_VALUE_INVALID,
HB_MAP_VALUE_INVALID>;
- hb_map_t () = default;
~hb_map_t () = default;
- hb_map_t (hb_map_t&) = default;
+ hb_map_t () : hashmap () {}
+ hb_map_t (std::nullptr_t) : hb_map_t () {}
+ hb_map_t (const hb_map_t &o) : hashmap ((hashmap &) o) {}
+ hb_map_t (hb_map_t &&o) : hashmap (std::move ((hashmap &) o)) {}
hb_map_t& operator= (const hb_map_t&) = default;
hb_map_t& operator= (hb_map_t&&) = default;
hb_map_t (std::initializer_list<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> lst) : hashmap (lst) {}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh
index 3fea5d995e9..90757d38acd 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-meta.hh
@@ -188,6 +188,19 @@ template <> struct hb_int_max<signed long long> : hb_integral_constant<signed l
template <> struct hb_int_max<unsigned long long> : hb_integral_constant<unsigned long long, ULLONG_MAX> {};
#define hb_int_max(T) hb_int_max<T>::value
+#if __GNUG__ && __GNUC__ < 5
+#define hb_is_trivially_copyable(T) __has_trivial_copy(T)
+#define hb_is_trivially_copy_assignable(T) __has_trivial_assign(T)
+#define hb_is_trivially_constructible(T) __has_trivial_constructor(T)
+#define hb_is_trivially_copy_constructible(T) __has_trivial_copy_constructor(T)
+#define hb_is_trivially_destructible(T) __has_trivial_destructor(T)
+#else
+#define hb_is_trivially_copyable(T) std::is_trivially_copyable<T>::value
+#define hb_is_trivially_copy_assignable(T) std::is_trivially_copy_assignable<T>::value
+#define hb_is_trivially_constructible(T) std::is_trivially_constructible<T>::value
+#define hb_is_trivially_copy_constructible(T) std::is_trivially_copy_constructible<T>::value
+#define hb_is_trivially_destructible(T) std::is_trivially_destructible<T>::value
+#endif
/* Class traits. */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh
index 7e524177f67..aee7064be3e 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-open-type.hh
@@ -33,6 +33,7 @@
#include "hb-blob.hh"
#include "hb-face.hh"
#include "hb-machinery.hh"
+#include "hb-meta.hh"
#include "hb-subset.hh"
@@ -518,7 +519,7 @@ struct UnsizedArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
for (unsigned int i = 0; i < count; i++)
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
return_trace (false);
@@ -707,7 +708,7 @@ struct ArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
@@ -835,7 +836,7 @@ struct HeadlessArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
unsigned int count = get_length ();
for (unsigned int i = 0; i < count; i++)
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
@@ -884,7 +885,7 @@ struct ArrayOfM1
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
unsigned int count = lenM1 + 1;
for (unsigned int i = 0; i < count; i++)
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
@@ -1070,7 +1071,7 @@ struct VarSizedBinSearchArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
unsigned int count = get_length ();
for (unsigned int i = 0; i < count; i++)
if (unlikely (!(*this)[i].sanitize (c, std::forward<Ts> (ds)...)))
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh
index c102c151733..ae3b83a2563 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff-common.hh
@@ -46,49 +46,21 @@ template<typename Type>
static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offset)
{ return offset ? StructAtOffset<Type> (P, offset) : Null (Type); }
-inline unsigned int calcOffSize (unsigned int dataSize)
-{
- unsigned int size = 1;
- unsigned int offset = dataSize + 1;
- while (offset & ~0xFF)
- {
- size++;
- offset >>= 8;
- }
- /* format does not support size > 4; caller should handle it as an error */
- return size;
-}
-
struct code_pair_t
{
hb_codepoint_t code;
hb_codepoint_t glyph;
};
-typedef hb_vector_t<unsigned char> str_buff_t;
-struct str_buff_vec_t : hb_vector_t<str_buff_t>
-{
- unsigned int total_size () const
- {
- unsigned int size = 0;
- for (unsigned int i = 0; i < length; i++)
- size += (*this)[i].length;
- return size;
- }
-
- private:
- typedef hb_vector_t<str_buff_t> SUPER;
-};
+using str_buff_t = hb_vector_t<unsigned char>;
+using str_buff_vec_t = hb_vector_t<str_buff_t>;
/* CFF INDEX */
template <typename COUNT>
struct CFFIndex
{
- static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count)
- { return offSize * (count + 1); }
-
unsigned int offset_array_size () const
- { return calculate_offset_array_size (offSize, count); }
+ { return offSize * (count + 1); }
CFFIndex *copy (hb_serialize_context_t *c) const
{
@@ -100,55 +72,46 @@ struct CFFIndex
return_trace (out);
}
- bool serialize (hb_serialize_context_t *c, const CFFIndex &src)
- {
- TRACE_SERIALIZE (this);
- unsigned int size = src.get_size ();
- CFFIndex *dest = c->allocate_size<CFFIndex> (size);
- if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &src, size);
- return_trace (true);
- }
-
bool serialize (hb_serialize_context_t *c,
unsigned int offSize_,
const byte_str_array_t &byteArray)
{
TRACE_SERIALIZE (this);
+
if (byteArray.length == 0)
{
COUNT *dest = c->allocate_min<COUNT> ();
if (unlikely (!dest)) return_trace (false);
*dest = 0;
+ return_trace (true);
}
- else
- {
- /* serialize CFFIndex header */
- if (unlikely (!c->extend_min (this))) return_trace (false);
- this->count = byteArray.length;
- this->offSize = offSize_;
- if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
- return_trace (false);
- /* serialize indices */
- unsigned int offset = 1;
- unsigned int i = 0;
- for (; i < byteArray.length; i++)
- {
- set_offset_at (i, offset);
- offset += byteArray[i].get_size ();
- }
+ /* serialize CFFIndex header */
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ this->count = byteArray.length;
+ this->offSize = offSize_;
+ if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
+ return_trace (false);
+
+ /* serialize indices */
+ unsigned int offset = 1;
+ unsigned int i = 0;
+ for (; i < byteArray.length; i++)
+ {
set_offset_at (i, offset);
+ offset += byteArray[i].get_size ();
+ }
+ set_offset_at (i, offset);
- /* serialize data */
- for (unsigned int i = 0; i < byteArray.length; i++)
- {
- const byte_str_t &bs = byteArray[i];
- unsigned char *dest = c->allocate_size<unsigned char> (bs.length);
- if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &bs[0], bs.length);
- }
+ /* serialize data */
+ for (unsigned int i = 0; i < byteArray.length; i++)
+ {
+ const hb_ubytes_t &bs = byteArray[i];
+ unsigned char *dest = c->allocate_size<unsigned char> (bs.length);
+ if (unlikely (!dest)) return_trace (false);
+ memcpy (dest, &bs[0], bs.length);
}
+
return_trace (true);
}
@@ -160,7 +123,7 @@ struct CFFIndex
byteArray.init ();
byteArray.resize (buffArray.length);
for (unsigned int i = 0; i < byteArray.length; i++)
- byteArray[i] = byte_str_t (buffArray[i].arrayZ, buffArray[i].length);
+ byteArray[i] = hb_ubytes_t (buffArray[i].arrayZ, buffArray[i].length);
bool result = this->serialize (c, offSize_, byteArray);
byteArray.fini ();
return result;
@@ -172,18 +135,9 @@ struct CFFIndex
Iterator it)
{
TRACE_SERIALIZE (this);
- if (it.len () == 0)
- {
- COUNT *dest = c->allocate_min<COUNT> ();
- if (unlikely (!dest)) return_trace (false);
- *dest = 0;
- }
- else
- {
- serialize_header(c, + it | hb_map ([] (const byte_str_t &_) { return _.length; }));
- for (const auto &_ : +it)
- _.copy (c);
- }
+ serialize_header(c, + it | hb_map ([] (const hb_ubytes_t &_) { return _.length; }));
+ for (const auto &_ : +it)
+ _.copy (c);
return_trace (true);
}
@@ -196,7 +150,7 @@ struct CFFIndex
{
auto it =
+ hb_iter (buffArray)
- | hb_map ([] (const str_buff_t &_) { return byte_str_t (_.arrayZ, _.length); })
+ | hb_map ([] (const str_buff_t &_) { return hb_ubytes_t (_.arrayZ, _.length); })
;
return serialize (c, it);
}
@@ -209,13 +163,15 @@ struct CFFIndex
TRACE_SERIALIZE (this);
unsigned total = + it | hb_reduce (hb_add, 0);
- unsigned off_size = calcOffSize (total);
+ unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
/* serialize CFFIndex header */
if (unlikely (!c->extend_min (this))) return_trace (false);
this->count = it.len ();
+ if (!this->count) return_trace (true);
+ if (unlikely (!c->extend (this->offSize))) return_trace (false);
this->offSize = off_size;
- if (unlikely (!c->allocate_size<HBUINT8> (off_size * (it.len () + 1))))
+ if (unlikely (!c->allocate_size<HBUINT8> (off_size * (this->count + 1))))
return_trace (false);
/* serialize indices */
@@ -233,6 +189,7 @@ struct CFFIndex
void set_offset_at (unsigned int index, unsigned int offset)
{
+ assert (index <= count);
HBUINT8 *p = offsets + offSize * index + offSize;
unsigned int size = offSize;
for (; size; size--)
@@ -243,11 +200,13 @@ struct CFFIndex
}
}
+ private:
unsigned int offset_at (unsigned int index) const
{
assert (index <= count);
- const HBUINT8 *p = offsets + offSize * index;
+
unsigned int size = offSize;
+ const HBUINT8 *p = offsets + size * index;
unsigned int offset = 0;
for (; size; size--)
offset = (offset << 8) + *p++;
@@ -256,72 +215,57 @@ struct CFFIndex
unsigned int length_at (unsigned int index) const
{
- if (unlikely ((offset_at (index + 1) < offset_at (index)) ||
- (offset_at (index + 1) > offset_at (count))))
+ unsigned offset0 = offset_at (index);
+ unsigned offset1 = offset_at (index + 1);
+ if (unlikely (offset1 < offset0 || offset1 > offset_at (count)))
return 0;
- return offset_at (index + 1) - offset_at (index);
+ return offset1 - offset0;
}
const unsigned char *data_base () const
- { return (const unsigned char *) this + min_size + offset_array_size (); }
-
- unsigned int data_size () const { return HBINT8::static_size; }
+ { return (const unsigned char *) this + min_size + offSize.static_size + offset_array_size (); }
+ public:
- byte_str_t operator [] (unsigned int index) const
+ hb_ubytes_t operator [] (unsigned int index) const
{
- if (unlikely (index >= count)) return Null (byte_str_t);
- return byte_str_t (data_base () + offset_at (index) - 1, length_at (index));
+ if (unlikely (index >= count)) return hb_ubytes_t ();
+ unsigned length = length_at (index);
+ if (unlikely (!length)) return hb_ubytes_t ();
+ return hb_ubytes_t (data_base () + offset_at (index) - 1, length);
}
unsigned int get_size () const
{
- if (this == &Null (CFFIndex)) return 0;
- if (count > 0)
- return min_size + offset_array_size () + (offset_at (count) - 1);
- return count.static_size; /* empty CFFIndex contains count only */
+ if (count)
+ return min_size + offSize.static_size + offset_array_size () + (offset_at (count) - 1);
+ return min_size; /* empty CFFIndex contains count only */
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely ((c->check_struct (this) && count == 0) || /* empty INDEX */
- (c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
- c->check_array (offsets, offSize, count + 1) &&
- c->check_array ((const HBUINT8*) data_base (), 1, max_offset () - 1))));
- }
-
- protected:
- unsigned int max_offset () const
- {
- unsigned int max = 0;
- for (unsigned int i = 0; i < count + 1u; i++)
- {
- unsigned int off = offset_at (i);
- if (off > max) max = off;
- }
- return max;
+ return_trace (likely (c->check_struct (this) &&
+ (count == 0 || /* empty INDEX */
+ (count < count + 1u &&
+ c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 &&
+ c->check_array (offsets, offSize, count + 1u) &&
+ c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count) - 1)))));
}
public:
COUNT count; /* Number of object data. Note there are (count+1) offsets */
+ private:
HBUINT8 offSize; /* The byte size of each offset in the offsets array. */
HBUINT8 offsets[HB_VAR_ARRAY];
/* The array of (count + 1) offsets into objects array (1-base). */
/* HBUINT8 data[HB_VAR_ARRAY]; Object data */
public:
- DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets);
+ DEFINE_SIZE_MIN (COUNT::static_size);
};
template <typename COUNT, typename TYPE>
struct CFFIndexOf : CFFIndex<COUNT>
{
- const byte_str_t operator [] (unsigned int index) const
- {
- if (likely (index < CFFIndex<COUNT>::count))
- return byte_str_t (CFFIndex<COUNT>::data_base () + CFFIndex<COUNT>::offset_at (index) - 1, CFFIndex<COUNT>::length_at (index));
- return Null (byte_str_t);
- }
-
template <typename DATA, typename PARAM1, typename PARAM2>
bool serialize (hb_serialize_context_t *c,
unsigned int offSize_,
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc
index df4554ac001..bd9fe5d6d40 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.cc
@@ -311,10 +311,8 @@ struct bounds_t
struct cff1_extents_param_t
{
- void init (const OT::cff1::accelerator_t *_cff)
+ cff1_extents_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff)
{
- path_open = false;
- cff = _cff;
bounds.init ();
}
@@ -322,7 +320,7 @@ struct cff1_extents_param_t
void end_path () { path_open = false; }
bool is_path_open () const { return path_open; }
- bool path_open;
+ bool path_open = false;
bounds_t bounds;
const OT::cff1::accelerator_t *cff;
@@ -395,12 +393,11 @@ bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, boun
if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
unsigned int fd = cff->fdSelect->get_fd (glyph);
- cff1_cs_interpreter_t<cff1_cs_opset_extents_t, cff1_extents_param_t> interp;
- const byte_str_t str = (*cff->charStrings)[glyph];
- interp.env.init (str, *cff, fd);
- interp.env.set_in_seac (in_seac);
- cff1_extents_param_t param;
- param.init (cff);
+ const hb_ubytes_t str = (*cff->charStrings)[glyph];
+ cff1_cs_interp_env_t env (str, *cff, fd);
+ env.set_in_seac (in_seac);
+ cff1_cs_interpreter_t<cff1_cs_opset_extents_t, cff1_extents_param_t> interp (env);
+ cff1_extents_param_t param (cff);
if (unlikely (!interp.interpret (param))) return false;
bounds = param.bounds;
return true;
@@ -541,10 +538,10 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin
if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
unsigned int fd = cff->fdSelect->get_fd (glyph);
- cff1_cs_interpreter_t<cff1_cs_opset_path_t, cff1_path_param_t> interp;
- const byte_str_t str = (*cff->charStrings)[glyph];
- interp.env.init (str, *cff, fd);
- interp.env.set_in_seac (in_seac);
+ const hb_ubytes_t str = (*cff->charStrings)[glyph];
+ cff1_cs_interp_env_t env (str, *cff, fd);
+ env.set_in_seac (in_seac);
+ cff1_cs_interpreter_t<cff1_cs_opset_path_t, cff1_path_param_t> interp (env);
cff1_path_param_t param (cff, font, draw_session, delta);
if (unlikely (!interp.interpret (param))) return false;
@@ -566,18 +563,13 @@ bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, h
struct get_seac_param_t
{
- void init (const OT::cff1::accelerator_t *_cff)
- {
- cff = _cff;
- base = 0;
- accent = 0;
- }
+ get_seac_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff) {}
bool has_seac () const { return base && accent; }
const OT::cff1::accelerator_t *cff;
- hb_codepoint_t base;
- hb_codepoint_t accent;
+ hb_codepoint_t base = 0;
+ hb_codepoint_t accent = 0;
};
struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t>
@@ -598,11 +590,10 @@ bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_code
if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
unsigned int fd = fdSelect->get_fd (glyph);
- cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp;
- const byte_str_t str = (*charStrings)[glyph];
- interp.env.init (str, *this, fd);
- get_seac_param_t param;
- param.init (this);
+ const hb_ubytes_t str = (*charStrings)[glyph];
+ cff1_cs_interp_env_t env (str, *this, fd);
+ cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp (env);
+ get_seac_param_t param (this);
if (unlikely (!interp.interpret (param))) return false;
if (param.has_seac ())
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh
index 542e3f4de35..b5047002ac4 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff1-table.hh
@@ -318,14 +318,21 @@ struct Charset0 {
return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
}
- hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+ hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
{
+ if (unlikely (glyph >= num_glyphs)) return 0;
if (glyph == 0)
return 0;
else
return sids[glyph - 1];
}
+ void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+ {
+ for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++)
+ mapping->set (gid, sids[gid - 1]);
+ }
+
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
{
if (sid == 0)
@@ -381,20 +388,36 @@ struct Charset1_2 {
return_trace (true);
}
- hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+ hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
{
+ if (unlikely (glyph >= num_glyphs)) return 0;
if (glyph == 0) return 0;
glyph--;
for (unsigned int i = 0;; i++)
{
if (glyph <= ranges[i].nLeft)
- return (hb_codepoint_t)ranges[i].first + glyph;
+ return (hb_codepoint_t) ranges[i].first + glyph;
glyph -= (ranges[i].nLeft + 1);
}
return 0;
}
+ void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+ {
+ hb_codepoint_t gid = 1;
+ for (unsigned i = 0;; i++)
+ {
+ hb_codepoint_t sid = ranges[i].first;
+ unsigned count = ranges[i].nLeft + 1;
+ for (unsigned j = 0; j < count; j++)
+ mapping->set (gid++, sid++);
+
+ if (gid >= num_glyphs)
+ break;
+ }
+ }
+
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
{
if (sid == 0) return 0;
@@ -521,16 +544,26 @@ struct Charset
hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const
{
- if (unlikely (glyph >= num_glyphs)) return 0;
switch (format)
{
- case 0: return u.format0.get_sid (glyph);
- case 1: return u.format1.get_sid (glyph);
- case 2: return u.format2.get_sid (glyph);
+ case 0: return u.format0.get_sid (glyph, num_glyphs);
+ case 1: return u.format1.get_sid (glyph, num_glyphs);
+ case 2: return u.format2.get_sid (glyph, num_glyphs);
default:return 0;
}
}
+ void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+ {
+ switch (format)
+ {
+ case 0: u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return;
+ case 1: u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return;
+ case 2: u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return;
+ default:return;
+ }
+ }
+
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
{
switch (format)
@@ -602,6 +635,8 @@ struct cff1_top_dict_interp_env_t : num_interp_env_t
{
cff1_top_dict_interp_env_t ()
: num_interp_env_t(), prev_offset(0), last_offset(0) {}
+ cff1_top_dict_interp_env_t (const hb_ubytes_t &bytes)
+ : num_interp_env_t(bytes), prev_offset(0), last_offset(0) {}
unsigned int prev_offset;
unsigned int last_offset;
@@ -1024,11 +1059,10 @@ struct cff1
{ fini (); return; }
{ /* parse top dict */
- const byte_str_t topDictStr = (*topDictIndex)[0];
+ const hb_ubytes_t topDictStr = (*topDictIndex)[0];
if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
- cff1_top_dict_interpreter_t top_interp;
- top_interp.env.init (topDictStr);
- topDict.init ();
+ cff1_top_dict_interp_env_t env (topDictStr);
+ cff1_top_dict_interpreter_t top_interp (env);
if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
}
@@ -1098,20 +1132,20 @@ struct cff1
{
for (unsigned int i = 0; i < fdCount; i++)
{
- byte_str_t fontDictStr = (*fdArray)[i];
+ hb_ubytes_t fontDictStr = (*fdArray)[i];
if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
cff1_font_dict_values_t *font;
- cff1_font_dict_interpreter_t font_interp;
- font_interp.env.init (fontDictStr);
+ cff1_top_dict_interp_env_t env (fontDictStr);
+ cff1_font_dict_interpreter_t font_interp (env);
font = fontDicts.push ();
if (unlikely (font == &Crap (cff1_font_dict_values_t))) { fini (); return; }
font->init ();
if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
PRIVDICTVAL *priv = &privateDicts[i];
- const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
+ const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
- dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
- priv_interp.env.init (privDictStr);
+ num_interp_env_t env2 (privDictStr);
+ dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2);
priv->init ();
if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
@@ -1126,10 +1160,10 @@ struct cff1
cff1_top_dict_values_t *font = &topDict;
PRIVDICTVAL *priv = &privateDicts[0];
- const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
+ const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
- dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
- priv_interp.env.init (privDictStr);
+ num_interp_env_t env (privDictStr);
+ dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env);
priv->init ();
if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
@@ -1194,6 +1228,19 @@ struct cff1
}
}
+ hb_map_t *create_glyph_to_sid_map () const
+ {
+ if (charset != &Null (Charset))
+ {
+ hb_map_t *mapping = hb_map_create ();
+ mapping->set (0, 0);
+ charset->collect_glyph_to_sid_map (mapping, num_glyphs);
+ return mapping;
+ }
+ else
+ return nullptr;
+ }
+
hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
{
if (charset != &Null (Charset))
@@ -1274,30 +1321,20 @@ struct cff1
{
SUPER::init (face);
+ glyph_names.set_relaxed (nullptr);
+
if (!is_valid ()) return;
if (is_CID ()) return;
- /* fill glyph_names */
- for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
- {
- hb_codepoint_t sid = glyph_to_sid (gid);
- gname_t gname;
- gname.sid = sid;
- if (sid < cff1_std_strings_length)
- gname.name = cff1_std_strings (sid);
- else
- {
- byte_str_t ustr = (*stringIndex)[sid - cff1_std_strings_length];
- gname.name = hb_bytes_t ((const char*)ustr.arrayZ, ustr.length);
- }
- if (unlikely (!gname.name.arrayZ)) { fini (); return; }
- glyph_names.push (gname);
- }
- glyph_names.qsort ();
}
~accelerator_t ()
{
- glyph_names.fini ();
+ hb_sorted_vector_t<gname_t> *names = glyph_names.get_relaxed ();
+ if (names)
+ {
+ names->fini ();
+ free (names);
+ }
SUPER::fini ();
}
@@ -1305,9 +1342,9 @@ struct cff1
bool get_glyph_name (hb_codepoint_t glyph,
char *buf, unsigned int buf_len) const
{
- if (!buf) return true;
if (unlikely (!is_valid ())) return false;
if (is_CID()) return false;
+ if (unlikely (!buf_len)) return true;
hb_codepoint_t sid = glyph_to_sid (glyph);
const char *str;
size_t str_len;
@@ -1319,7 +1356,7 @@ struct cff1
}
else
{
- byte_str_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
+ hb_ubytes_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
str = (const char *)ubyte_str.arrayZ;
str_len = ubyte_str.length;
}
@@ -1333,11 +1370,53 @@ struct cff1
bool get_glyph_from_name (const char *name, int len,
hb_codepoint_t *glyph) const
{
+ if (unlikely (!is_valid ())) return false;
+ if (is_CID()) return false;
if (len < 0) len = strlen (name);
if (unlikely (!len)) return false;
+ retry:
+ hb_sorted_vector_t<gname_t> *names = glyph_names.get ();
+ if (unlikely (!names))
+ {
+ names = (hb_sorted_vector_t<gname_t> *) calloc (sizeof (hb_sorted_vector_t<gname_t>), 1);
+ if (likely (names))
+ {
+ names->init ();
+ /* TODO */
+
+ /* fill glyph names */
+ for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
+ {
+ hb_codepoint_t sid = glyph_to_sid (gid);
+ gname_t gname;
+ gname.sid = sid;
+ if (sid < cff1_std_strings_length)
+ gname.name = cff1_std_strings (sid);
+ else
+ {
+ hb_ubytes_t ustr = (*stringIndex)[sid - cff1_std_strings_length];
+ gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length);
+ }
+ if (unlikely (!gname.name.arrayZ))
+ gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */
+ names->push (gname);
+ }
+ names->qsort ();
+ }
+ if (unlikely (!glyph_names.cmpexch (nullptr, names)))
+ {
+ if (names)
+ {
+ names->fini ();
+ free (names);
+ }
+ goto retry;
+ }
+ }
+
gname_t key = { hb_bytes_t (name, len), 0 };
- const gname_t *gname = glyph_names.bsearch (key);
+ const gname_t *gname = glyph_names->bsearch (key);
if (!gname) return false;
hb_codepoint_t gid = sid_to_glyph (gname->sid);
if (!gid && gname->sid) return false;
@@ -1359,7 +1438,7 @@ struct cff1
{
const gname_t *a = (const gname_t *)a_;
const gname_t *b = (const gname_t *)b_;
- int minlen = hb_min (a->name.length, b->name.length);
+ unsigned minlen = hb_min (a->name.length, b->name.length);
int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen);
if (ret) return ret;
return a->name.length - b->name.length;
@@ -1368,7 +1447,7 @@ struct cff1
int cmp (const gname_t &a) const { return cmp (&a, this); }
};
- hb_sorted_vector_t<gname_t> glyph_names;
+ mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names;
typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc
index 817fe064ce4..50c76daf93e 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.cc
@@ -36,9 +36,8 @@ using namespace CFF;
struct cff2_extents_param_t
{
- void init ()
+ cff2_extents_param_t ()
{
- path_open = false;
min_x.set_int (INT_MAX);
min_y.set_int (INT_MAX);
max_x.set_int (INT_MIN);
@@ -57,22 +56,22 @@ struct cff2_extents_param_t
if (pt.y > max_y) max_y = pt.y;
}
- bool path_open;
+ bool path_open = false;
number_t min_x;
number_t min_y;
number_t max_x;
number_t max_y;
};
-struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t, cff2_extents_param_t>
+struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t<number_t>, cff2_extents_param_t>
{
- static void moveto (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt)
+ static void moveto (cff2_cs_interp_env_t<number_t> &env, cff2_extents_param_t& param, const point_t &pt)
{
param.end_path ();
env.moveto (pt);
}
- static void line (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1)
+ static void line (cff2_cs_interp_env_t<number_t> &env, cff2_extents_param_t& param, const point_t &pt1)
{
if (!param.is_path_open ())
{
@@ -83,7 +82,7 @@ struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_
param.update_bounds (env.get_pt ());
}
- static void curve (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+ static void curve (cff2_cs_interp_env_t<number_t> &env, cff2_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
{
if (!param.is_path_open ())
{
@@ -98,7 +97,7 @@ struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_
}
};
-struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, cff2_extents_param_t, cff2_path_procs_extents_t> {};
+struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, cff2_extents_param_t, number_t, cff2_path_procs_extents_t> {};
bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
hb_codepoint_t glyph,
@@ -112,11 +111,10 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
unsigned int fd = fdSelect->get_fd (glyph);
- cff2_cs_interpreter_t<cff2_cs_opset_extents_t, cff2_extents_param_t> interp;
- const byte_str_t str = (*charStrings)[glyph];
- interp.env.init (str, *this, fd, font->coords, font->num_coords);
+ const hb_ubytes_t str = (*charStrings)[glyph];
+ cff2_cs_interp_env_t<number_t> env (str, *this, fd, font->coords, font->num_coords);
+ cff2_cs_interpreter_t<cff2_cs_opset_extents_t, cff2_extents_param_t, number_t> interp (env);
cff2_extents_param_t param;
- param.init ();
if (unlikely (!interp.interpret (param))) return false;
if (param.min_x >= param.max_x)
@@ -169,28 +167,28 @@ struct cff2_path_param_t
hb_font_t *font;
};
-struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_interp_env_t, cff2_path_param_t>
+struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_interp_env_t<number_t>, cff2_path_param_t>
{
- static void moveto (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt)
+ static void moveto (cff2_cs_interp_env_t<number_t> &env, cff2_path_param_t& param, const point_t &pt)
{
param.move_to (pt);
env.moveto (pt);
}
- static void line (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1)
+ static void line (cff2_cs_interp_env_t<number_t> &env, cff2_path_param_t& param, const point_t &pt1)
{
param.line_to (pt1);
env.moveto (pt1);
}
- static void curve (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+ static void curve (cff2_cs_interp_env_t<number_t> &env, cff2_path_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
{
param.cubic_to (pt1, pt2, pt3);
env.moveto (pt3);
}
};
-struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, cff2_path_procs_path_t> {};
+struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, number_t, cff2_path_procs_path_t> {};
bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
{
@@ -202,9 +200,9 @@ bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, h
if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
unsigned int fd = fdSelect->get_fd (glyph);
- cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t> interp;
- const byte_str_t str = (*charStrings)[glyph];
- interp.env.init (str, *this, fd, font->coords, font->num_coords);
+ const hb_ubytes_t str = (*charStrings)[glyph];
+ cff2_cs_interp_env_t<number_t> env (str, *this, fd, font->coords, font->num_coords);
+ cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t, number_t> interp (env);
cff2_path_param_t param (font, draw_session);
if (unlikely (!interp.interpret (param))) return false;
return true;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh
index b77e7f53fad..746160dc8e4 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cff2-table.hh
@@ -247,12 +247,8 @@ typedef cff2_private_dict_values_base_t<num_dict_val_t> cff2_private_dict_values
struct cff2_priv_dict_interp_env_t : num_interp_env_t
{
- void init (const byte_str_t &str)
- {
- num_interp_env_t::init (str);
- ivs = 0;
- seen_vsindex = false;
- }
+ cff2_priv_dict_interp_env_t (const hb_ubytes_t &str) :
+ num_interp_env_t (str) {}
void process_vsindex ()
{
@@ -267,8 +263,8 @@ struct cff2_priv_dict_interp_env_t : num_interp_env_t
void set_ivs (unsigned int ivs_) { ivs = ivs_; }
protected:
- unsigned int ivs;
- bool seen_vsindex;
+ unsigned int ivs = 0;
+ bool seen_vsindex = false;
};
struct cff2_private_dict_opset_t : dict_opset_t
@@ -415,10 +411,10 @@ struct cff2
goto fail;
{ /* parse top dict */
- byte_str_t topDictStr (cff2 + cff2->topDict, cff2->topDictSize);
+ hb_ubytes_t topDictStr = (cff2 + cff2->topDict).as_ubytes (cff2->topDictSize);
if (unlikely (!topDictStr.sanitize (&sc))) goto fail;
- cff2_top_dict_interpreter_t top_interp;
- top_interp.env.init (topDictStr);
+ num_interp_env_t env (topDictStr);
+ cff2_top_dict_interpreter_t top_interp (env);
topDict.init ();
if (unlikely (!top_interp.interpret (topDict))) goto fail;
}
@@ -447,20 +443,20 @@ struct cff2
/* parse font dicts and gather private dicts */
for (unsigned int i = 0; i < fdCount; i++)
{
- const byte_str_t fontDictStr = (*fdArray)[i];
+ const hb_ubytes_t fontDictStr = (*fdArray)[i];
if (unlikely (!fontDictStr.sanitize (&sc))) goto fail;
cff2_font_dict_values_t *font;
- cff2_font_dict_interpreter_t font_interp;
- font_interp.env.init (fontDictStr);
+ num_interp_env_t env (fontDictStr);
+ cff2_font_dict_interpreter_t font_interp (env);
font = fontDicts.push ();
if (unlikely (font == &Crap (cff2_font_dict_values_t))) goto fail;
font->init ();
if (unlikely (!font_interp.interpret (*font))) goto fail;
- const byte_str_t privDictStr (StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset), font->privateDictInfo.size);
+ const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
if (unlikely (!privDictStr.sanitize (&sc))) goto fail;
- dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp;
- priv_interp.env.init(privDictStr);
+ cff2_priv_dict_interp_env_t env2 (privDictStr);
+ dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp (env2);
privateDicts[i].init ();
if (unlikely (!priv_interp.interpret (privateDicts[i]))) goto fail;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh
index a8747ee5a18..7e96d9c8b32 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-cmap-table.hh
@@ -44,7 +44,7 @@ struct CmapSubtableFormat0
bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{
hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0;
- if (!gid)
+ if (unlikely (!gid))
return false;
*glyph = gid;
return true;
@@ -109,22 +109,26 @@ struct CmapSubtableFormat4
while (it) {
// Start a new range
- start_cp = (*it).first;
- prev_run_start_cp = (*it).first;
- run_start_cp = (*it).first;
- end_cp = (*it).first;
- last_gid = (*it).second;
- run_length = 1;
- prev_delta = 0;
-
- delta = (*it).second - (*it).first;
+ {
+ const auto& pair = *it;
+ start_cp = pair.first;
+ prev_run_start_cp = start_cp;
+ run_start_cp = start_cp;
+ end_cp = start_cp;
+ last_gid = pair.second;
+ run_length = 1;
+ prev_delta = 0;
+ }
+
+ delta = last_gid - start_cp;
mode = FIRST_SUB_RANGE;
it++;
while (it) {
// Process range
- hb_codepoint_t next_cp = (*it).first;
- hb_codepoint_t next_gid = (*it).second;
+ const auto& pair = *it;
+ hb_codepoint_t next_cp = pair.first;
+ hb_codepoint_t next_gid = pair.second;
if (next_cp != end_cp + 1) {
// Current range is over, stop processing.
break;
@@ -282,23 +286,22 @@ struct CmapSubtableFormat4
}
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ hb_requires (hb_is_iterator (Iterator))>
HBUINT16* serialize_rangeoffset_glyid (hb_serialize_context_t *c,
- Iterator it,
+ Iterator it,
HBUINT16 *endCode,
HBUINT16 *startCode,
HBINT16 *idDelta,
unsigned segcount)
{
- hb_hashmap_t<hb_codepoint_t, hb_codepoint_t> cp_to_gid;
- + it | hb_sink (cp_to_gid);
+ hb_map_t cp_to_gid { it };
HBUINT16 *idRangeOffset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
if (unlikely (!c->check_success (idRangeOffset))) return nullptr;
if (unlikely ((char *)idRangeOffset - (char *)idDelta != (int) segcount * (int) HBINT16::static_size)) return nullptr;
for (unsigned i : + hb_range (segcount)
- | hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; }))
+ | hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; }))
{
idRangeOffset[i] = 2 * (c->start_embed<HBUINT16> () - idRangeOffset - i);
for (hb_codepoint_t cp = startCode[i]; cp <= endCode[i]; cp++)
@@ -323,22 +326,31 @@ struct CmapSubtableFormat4
{ return _.first <= 0xFFFF; })
;
- if (format4_iter.len () == 0) return;
+ if (!format4_iter) return;
unsigned table_initpos = c->length ();
if (unlikely (!c->extend_min (this))) return;
this->format = 4;
+ hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> cp_to_gid {
+ format4_iter
+ };
+
//serialize endCode[], startCode[], idDelta[]
HBUINT16* endCode = c->start_embed<HBUINT16> ();
- unsigned segcount = serialize_find_segcount (format4_iter);
- if (unlikely (!serialize_start_end_delta_arrays (c, format4_iter, segcount)))
+ unsigned segcount = serialize_find_segcount (cp_to_gid.iter());
+ if (unlikely (!serialize_start_end_delta_arrays (c, cp_to_gid.iter(), segcount)))
return;
HBUINT16 *startCode = endCode + segcount + 1;
HBINT16 *idDelta = ((HBINT16*)startCode) + segcount;
- HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount);
+ HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c,
+ cp_to_gid.iter (),
+ endCode,
+ startCode,
+ idDelta,
+ segcount);
if (unlikely (!c->check_success (idRangeOffset))) return;
this->length = c->length () - table_initpos;
@@ -401,7 +413,7 @@ struct CmapSubtableFormat4
2,
_hb_cmp_method<hb_codepoint_t, CustomRange, unsigned>,
this->segCount + 1);
- if (!found)
+ if (unlikely (!found))
return false;
unsigned int i = found - endCount;
@@ -421,7 +433,7 @@ struct CmapSubtableFormat4
gid += this->idDelta[i];
}
gid &= 0xFFFFu;
- if (!gid)
+ if (unlikely (!gid))
return false;
*glyph = gid;
return true;
@@ -440,14 +452,14 @@ struct CmapSubtableFormat4
hb_codepoint_t start = this->startCount[i];
hb_codepoint_t end = this->endCount[i];
unsigned int rangeOffset = this->idRangeOffset[i];
+ out->add_range(start, end);
if (rangeOffset == 0)
{
for (hb_codepoint_t codepoint = start; codepoint <= end; codepoint++)
{
hb_codepoint_t gid = (codepoint + this->idDelta[i]) & 0xFFFFu;
if (unlikely (!gid))
- continue;
- out->add (codepoint);
+ out->del(codepoint);
}
}
else
@@ -456,11 +468,13 @@ struct CmapSubtableFormat4
{
unsigned int index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount;
if (unlikely (index >= this->glyphIdArrayLength))
+ {
+ out->del_range (codepoint, end);
break;
+ }
hb_codepoint_t gid = this->glyphIdArray[index];
if (unlikely (!gid))
- continue;
- out->add (codepoint);
+ out->del(codepoint);
}
}
}
@@ -469,6 +483,8 @@ struct CmapSubtableFormat4
void collect_mapping (hb_set_t *unicodes, /* OUT */
hb_map_t *mapping /* OUT */) const
{
+ // TODO(grieger): optimize similar to collect_unicodes
+ // (ie. use add_range())
unsigned count = this->segCount;
if (count && this->startCount[count - 1] == 0xFFFFu)
count--; /* Skip sentinel segment. */
@@ -620,7 +636,7 @@ struct CmapSubtableTrimmed
{
/* Rely on our implicit array bound-checking. */
hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
- if (!gid)
+ if (unlikely (!gid))
return false;
*glyph = gid;
return true;
@@ -674,7 +690,7 @@ struct CmapSubtableTrimmed
};
struct CmapSubtableFormat6 : CmapSubtableTrimmed<HBUINT16> {};
-struct CmapSubtableFormat10 : CmapSubtableTrimmed<HBUINT32 > {};
+struct CmapSubtableFormat10 : CmapSubtableTrimmed<HBUINT32> {};
template <typename T>
struct CmapSubtableLongSegmented
@@ -684,7 +700,7 @@ struct CmapSubtableLongSegmented
bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{
hb_codepoint_t gid = T::group_get_glyph (groups.bsearch (codepoint), codepoint);
- if (!gid)
+ if (unlikely (!gid))
return false;
*glyph = gid;
return true;
@@ -722,11 +738,19 @@ struct CmapSubtableLongSegmented
hb_map_t *mapping, /* OUT */
unsigned num_glyphs) const
{
+ hb_codepoint_t last_end = 0;
for (unsigned i = 0; i < this->groups.len; i++)
{
hb_codepoint_t start = this->groups[i].startCharCode;
hb_codepoint_t end = hb_min ((hb_codepoint_t) this->groups[i].endCharCode,
(hb_codepoint_t) HB_UNICODE_MAX);
+ if (unlikely (start > end || start < last_end)) {
+ // Range is not in order and is invalid, skip it.
+ continue;
+ }
+ last_end = end;
+
+
hb_codepoint_t gid = this->groups[i].glyphID;
if (!gid)
{
@@ -778,16 +802,16 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
void serialize (hb_serialize_context_t *c,
Iterator it)
{
- if (it.len () == 0) return;
+ if (!it) return;
unsigned table_initpos = c->length ();
if (unlikely (!c->extend_min (this))) return;
- hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF;
+ hb_codepoint_t startCharCode = (hb_codepoint_t) -1, endCharCode = (hb_codepoint_t) -1;
hb_codepoint_t glyphID = 0;
for (const auto& _ : +it)
{
- if (startCharCode == 0xFFFF)
+ if (startCharCode == (hb_codepoint_t) -1)
{
startCharCode = _.first;
endCharCode = _.first;
@@ -818,7 +842,7 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
this->format = 12;
this->reserved = 0;
this->length = c->length () - table_initpos;
- this->groups.len = (this->length - min_size)/CmapSubtableLongGroup::static_size;
+ this->groups.len = (this->length - min_size) / CmapSubtableLongGroup::static_size;
}
static size_t get_sub_table_size (const hb_sorted_vector_t<CmapSubtableLongGroup> &groups_data)
@@ -1448,6 +1472,37 @@ struct EncodingRecord
DEFINE_SIZE_STATIC (8);
};
+struct SubtableUnicodesCache {
+
+ private:
+ const void* base;
+ hb_hashmap_t<intptr_t, hb_set_t*> cached_unicodes;
+
+ public:
+ SubtableUnicodesCache(const void* cmap_base)
+ : base(cmap_base), cached_unicodes() {}
+ ~SubtableUnicodesCache()
+ {
+ for (hb_set_t* s : cached_unicodes.values()) {
+ hb_set_destroy (s);
+ }
+ }
+
+ hb_set_t* set_for(const EncodingRecord* record)
+ {
+ if (!cached_unicodes.has ((intptr_t) record)) {
+ hb_set_t* new_set = hb_set_create ();
+ if (!cached_unicodes.set ((intptr_t) record, new_set)) {
+ hb_set_destroy (new_set);
+ return hb_set_get_empty ();
+ }
+ (base+record->subtable).collect_unicodes (cached_unicodes.get ((intptr_t) record));
+ }
+ return cached_unicodes.get ((intptr_t) record);
+ }
+
+};
+
struct cmap
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
@@ -1467,6 +1522,7 @@ struct cmap
unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0;
auto snap = c->snapshot ();
+ SubtableUnicodesCache unicodes_cache (base);
for (const EncodingRecord& _ : encodingrec_iter)
{
if (c->in_error ())
@@ -1475,12 +1531,11 @@ struct cmap
unsigned format = (base+_.subtable).u.format;
if (format != 4 && format != 12 && format != 14) continue;
- hb_set_t unicodes_set;
- (base+_.subtable).collect_unicodes (&unicodes_set);
+ hb_set_t* unicodes_set = unicodes_cache.set_for (&_);
if (!drop_format_4 && format == 4)
{
- c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx);
+ c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 4u, base, plan, &format4objidx);
if (c->in_error () && c->only_overflow ())
{
// cmap4 overflowed, reset and retry serialization without format 4 subtables.
@@ -1495,8 +1550,8 @@ struct cmap
else if (format == 12)
{
- if (_can_drop (_, unicodes_set, base, + it | hb_map (hb_first), encodingrec_iter)) continue;
- c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx);
+ if (_can_drop (_, *unicodes_set, base, unicodes_cache, + it | hb_map (hb_first), encodingrec_iter)) continue;
+ c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 12u, base, plan, &format12objidx);
}
else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
}
@@ -1514,6 +1569,7 @@ struct cmap
bool _can_drop (const EncodingRecord& cmap12,
const hb_set_t& cmap12_unicodes,
const void* base,
+ SubtableUnicodesCache& unicodes_cache,
Iterator subset_unicodes,
EncodingRecordIterator encoding_records)
{
@@ -1544,11 +1600,10 @@ struct cmap
|| (base+_.subtable).get_language() != target_language)
continue;
- hb_set_t sibling_unicodes;
- (base+_.subtable).collect_unicodes (&sibling_unicodes);
+ hb_set_t* sibling_unicodes = unicodes_cache.set_for (&_);
auto cmap12 = + subset_unicodes | hb_filter (cmap12_unicodes);
- auto sibling = + subset_unicodes | hb_filter (sibling_unicodes);
+ auto sibling = + subset_unicodes | hb_filter (*sibling_unicodes);
for (; cmap12 && sibling; cmap12++, sibling++)
{
unsigned a = *cmap12;
@@ -1616,13 +1671,7 @@ struct cmap
if (unlikely (has_format12 && (!unicode_ucs4 && !ms_ucs4))) return_trace (false);
auto it =
- + hb_iter (c->plan->unicodes)
- | hb_map ([&] (hb_codepoint_t _)
- {
- hb_codepoint_t new_gid = HB_MAP_VALUE_INVALID;
- c->plan->new_gid_for_codepoint (_, &new_gid);
- return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (_, new_gid);
- })
+ + c->plan->unicode_to_new_gid_list.iter ()
| hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
{ return (_.second != HB_MAP_VALUE_INVALID); })
;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh
index a9deeba9a7a..24476eda178 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-color-cpal-table.hh
@@ -197,30 +197,38 @@ struct CPAL
public:
bool serialize (hb_serialize_context_t *c,
- const hb_array_t<const BGRAColor> &color_records,
const hb_array_t<const HBUINT16> &color_record_indices,
- const hb_map_t &color_record_index_map,
- const hb_set_t &retained_color_record_indices) const
+ const hb_array_t<const BGRAColor> &color_records,
+ const hb_vector_t<unsigned>& first_color_index_for_layer,
+ const hb_map_t& first_color_to_layer_index,
+ const hb_set_t &retained_color_indices) const
{
TRACE_SERIALIZE (this);
+ // TODO(grieger): limit total final size.
+
for (const auto idx : color_record_indices)
{
+ hb_codepoint_t layer_index = first_color_to_layer_index[idx];
+
HBUINT16 new_idx;
- if (idx == 0) new_idx = 0;
- else new_idx = color_record_index_map.get (idx);
+ new_idx = layer_index * retained_color_indices.get_population ();
if (!c->copy<HBUINT16> (new_idx)) return_trace (false);
}
c->push ();
- for (const auto _ : retained_color_record_indices.iter ())
+ for (unsigned first_color_index : first_color_index_for_layer)
{
- if (!c->copy<BGRAColor> (color_records[_]))
+ for (hb_codepoint_t color_index : retained_color_indices)
{
- c->pop_discard ();
- return_trace (false);
+ if (!c->copy<BGRAColor> (color_records[first_color_index + color_index]))
+ {
+ c->pop_discard ();
+ return_trace (false);
+ }
}
}
+
c->add_link (colorRecordsZ, c->pop_pack ());
return_trace (true);
}
@@ -228,6 +236,8 @@ struct CPAL
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
+ if (!numPalettes) return_trace (false);
+
const hb_map_t *color_index_map = c->plan->colr_palettes;
if (color_index_map->is_empty ()) return_trace (false);
@@ -242,30 +252,34 @@ struct CPAL
auto *out = c->serializer->start_embed (*this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
out->version = version;
out->numColors = retained_color_indices.get_population ();
out->numPalettes = numPalettes;
- const hb_array_t<const HBUINT16> colorRecordIndices = colorRecordIndicesZ.as_array (numPalettes);
- hb_map_t color_record_index_map;
- hb_set_t retained_color_record_indices;
+ hb_vector_t<unsigned> first_color_index_for_layer;
+ hb_map_t first_color_to_layer_index;
- unsigned record_count = 0;
+ const hb_array_t<const HBUINT16> colorRecordIndices = colorRecordIndicesZ.as_array (numPalettes);
for (const auto first_color_record_idx : colorRecordIndices)
{
- for (unsigned retained_color_idx : retained_color_indices.iter ())
- {
- unsigned color_record_idx = first_color_record_idx + retained_color_idx;
- if (color_record_index_map.has (color_record_idx)) continue;
- color_record_index_map.set (color_record_idx, record_count);
- retained_color_record_indices.add (color_record_idx);
- record_count++;
- }
+ if (first_color_to_layer_index.has (first_color_record_idx)) continue;
+
+ first_color_index_for_layer.push (first_color_record_idx);
+ first_color_to_layer_index.set (first_color_record_idx,
+ first_color_index_for_layer.length - 1);
}
- out->numColorRecords = record_count;
+ out->numColorRecords = first_color_index_for_layer.length
+ * retained_color_indices.get_population ();
+
const hb_array_t<const BGRAColor> color_records = (this+colorRecordsZ).as_array (numColorRecords);
- if (!out->serialize (c->serializer, color_records, colorRecordIndices, color_record_index_map, retained_color_record_indices))
+ if (!out->serialize (c->serializer,
+ colorRecordIndices,
+ color_records,
+ first_color_index_for_layer,
+ first_color_to_layer_index,
+ retained_color_indices))
return_trace (false);
if (version == 1)
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh
index b4ac6883443..866bb7e04c1 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-glyf-table.hh
@@ -953,6 +953,8 @@ struct glyf
glyf_table.destroy ();
}
+ bool has_data () const { return num_glyphs; }
+
protected:
template<typename T>
bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh
index f2a58028e32..b644df708d4 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-common.hh
@@ -91,12 +91,12 @@ template<typename Iterator>
static inline void ClassDef_serialize (hb_serialize_context_t *c,
Iterator it);
-static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
- const hb_map_t &gid_klass_map,
- hb_sorted_vector_t<HBGlyphID16> &glyphs,
- const hb_set_t &klasses,
- bool use_class_zero,
- hb_map_t *klass_map /*INOUT*/);
+static void ClassDef_remap_and_serialize (
+ hb_serialize_context_t *c,
+ const hb_set_t &klasses,
+ bool use_class_zero,
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
+ hb_map_t *klass_map /*IN/OUT*/);
struct hb_prune_langsys_context_t
@@ -1470,7 +1470,8 @@ struct CoverageFormat1
void next () { i++; }
hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
bool operator != (const iter_t& o) const
- { return i != o.i || c != o.c; }
+ { return i != o.i; }
+ iter_t __end__ () const { iter_t it; it.init (*c); it.i = c->glyphArray.len; return it; }
private:
const struct CoverageFormat1 *c;
@@ -1506,12 +1507,6 @@ struct CoverageFormat2
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!glyphs))
- {
- rangeRecord.len = 0;
- return_trace (true);
- }
-
/* TODO(iter) Write more efficiently? */
unsigned num_ranges = 0;
@@ -1524,6 +1519,7 @@ struct CoverageFormat2
}
if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
+ if (!num_ranges) return_trace (true);
unsigned count = 0;
unsigned range = (unsigned) -1;
@@ -1552,25 +1548,26 @@ struct CoverageFormat2
bool intersects (const hb_set_t *glyphs) const
{
- /* TODO Speed up, using hb_set_next() and bsearch()? */
- /* TODO(iter) Rewrite as dagger. */
- for (const auto& range : rangeRecord.as_array ())
- if (range.intersects (glyphs))
- return true;
- return false;
+ return hb_any (+ hb_iter (rangeRecord.as_array ())
+ | hb_map ([glyphs] (const RangeRecord &range) { return range.intersects (glyphs); }));
}
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
{
- /* TODO(iter) Rewrite as dagger. */
- for (const auto& range : rangeRecord.as_array ())
+ auto cmp = [] (const void *pk, const void *pr) -> int
{
- if (range.value <= index &&
- index < (unsigned int) range.value + (range.last - range.first) &&
- range.intersects (glyphs))
- return true;
- else if (index < range.value)
- return false;
- }
+ unsigned index = * (const unsigned *) pk;
+ const RangeRecord &range = * (const RangeRecord *) pr;
+ if (index < range.value) return -1;
+ if (index > (unsigned int) range.value + (range.last - range.first)) return +1;
+ return 0;
+ };
+
+ auto arr = rangeRecord.as_array ();
+ unsigned idx;
+ if (hb_bsearch_impl (&idx, index,
+ arr.arrayZ, arr.length, sizeof (arr[0]),
+ (int (*)(const void *_key, const void *_item)) cmp))
+ return arr.arrayZ[idx].intersects (glyphs);
return false;
}
@@ -1579,8 +1576,10 @@ struct CoverageFormat2
for (const auto& range : rangeRecord.as_array ())
{
if (!range.intersects (glyphs)) continue;
- for (hb_codepoint_t g = range.first; g <= range.last; g++)
- if (glyphs->has (g)) intersect_glyphs->add (g);
+ unsigned last = range.last;
+ for (hb_codepoint_t g = range.first - 1;
+ glyphs->next (&g) && g <= last;)
+ intersect_glyphs->add (g);
}
}
@@ -1632,6 +1631,8 @@ struct CoverageFormat2
return;
}
}
+ else
+ j = 0;
return;
}
coverage++;
@@ -1639,7 +1640,15 @@ struct CoverageFormat2
}
hb_codepoint_t get_glyph () const { return j; }
bool operator != (const iter_t& o) const
- { return i != o.i || j != o.j || c != o.c; }
+ { return i != o.i || j != o.j; }
+ iter_t __end__ () const
+ {
+ iter_t it;
+ it.init (*c);
+ it.i = c->rangeRecord.len;
+ it.j = 0;
+ return it;
+ }
private:
const struct CoverageFormat2 *c;
@@ -1708,18 +1717,17 @@ struct Coverage
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
auto it =
+ iter ()
- | hb_filter (glyphset)
- | hb_map_retains_sorting (glyph_map)
+ | hb_filter (c->plan->glyph_map_gsub)
+ | hb_map_retains_sorting (c->plan->glyph_map_gsub)
;
- bool ret = bool (it);
- Coverage_serialize (c->serializer, it);
- return_trace (ret);
+ // Cache the iterator result as it will be iterated multiple times
+ // by the serialize code below.
+ hb_sorted_vector_t<hb_codepoint_t> glyphs (it);
+ Coverage_serialize (c->serializer, glyphs.iter ());
+ return_trace (bool (glyphs));
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -1822,7 +1830,7 @@ struct Coverage
}
bool operator != (const iter_t& o) const
{
- if (format != o.format) return true;
+ if (unlikely (format != o.format)) return true;
switch (format)
{
case 1: return u.format1 != o.u.format1;
@@ -1830,6 +1838,18 @@ struct Coverage
default:return false;
}
}
+ iter_t __end__ () const
+ {
+ iter_t it = {};
+ it.format = format;
+ switch (format)
+ {
+ case 1: it.u.format1 = u.format1.__end__ (); break;
+ case 2: it.u.format2 = u.format2.__end__ (); break;
+ default: break;
+ }
+ return it;
+ }
private:
unsigned int format;
@@ -1857,16 +1877,14 @@ Coverage_serialize (hb_serialize_context_t *c,
{ c->start_embed<Coverage> ()->serialize (c, it); }
static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
- const hb_map_t &gid_klass_map,
- hb_sorted_vector_t<HBGlyphID16> &glyphs,
const hb_set_t &klasses,
bool use_class_zero,
- hb_map_t *klass_map /*INOUT*/)
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
+ hb_map_t *klass_map /*IN/OUT*/)
{
if (!klass_map)
{
- ClassDef_serialize (c, hb_zip (glyphs.iter (), + glyphs.iter ()
- | hb_map (gid_klass_map)));
+ ClassDef_serialize (c, glyph_and_klass.iter ());
return;
}
@@ -1883,17 +1901,15 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
idx++;
}
- auto it =
- + glyphs.iter ()
- | hb_map_retains_sorting ([&] (const HBGlyphID16& gid) -> hb_pair_t<hb_codepoint_t, unsigned>
- {
- unsigned new_klass = klass_map->get (gid_klass_map[gid]);
- return hb_pair ((hb_codepoint_t)gid, new_klass);
- })
- ;
- c->propagate_error (glyphs, klasses);
- ClassDef_serialize (c, it);
+ for (unsigned i = 0; i < glyph_and_klass.length; i++)
+ {
+ hb_codepoint_t klass = glyph_and_klass[i].second;
+ glyph_and_klass[i].second = klass_map->get (klass);
+ }
+
+ c->propagate_error (glyph_and_klass, klasses);
+ ClassDef_serialize (c, glyph_and_klass.iter ());
}
/*
@@ -1949,36 +1965,37 @@ struct ClassDefFormat1
const Coverage* glyph_filter = nullptr) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
+ const hb_map_t &glyph_map = *c->plan->glyph_map_gsub;
- hb_sorted_vector_t<HBGlyphID16> glyphs;
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
hb_set_t orig_klasses;
- hb_map_t gid_org_klass_map;
hb_codepoint_t start = startGlyph;
hb_codepoint_t end = start + classValue.len;
- for (const hb_codepoint_t gid : + hb_range (start, end)
- | hb_filter (glyphset))
+ for (const hb_codepoint_t gid : + hb_range (start, end))
{
+ hb_codepoint_t new_gid = glyph_map[gid];
+ if (new_gid == HB_MAP_VALUE_INVALID) continue;
if (glyph_filter && !glyph_filter->has(gid)) continue;
unsigned klass = classValue[gid - start];
if (!klass) continue;
- glyphs.push (glyph_map[gid]);
- gid_org_klass_map.set (glyph_map[gid], klass);
+ glyph_and_klass.push (hb_pair (new_gid, klass));
orig_klasses.add (klass);
}
unsigned glyph_count = glyph_filter
- ? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter))
- : glyphset.get_population ();
- use_class_zero = use_class_zero && glyph_count <= gid_org_klass_map.get_population ();
- ClassDef_remap_and_serialize (c->serializer, gid_org_klass_map,
- glyphs, orig_klasses, use_class_zero, klass_map);
- return_trace (keep_empty_table || (bool) glyphs);
+ ? hb_len (hb_iter (glyph_map.keys()) | hb_filter (glyph_filter))
+ : glyph_map.get_population ();
+ use_class_zero = use_class_zero && glyph_count <= glyph_and_klass.length;
+ ClassDef_remap_and_serialize (c->serializer,
+ orig_klasses,
+ use_class_zero,
+ glyph_and_klass,
+ klass_map);
+ return_trace (keep_empty_table || (bool) glyph_and_klass);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -2044,10 +2061,9 @@ struct ClassDefFormat1
}
/* TODO Speed up, using set overlap first? */
/* TODO(iter) Rewrite as dagger. */
- HBUINT16 k {klass};
const HBUINT16 *arr = classValue.arrayZ;
for (unsigned int i = 0; i < count; i++)
- if (arr[i] == k && glyphs->has (startGlyph + i))
+ if (arr[i] == klass && glyphs->has (startGlyph + i))
return true;
return false;
}
@@ -2057,17 +2073,32 @@ struct ClassDefFormat1
unsigned count = classValue.len;
if (klass == 0)
{
- hb_codepoint_t endGlyph = startGlyph + count -1;
- for (hb_codepoint_t g : glyphs->iter ())
- if (g < startGlyph || g > endGlyph)
- intersect_glyphs->add (g);
+ unsigned start_glyph = startGlyph;
+ for (unsigned g = HB_SET_VALUE_INVALID;
+ hb_set_next (glyphs, &g) && g < start_glyph;)
+ intersect_glyphs->add (g);
+
+ for (unsigned g = startGlyph + count - 1;
+ hb_set_next (glyphs, &g);)
+ intersect_glyphs->add (g);
return;
}
for (unsigned i = 0; i < count; i++)
if (classValue[i] == klass && glyphs->has (startGlyph + i))
- intersect_glyphs->add (startGlyph + i);
+ intersect_glyphs->add (startGlyph + i);
+
+#if 0
+ /* The following implementation is faster asymptotically, but slower
+ * in practice. */
+ unsigned start_glyph = startGlyph;
+ unsigned end_glyph = start_glyph + count;
+ for (unsigned g = startGlyph - 1;
+ hb_set_next (glyphs, &g) && g < end_glyph;)
+ if (classValue.arrayZ[g - start_glyph] == klass)
+ intersect_glyphs->add (g);
+#endif
}
void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
@@ -2167,12 +2198,10 @@ struct ClassDefFormat2
const Coverage* glyph_filter = nullptr) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
+ const hb_map_t &glyph_map = *c->plan->glyph_map_gsub;
- hb_sorted_vector_t<HBGlyphID16> glyphs;
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
hb_set_t orig_klasses;
- hb_map_t gid_org_klass_map;
unsigned count = rangeRecord.len;
for (unsigned i = 0; i < count; i++)
@@ -2183,21 +2212,26 @@ struct ClassDefFormat2
hb_codepoint_t end = rangeRecord[i].last + 1;
for (hb_codepoint_t g = start; g < end; g++)
{
- if (!glyphset.has (g)) continue;
+ hb_codepoint_t new_gid = glyph_map[g];
+ if (new_gid == HB_MAP_VALUE_INVALID) continue;
if (glyph_filter && !glyph_filter->has (g)) continue;
- glyphs.push (glyph_map[g]);
- gid_org_klass_map.set (glyph_map[g], klass);
+
+ glyph_and_klass.push (hb_pair (new_gid, klass));
orig_klasses.add (klass);
}
}
+ const hb_set_t& glyphset = *c->plan->glyphset_gsub ();
unsigned glyph_count = glyph_filter
? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter))
- : glyphset.get_population ();
- use_class_zero = use_class_zero && glyph_count <= gid_org_klass_map.get_population ();
- ClassDef_remap_and_serialize (c->serializer, gid_org_klass_map,
- glyphs, orig_klasses, use_class_zero, klass_map);
- return_trace (keep_empty_table || (bool) glyphs);
+ : glyph_map.get_population ();
+ use_class_zero = use_class_zero && glyph_count <= glyph_and_klass.length;
+ ClassDef_remap_and_serialize (c->serializer,
+ orig_klasses,
+ use_class_zero,
+ glyph_and_klass,
+ klass_map);
+ return_trace (keep_empty_table || (bool) glyph_and_klass);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -2263,10 +2297,9 @@ struct ClassDefFormat2
}
/* TODO Speed up, using set overlap first? */
/* TODO(iter) Rewrite as dagger. */
- HBUINT16 k {klass};
const RangeRecord *arr = rangeRecord.arrayZ;
for (unsigned int i = 0; i < count; i++)
- if (arr[i].value == k && arr[i].intersects (glyphs))
+ if (arr[i].value == klass && arr[i].intersects (glyphs))
return true;
return false;
}
@@ -2279,43 +2312,44 @@ struct ClassDefFormat2
hb_codepoint_t g = HB_SET_VALUE_INVALID;
for (unsigned int i = 0; i < count; i++)
{
- if (!hb_set_next (glyphs, &g))
- break;
- while (g != HB_SET_VALUE_INVALID && g < rangeRecord[i].first)
- {
- intersect_glyphs->add (g);
- hb_set_next (glyphs, &g);
+ if (!hb_set_next (glyphs, &g))
+ goto done;
+ while (g < rangeRecord[i].first)
+ {
+ intersect_glyphs->add (g);
+ if (!hb_set_next (glyphs, &g))
+ goto done;
}
g = rangeRecord[i].last;
}
- while (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
- intersect_glyphs->add (g);
+ while (hb_set_next (glyphs, &g))
+ intersect_glyphs->add (g);
+ done:
return;
}
- hb_codepoint_t g = HB_SET_VALUE_INVALID;
+#if 0
+ /* The following implementation is faster asymptotically, but slower
+ * in practice. */
+ if ((count >> 3) > glyphs->get_population ())
+ {
+ for (hb_codepoint_t g = HB_SET_VALUE_INVALID;
+ hb_set_next (glyphs, &g);)
+ if (rangeRecord.as_array ().bfind (g))
+ intersect_glyphs->add (g);
+ return;
+ }
+#endif
+
for (unsigned int i = 0; i < count; i++)
{
if (rangeRecord[i].value != klass) continue;
- if (g != HB_SET_VALUE_INVALID)
- {
- if (g >= rangeRecord[i].first &&
- g <= rangeRecord[i].last)
- intersect_glyphs->add (g);
- if (g > rangeRecord[i].last)
- continue;
- }
-
- g = rangeRecord[i].first - 1;
- while (hb_set_next (glyphs, &g))
- {
- if (g >= rangeRecord[i].first && g <= rangeRecord[i].last)
- intersect_glyphs->add (g);
- else if (g > rangeRecord[i].last)
- break;
- }
+ unsigned end = rangeRecord[i].last + 1;
+ for (hb_codepoint_t g = rangeRecord[i].first - 1;
+ hb_set_next (glyphs, &g) && g < end;)
+ intersect_glyphs->add (g);
}
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh
index 56e8c5b0063..c9750ff63b5 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-layout-gsubgpos.hh
@@ -1328,7 +1328,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
bool has_pos_glyphs = false;
hb_set_t pos_glyphs;
- if (hb_set_is_empty (covered_seq_indicies) || !hb_set_has (covered_seq_indicies, seqIndex))
+ if (!hb_set_has (covered_seq_indicies, seqIndex))
{
has_pos_glyphs = true;
if (seqIndex == 0)
@@ -1361,7 +1361,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
covered_seq_indicies->add (seqIndex);
if (has_pos_glyphs) {
- c->push_cur_active_glyphs () = pos_glyphs;
+ c->push_cur_active_glyphs () = std::move (pos_glyphs);
} else {
c->push_cur_active_glyphs ().set (*c->glyphs);
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use-table.hh
index ea627cd27ef..c8e51516949 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-shape-complex-use-table.hh
@@ -606,7 +606,7 @@ static const uint8_t use_table[] = {
/* 10A00 */ B, VBlw, VBlw, VBlw, WJ, VAbv, VBlw, WJ, WJ, WJ, WJ, WJ, VPst, VMBlw, VMBlw, VMAbv,
/* 10A10 */ B, B, B, B, WJ, B, B, B, WJ, B, B, B, B, B, B, B,
/* 10A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10A30 */ B, B, B, B, B, B, WJ, WJ, CMAbv, CMBlw, CMBlw, WJ, WJ, WJ, WJ, IS,
+ /* 10A30 */ B, B, B, B, B, B, WJ, WJ, CMBlw, CMBlw, CMBlw, WJ, WJ, WJ, WJ, IS,
/* 10A40 */ B, B, B, B, B, B, B, B, B, WJ, WJ, WJ, WJ, WJ, WJ, WJ,
#define use_offset_0x10ac0u 4304
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag-table.hh
index 52617832774..b242fba2d87 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag-table.hh
@@ -13,1610 +13,1613 @@
#ifndef HB_OT_TAG_TABLE_HH
#define HB_OT_TAG_TABLE_HH
-static const LangTag ot_languages[] = {
- {"aa", HB_TAG('A','F','R',' ')}, /* Afar */
- {"aae", HB_TAG('S','Q','I',' ')}, /* Arbëreshë Albanian -> Albanian */
- {"aao", HB_TAG('A','R','A',' ')}, /* Algerian Saharan Arabic -> Arabic */
- {"aat", HB_TAG('S','Q','I',' ')}, /* Arvanitika Albanian -> Albanian */
- {"ab", HB_TAG('A','B','K',' ')}, /* Abkhazian */
- {"aba", HB_TAG_NONE }, /* Abé != Abaza */
- {"abh", HB_TAG('A','R','A',' ')}, /* Tajiki Arabic -> Arabic */
- {"abq", HB_TAG('A','B','A',' ')}, /* Abaza */
- {"abs", HB_TAG('C','P','P',' ')}, /* Ambonese Malay -> Creoles */
- {"abv", HB_TAG('A','R','A',' ')}, /* Baharna Arabic -> Arabic */
- {"acf", HB_TAG('F','A','N',' ')}, /* Saint Lucian Creole French -> French Antillean */
- {"acf", HB_TAG('C','P','P',' ')}, /* Saint Lucian Creole French -> Creoles */
-/*{"ach", HB_TAG('A','C','H',' ')},*/ /* Acoli -> Acholi */
- {"acm", HB_TAG('A','R','A',' ')}, /* Mesopotamian Arabic -> Arabic */
- {"acq", HB_TAG('A','R','A',' ')}, /* Ta'izzi-Adeni Arabic -> Arabic */
- {"acr", HB_TAG('A','C','R',' ')}, /* Achi */
- {"acr", HB_TAG('M','Y','N',' ')}, /* Achi -> Mayan */
- {"acw", HB_TAG('A','R','A',' ')}, /* Hijazi Arabic -> Arabic */
- {"acx", HB_TAG('A','R','A',' ')}, /* Omani Arabic -> Arabic */
- {"acy", HB_TAG('A','R','A',' ')}, /* Cypriot Arabic -> Arabic */
- {"ada", HB_TAG('D','N','G',' ')}, /* Adangme -> Dangme */
- {"adf", HB_TAG('A','R','A',' ')}, /* Dhofari Arabic -> Arabic */
- {"adp", HB_TAG('D','Z','N',' ')}, /* Adap (retired code) -> Dzongkha */
-/*{"ady", HB_TAG('A','D','Y',' ')},*/ /* Adyghe */
- {"aeb", HB_TAG('A','R','A',' ')}, /* Tunisian Arabic -> Arabic */
- {"aec", HB_TAG('A','R','A',' ')}, /* Saidi Arabic -> Arabic */
- {"af", HB_TAG('A','F','K',' ')}, /* Afrikaans */
- {"afb", HB_TAG('A','R','A',' ')}, /* Gulf Arabic -> Arabic */
- {"afk", HB_TAG_NONE }, /* Nanubae != Afrikaans */
- {"afs", HB_TAG('C','P','P',' ')}, /* Afro-Seminole Creole -> Creoles */
- {"agu", HB_TAG('M','Y','N',' ')}, /* Aguacateco -> Mayan */
- {"agw", HB_TAG_NONE }, /* Kahua != Agaw */
- {"ahg", HB_TAG('A','G','W',' ')}, /* Qimant -> Agaw */
- {"aht", HB_TAG('A','T','H',' ')}, /* Ahtena -> Athapaskan */
- {"aig", HB_TAG('C','P','P',' ')}, /* Antigua and Barbuda Creole English -> Creoles */
- {"aii", HB_TAG('S','W','A',' ')}, /* Assyrian Neo-Aramaic -> Swadaya Aramaic */
- {"aii", HB_TAG('S','Y','R',' ')}, /* Assyrian Neo-Aramaic -> Syriac */
-/*{"aio", HB_TAG('A','I','O',' ')},*/ /* Aiton */
- {"aiw", HB_TAG('A','R','I',' ')}, /* Aari */
- {"ajp", HB_TAG('A','R','A',' ')}, /* South Levantine Arabic -> Arabic */
- {"ajt", HB_TAG('A','R','A',' ')}, /* Judeo-Tunisian Arabic (retired code) -> Arabic */
- {"ak", HB_TAG('A','K','A',' ')}, /* Akan [macrolanguage] */
- {"akb", HB_TAG('A','K','B',' ')}, /* Batak Angkola */
- {"akb", HB_TAG('B','T','K',' ')}, /* Batak Angkola -> Batak */
- {"aln", HB_TAG('S','Q','I',' ')}, /* Gheg Albanian -> Albanian */
- {"als", HB_TAG('S','Q','I',' ')}, /* Tosk Albanian -> Albanian */
-/*{"alt", HB_TAG('A','L','T',' ')},*/ /* Southern Altai -> Altai */
- {"am", HB_TAG('A','M','H',' ')}, /* Amharic */
- {"amf", HB_TAG('H','B','N',' ')}, /* Hamer-Banna -> Hammer-Banna */
- {"amw", HB_TAG('S','Y','R',' ')}, /* Western Neo-Aramaic -> Syriac */
- {"an", HB_TAG('A','R','G',' ')}, /* Aragonese */
-/*{"ang", HB_TAG('A','N','G',' ')},*/ /* Old English (ca. 450-1100) -> Anglo-Saxon */
- {"aoa", HB_TAG('C','P','P',' ')}, /* Angolar -> Creoles */
- {"apa", HB_TAG('A','T','H',' ')}, /* Apache [collection] -> Athapaskan */
- {"apc", HB_TAG('A','R','A',' ')}, /* North Levantine Arabic -> Arabic */
- {"apd", HB_TAG('A','R','A',' ')}, /* Sudanese Arabic -> Arabic */
- {"apj", HB_TAG('A','T','H',' ')}, /* Jicarilla Apache -> Athapaskan */
- {"apk", HB_TAG('A','T','H',' ')}, /* Kiowa Apache -> Athapaskan */
- {"apl", HB_TAG('A','T','H',' ')}, /* Lipan Apache -> Athapaskan */
- {"apm", HB_TAG('A','T','H',' ')}, /* Mescalero-Chiricahua Apache -> Athapaskan */
- {"apw", HB_TAG('A','T','H',' ')}, /* Western Apache -> Athapaskan */
- {"ar", HB_TAG('A','R','A',' ')}, /* Arabic [macrolanguage] */
- {"arb", HB_TAG('A','R','A',' ')}, /* Standard Arabic -> Arabic */
- {"ari", HB_TAG_NONE }, /* Arikara != Aari */
- {"ark", HB_TAG_NONE }, /* Arikapú != Rakhine */
- {"arn", HB_TAG('M','A','P',' ')}, /* Mapudungun */
- {"arq", HB_TAG('A','R','A',' ')}, /* Algerian Arabic -> Arabic */
- {"ars", HB_TAG('A','R','A',' ')}, /* Najdi Arabic -> Arabic */
- {"ary", HB_TAG('M','O','R',' ')}, /* Moroccan Arabic -> Moroccan */
- {"ary", HB_TAG('A','R','A',' ')}, /* Moroccan Arabic -> Arabic */
- {"arz", HB_TAG('A','R','A',' ')}, /* Egyptian Arabic -> Arabic */
- {"as", HB_TAG('A','S','M',' ')}, /* Assamese */
-/*{"ast", HB_TAG('A','S','T',' ')},*/ /* Asturian */
-/*{"ath", HB_TAG('A','T','H',' ')},*/ /* Athapascan [collection] -> Athapaskan */
- {"atj", HB_TAG('R','C','R',' ')}, /* Atikamekw -> R-Cree */
- {"atv", HB_TAG('A','L','T',' ')}, /* Northern Altai -> Altai */
- {"auj", HB_TAG('B','B','R',' ')}, /* Awjilah -> Berber */
- {"auz", HB_TAG('A','R','A',' ')}, /* Uzbeki Arabic -> Arabic */
- {"av", HB_TAG('A','V','R',' ')}, /* Avaric -> Avar */
- {"avl", HB_TAG('A','R','A',' ')}, /* Eastern Egyptian Bedawi Arabic -> Arabic */
-/*{"avn", HB_TAG('A','V','N',' ')},*/ /* Avatime */
-/*{"awa", HB_TAG('A','W','A',' ')},*/ /* Awadhi */
- {"ay", HB_TAG('A','Y','M',' ')}, /* Aymara [macrolanguage] */
- {"ayc", HB_TAG('A','Y','M',' ')}, /* Southern Aymara -> Aymara */
- {"ayh", HB_TAG('A','R','A',' ')}, /* Hadrami Arabic -> Arabic */
- {"ayl", HB_TAG('A','R','A',' ')}, /* Libyan Arabic -> Arabic */
- {"ayn", HB_TAG('A','R','A',' ')}, /* Sanaani Arabic -> Arabic */
- {"ayp", HB_TAG('A','R','A',' ')}, /* North Mesopotamian Arabic -> Arabic */
- {"ayr", HB_TAG('A','Y','M',' ')}, /* Central Aymara -> Aymara */
- {"az", HB_TAG('A','Z','E',' ')}, /* Azerbaijani [macrolanguage] */
- {"azb", HB_TAG('A','Z','B',' ')}, /* South Azerbaijani -> Torki */
- {"azb", HB_TAG('A','Z','E',' ')}, /* South Azerbaijani -> Azerbaijani */
- {"azd", HB_TAG('N','A','H',' ')}, /* Eastern Durango Nahuatl -> Nahuatl */
- {"azj", HB_TAG('A','Z','E',' ')}, /* North Azerbaijani -> Azerbaijani */
- {"azn", HB_TAG('N','A','H',' ')}, /* Western Durango Nahuatl -> Nahuatl */
- {"azz", HB_TAG('N','A','H',' ')}, /* Highland Puebla Nahuatl -> Nahuatl */
- {"ba", HB_TAG('B','S','H',' ')}, /* Bashkir */
- {"bad", HB_TAG('B','A','D','0')}, /* Banda [collection] */
- {"bag", HB_TAG_NONE }, /* Tuki != Baghelkhandi */
- {"bah", HB_TAG('C','P','P',' ')}, /* Bahamas Creole English -> Creoles */
- {"bai", HB_TAG('B','M','L',' ')}, /* Bamileke [collection] */
- {"bal", HB_TAG('B','L','I',' ')}, /* Baluchi [macrolanguage] */
-/*{"ban", HB_TAG('B','A','N',' ')},*/ /* Balinese */
-/*{"bar", HB_TAG('B','A','R',' ')},*/ /* Bavarian */
- {"bau", HB_TAG_NONE }, /* Bada (Nigeria) != Baulé */
- {"bbc", HB_TAG('B','B','C',' ')}, /* Batak Toba */
- {"bbc", HB_TAG('B','T','K',' ')}, /* Batak Toba -> Batak */
- {"bbj", HB_TAG('B','M','L',' ')}, /* Ghomálá' -> Bamileke */
- {"bbp", HB_TAG('B','A','D','0')}, /* West Central Banda -> Banda */
- {"bbr", HB_TAG_NONE }, /* Girawa != Berber */
- {"bbz", HB_TAG('A','R','A',' ')}, /* Babalia Creole Arabic (retired code) -> Arabic */
- {"bcc", HB_TAG('B','L','I',' ')}, /* Southern Balochi -> Baluchi */
- {"bch", HB_TAG_NONE }, /* Bariai != Bench */
- {"bci", HB_TAG('B','A','U',' ')}, /* Baoulé -> Baulé */
- {"bcl", HB_TAG('B','I','K',' ')}, /* Central Bikol -> Bikol */
- {"bcq", HB_TAG('B','C','H',' ')}, /* Bench */
- {"bcr", HB_TAG('A','T','H',' ')}, /* Babine -> Athapaskan */
-/*{"bdy", HB_TAG('B','D','Y',' ')},*/ /* Bandjalang */
- {"be", HB_TAG('B','E','L',' ')}, /* Belarusian -> Belarussian */
- {"bea", HB_TAG('A','T','H',' ')}, /* Beaver -> Athapaskan */
- {"beb", HB_TAG('B','T','I',' ')}, /* Bebele -> Beti */
-/*{"bem", HB_TAG('B','E','M',' ')},*/ /* Bemba (Zambia) */
- {"ber", HB_TAG('B','B','R',' ')}, /* Berber [collection] */
- {"bew", HB_TAG('C','P','P',' ')}, /* Betawi -> Creoles */
- {"bfl", HB_TAG('B','A','D','0')}, /* Banda-Ndélé -> Banda */
- {"bfq", HB_TAG('B','A','D',' ')}, /* Badaga */
- {"bft", HB_TAG('B','L','T',' ')}, /* Balti */
- {"bfu", HB_TAG('L','A','H',' ')}, /* Gahri -> Lahuli */
- {"bfy", HB_TAG('B','A','G',' ')}, /* Bagheli -> Baghelkhandi */
- {"bg", HB_TAG('B','G','R',' ')}, /* Bulgarian */
-/*{"bgc", HB_TAG('B','G','C',' ')},*/ /* Haryanvi */
- {"bgn", HB_TAG('B','L','I',' ')}, /* Western Balochi -> Baluchi */
- {"bgp", HB_TAG('B','L','I',' ')}, /* Eastern Balochi -> Baluchi */
- {"bgq", HB_TAG('B','G','Q',' ')}, /* Bagri */
- {"bgq", HB_TAG('R','A','J',' ')}, /* Bagri -> Rajasthani */
- {"bgr", HB_TAG('Q','I','N',' ')}, /* Bawm Chin -> Chin */
- {"bhb", HB_TAG('B','H','I',' ')}, /* Bhili */
-/*{"bhi", HB_TAG('B','H','I',' ')},*/ /* Bhilali -> Bhili */
- {"bhk", HB_TAG('B','I','K',' ')}, /* Albay Bicolano (retired code) -> Bikol */
-/*{"bho", HB_TAG('B','H','O',' ')},*/ /* Bhojpuri */
- {"bhr", HB_TAG('M','L','G',' ')}, /* Bara Malagasy -> Malagasy */
- {"bi", HB_TAG('B','I','S',' ')}, /* Bislama */
- {"bi", HB_TAG('C','P','P',' ')}, /* Bislama -> Creoles */
-/*{"bik", HB_TAG('B','I','K',' ')},*/ /* Bikol [macrolanguage] */
- {"bil", HB_TAG_NONE }, /* Bile != Bilen */
- {"bin", HB_TAG('E','D','O',' ')}, /* Edo */
- {"biu", HB_TAG('Q','I','N',' ')}, /* Biete -> Chin */
-/*{"bjj", HB_TAG('B','J','J',' ')},*/ /* Kanauji */
- {"bjn", HB_TAG('M','L','Y',' ')}, /* Banjar -> Malay */
- {"bjo", HB_TAG('B','A','D','0')}, /* Mid-Southern Banda -> Banda */
- {"bjq", HB_TAG('M','L','G',' ')}, /* Southern Betsimisaraka Malagasy (retired code) -> Malagasy */
- {"bjs", HB_TAG('C','P','P',' ')}, /* Bajan -> Creoles */
- {"bjt", HB_TAG('B','L','N',' ')}, /* Balanta-Ganja -> Balante */
- {"bkf", HB_TAG_NONE }, /* Beeke != Blackfoot */
- {"bko", HB_TAG('B','M','L',' ')}, /* Kwa' -> Bamileke */
- {"bla", HB_TAG('B','K','F',' ')}, /* Siksika -> Blackfoot */
- {"ble", HB_TAG('B','L','N',' ')}, /* Balanta-Kentohe -> Balante */
- {"blg", HB_TAG('I','B','A',' ')}, /* Balau (retired code) -> Iban */
- {"bli", HB_TAG_NONE }, /* Bolia != Baluchi */
- {"blk", HB_TAG('B','L','K',' ')}, /* Pa’o Karen */
- {"blk", HB_TAG('K','R','N',' ')}, /* Pa'o Karen -> Karen */
- {"bln", HB_TAG('B','I','K',' ')}, /* Southern Catanduanes Bikol -> Bikol */
- {"blt", HB_TAG_NONE }, /* Tai Dam != Balti */
- {"bm", HB_TAG('B','M','B',' ')}, /* Bambara (Bamanankan) */
- {"bmb", HB_TAG_NONE }, /* Bembe != Bambara (Bamanankan) */
- {"bml", HB_TAG_NONE }, /* Bomboli != Bamileke */
- {"bmm", HB_TAG('M','L','G',' ')}, /* Northern Betsimisaraka Malagasy -> Malagasy */
- {"bn", HB_TAG('B','E','N',' ')}, /* Bengali */
- {"bo", HB_TAG('T','I','B',' ')}, /* Tibetan */
- {"bpd", HB_TAG('B','A','D','0')}, /* Banda-Banda -> Banda */
- {"bpl", HB_TAG('C','P','P',' ')}, /* Broome Pearling Lugger Pidgin -> Creoles */
- {"bpq", HB_TAG('C','P','P',' ')}, /* Banda Malay -> Creoles */
-/*{"bpy", HB_TAG('B','P','Y',' ')},*/ /* Bishnupriya -> Bishnupriya Manipuri */
- {"bqi", HB_TAG('L','R','C',' ')}, /* Bakhtiari -> Luri */
- {"bqk", HB_TAG('B','A','D','0')}, /* Banda-Mbrès -> Banda */
- {"br", HB_TAG('B','R','E',' ')}, /* Breton */
- {"bra", HB_TAG('B','R','I',' ')}, /* Braj -> Braj Bhasha */
- {"brc", HB_TAG('C','P','P',' ')}, /* Berbice Creole Dutch -> Creoles */
-/*{"brh", HB_TAG('B','R','H',' ')},*/ /* Brahui */
- {"bri", HB_TAG_NONE }, /* Mokpwe != Braj Bhasha */
- {"brm", HB_TAG_NONE }, /* Barambu != Burmese */
-/*{"brx", HB_TAG('B','R','X',' ')},*/ /* Bodo (India) */
- {"bs", HB_TAG('B','O','S',' ')}, /* Bosnian */
- {"bsh", HB_TAG_NONE }, /* Kati != Bashkir */
-/*{"bsk", HB_TAG('B','S','K',' ')},*/ /* Burushaski */
- {"btb", HB_TAG('B','T','I',' ')}, /* Beti (Cameroon) (retired code) */
- {"btd", HB_TAG('B','T','D',' ')}, /* Batak Dairi (Pakpak) */
- {"btd", HB_TAG('B','T','K',' ')}, /* Batak Dairi -> Batak */
- {"bti", HB_TAG_NONE }, /* Burate != Beti */
- {"btj", HB_TAG('M','L','Y',' ')}, /* Bacanese Malay -> Malay */
-/*{"btk", HB_TAG('B','T','K',' ')},*/ /* Batak [collection] */
- {"btm", HB_TAG('B','T','M',' ')}, /* Batak Mandailing */
- {"btm", HB_TAG('B','T','K',' ')}, /* Batak Mandailing -> Batak */
- {"bto", HB_TAG('B','I','K',' ')}, /* Rinconada Bikol -> Bikol */
- {"bts", HB_TAG('B','T','S',' ')}, /* Batak Simalungun */
- {"bts", HB_TAG('B','T','K',' ')}, /* Batak Simalungun -> Batak */
- {"btx", HB_TAG('B','T','X',' ')}, /* Batak Karo */
- {"btx", HB_TAG('B','T','K',' ')}, /* Batak Karo -> Batak */
- {"btz", HB_TAG('B','T','Z',' ')}, /* Batak Alas-Kluet */
- {"btz", HB_TAG('B','T','K',' ')}, /* Batak Alas-Kluet -> Batak */
-/*{"bug", HB_TAG('B','U','G',' ')},*/ /* Buginese -> Bugis */
- {"bum", HB_TAG('B','T','I',' ')}, /* Bulu (Cameroon) -> Beti */
- {"bve", HB_TAG('M','L','Y',' ')}, /* Berau Malay -> Malay */
- {"bvu", HB_TAG('M','L','Y',' ')}, /* Bukit Malay -> Malay */
- {"bwe", HB_TAG('K','R','N',' ')}, /* Bwe Karen -> Karen */
- {"bxk", HB_TAG('L','U','H',' ')}, /* Bukusu -> Luyia */
- {"bxo", HB_TAG('C','P','P',' ')}, /* Barikanchi -> Creoles */
- {"bxp", HB_TAG('B','T','I',' ')}, /* Bebil -> Beti */
- {"bxr", HB_TAG('R','B','U',' ')}, /* Russia Buriat -> Russian Buriat */
- {"byn", HB_TAG('B','I','L',' ')}, /* Bilin -> Bilen */
- {"byv", HB_TAG('B','Y','V',' ')}, /* Medumba */
- {"byv", HB_TAG('B','M','L',' ')}, /* Medumba -> Bamileke */
- {"bzc", HB_TAG('M','L','G',' ')}, /* Southern Betsimisaraka Malagasy -> Malagasy */
- {"bzj", HB_TAG('C','P','P',' ')}, /* Belize Kriol English -> Creoles */
- {"bzk", HB_TAG('C','P','P',' ')}, /* Nicaragua Creole English -> Creoles */
- {"ca", HB_TAG('C','A','T',' ')}, /* Catalan */
- {"caa", HB_TAG('M','Y','N',' ')}, /* Chortí -> Mayan */
- {"cac", HB_TAG('M','Y','N',' ')}, /* Chuj -> Mayan */
- {"caf", HB_TAG('C','R','R',' ')}, /* Southern Carrier -> Carrier */
- {"caf", HB_TAG('A','T','H',' ')}, /* Southern Carrier -> Athapaskan */
- {"cak", HB_TAG('C','A','K',' ')}, /* Kaqchikel */
- {"cak", HB_TAG('M','Y','N',' ')}, /* Kaqchikel -> Mayan */
- {"cbk", HB_TAG('C','B','K',' ')}, /* Chavacano -> Zamboanga Chavacano */
- {"cbk", HB_TAG('C','P','P',' ')}, /* Chavacano -> Creoles */
- {"cbl", HB_TAG('Q','I','N',' ')}, /* Bualkhaw Chin -> Chin */
- {"ccl", HB_TAG('C','P','P',' ')}, /* Cutchi-Swahili -> Creoles */
- {"ccm", HB_TAG('C','P','P',' ')}, /* Malaccan Creole Malay -> Creoles */
- {"cco", HB_TAG('C','C','H','N')}, /* Comaltepec Chinantec -> Chinantec */
- {"ccq", HB_TAG('A','R','K',' ')}, /* Chaungtha (retired code) -> Rakhine */
- {"cdo", HB_TAG('Z','H','S',' ')}, /* Min Dong Chinese -> Chinese, Simplified */
- {"ce", HB_TAG('C','H','E',' ')}, /* Chechen */
-/*{"ceb", HB_TAG('C','E','B',' ')},*/ /* Cebuano */
- {"cek", HB_TAG('Q','I','N',' ')}, /* Eastern Khumi Chin -> Chin */
- {"cey", HB_TAG('Q','I','N',' ')}, /* Ekai Chin -> Chin */
- {"cfm", HB_TAG('H','A','L',' ')}, /* Halam (Falam Chin) */
- {"cfm", HB_TAG('Q','I','N',' ')}, /* Falam Chin -> Chin */
-/*{"cgg", HB_TAG('C','G','G',' ')},*/ /* Chiga */
- {"ch", HB_TAG('C','H','A',' ')}, /* Chamorro */
- {"chf", HB_TAG('M','Y','N',' ')}, /* Tabasco Chontal -> Mayan */
- {"chg", HB_TAG_NONE }, /* Chagatai != Chaha Gurage */
- {"chh", HB_TAG_NONE }, /* Chinook != Chattisgarhi */
- {"chj", HB_TAG('C','C','H','N')}, /* Ojitlán Chinantec -> Chinantec */
- {"chk", HB_TAG('C','H','K','0')}, /* Chuukese */
- {"chm", HB_TAG('H','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> High Mari */
- {"chm", HB_TAG('L','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> Low Mari */
- {"chn", HB_TAG('C','P','P',' ')}, /* Chinook jargon -> Creoles */
-/*{"cho", HB_TAG('C','H','O',' ')},*/ /* Choctaw */
- {"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */
- {"chp", HB_TAG('S','A','Y',' ')}, /* Chipewyan -> Sayisi */
- {"chp", HB_TAG('A','T','H',' ')}, /* Chipewyan -> Athapaskan */
- {"chq", HB_TAG('C','C','H','N')}, /* Quiotepec Chinantec -> Chinantec */
-/*{"chr", HB_TAG('C','H','R',' ')},*/ /* Cherokee */
-/*{"chy", HB_TAG('C','H','Y',' ')},*/ /* Cheyenne */
- {"chz", HB_TAG('C','C','H','N')}, /* Ozumacín Chinantec -> Chinantec */
- {"ciw", HB_TAG('O','J','B',' ')}, /* Chippewa -> Ojibway */
-/*{"cja", HB_TAG('C','J','A',' ')},*/ /* Western Cham */
-/*{"cjm", HB_TAG('C','J','M',' ')},*/ /* Eastern Cham */
- {"cjy", HB_TAG('Z','H','S',' ')}, /* Jinyu Chinese -> Chinese, Simplified */
- {"cka", HB_TAG('Q','I','N',' ')}, /* Khumi Awa Chin (retired code) -> Chin */
- {"ckb", HB_TAG('K','U','R',' ')}, /* Central Kurdish -> Kurdish */
- {"ckn", HB_TAG('Q','I','N',' ')}, /* Kaang Chin -> Chin */
- {"cks", HB_TAG('C','P','P',' ')}, /* Tayo -> Creoles */
- {"ckt", HB_TAG('C','H','K',' ')}, /* Chukot -> Chukchi */
- {"ckz", HB_TAG('M','Y','N',' ')}, /* Cakchiquel-Quiché Mixed Language -> Mayan */
- {"clc", HB_TAG('A','T','H',' ')}, /* Chilcotin -> Athapaskan */
- {"cld", HB_TAG('S','Y','R',' ')}, /* Chaldean Neo-Aramaic -> Syriac */
- {"cle", HB_TAG('C','C','H','N')}, /* Lealao Chinantec -> Chinantec */
- {"clj", HB_TAG('Q','I','N',' ')}, /* Laitu Chin -> Chin */
- {"clt", HB_TAG('Q','I','N',' ')}, /* Lautu Chin -> Chin */
- {"cmn", HB_TAG('Z','H','S',' ')}, /* Mandarin Chinese -> Chinese, Simplified */
- {"cmr", HB_TAG('Q','I','N',' ')}, /* Mro-Khimi Chin -> Chin */
- {"cnb", HB_TAG('Q','I','N',' ')}, /* Chinbon Chin -> Chin */
- {"cnh", HB_TAG('Q','I','N',' ')}, /* Hakha Chin -> Chin */
- {"cnk", HB_TAG('Q','I','N',' ')}, /* Khumi Chin -> Chin */
- {"cnl", HB_TAG('C','C','H','N')}, /* Lalana Chinantec -> Chinantec */
- {"cnp", HB_TAG('Z','H','S',' ')}, /* Northern Ping Chinese -> Chinese, Simplified */
- {"cnr", HB_TAG('S','R','B',' ')}, /* Montenegrin -> Serbian */
- {"cnt", HB_TAG('C','C','H','N')}, /* Tepetotutla Chinantec -> Chinantec */
- {"cnu", HB_TAG('B','B','R',' ')}, /* Chenoua -> Berber */
- {"cnw", HB_TAG('Q','I','N',' ')}, /* Ngawn Chin -> Chin */
- {"co", HB_TAG('C','O','S',' ')}, /* Corsican */
- {"coa", HB_TAG('M','L','Y',' ')}, /* Cocos Islands Malay -> Malay */
- {"cob", HB_TAG('M','Y','N',' ')}, /* Chicomuceltec -> Mayan */
-/*{"cop", HB_TAG('C','O','P',' ')},*/ /* Coptic */
- {"coq", HB_TAG('A','T','H',' ')}, /* Coquille -> Athapaskan */
- {"cpa", HB_TAG('C','C','H','N')}, /* Palantla Chinantec -> Chinantec */
- {"cpe", HB_TAG('C','P','P',' ')}, /* English-based creoles and pidgins [collection] -> Creoles */
- {"cpf", HB_TAG('C','P','P',' ')}, /* French-based creoles and pidgins [collection] -> Creoles */
- {"cpi", HB_TAG('C','P','P',' ')}, /* Chinese Pidgin English -> Creoles */
-/*{"cpp", HB_TAG('C','P','P',' ')},*/ /* Portuguese-based creoles and pidgins [collection] -> Creoles */
- {"cpx", HB_TAG('Z','H','S',' ')}, /* Pu-Xian Chinese -> Chinese, Simplified */
- {"cqd", HB_TAG('H','M','N',' ')}, /* Chuanqiandian Cluster Miao -> Hmong */
- {"cqu", HB_TAG('Q','U','H',' ')}, /* Chilean Quechua (retired code) -> Quechua (Bolivia) */
- {"cqu", HB_TAG('Q','U','Z',' ')}, /* Chilean Quechua (retired code) -> Quechua */
- {"cr", HB_TAG('C','R','E',' ')}, /* Cree [macrolanguage] */
- {"crh", HB_TAG('C','R','T',' ')}, /* Crimean Tatar */
- {"cri", HB_TAG('C','P','P',' ')}, /* Sãotomense -> Creoles */
- {"crj", HB_TAG('E','C','R',' ')}, /* Southern East Cree -> Eastern Cree */
- {"crj", HB_TAG('Y','C','R',' ')}, /* Southern East Cree -> Y-Cree */
- {"crj", HB_TAG('C','R','E',' ')}, /* Southern East Cree -> Cree */
- {"crk", HB_TAG('W','C','R',' ')}, /* Plains Cree -> West-Cree */
- {"crk", HB_TAG('Y','C','R',' ')}, /* Plains Cree -> Y-Cree */
- {"crk", HB_TAG('C','R','E',' ')}, /* Plains Cree -> Cree */
- {"crl", HB_TAG('E','C','R',' ')}, /* Northern East Cree -> Eastern Cree */
- {"crl", HB_TAG('Y','C','R',' ')}, /* Northern East Cree -> Y-Cree */
- {"crl", HB_TAG('C','R','E',' ')}, /* Northern East Cree -> Cree */
- {"crm", HB_TAG('M','C','R',' ')}, /* Moose Cree */
- {"crm", HB_TAG('L','C','R',' ')}, /* Moose Cree -> L-Cree */
- {"crm", HB_TAG('C','R','E',' ')}, /* Moose Cree -> Cree */
- {"crp", HB_TAG('C','P','P',' ')}, /* Creoles and pidgins [collection] -> Creoles */
- {"crr", HB_TAG_NONE }, /* Carolina Algonquian != Carrier */
- {"crs", HB_TAG('C','P','P',' ')}, /* Seselwa Creole French -> Creoles */
- {"crt", HB_TAG_NONE }, /* Iyojwa'ja Chorote != Crimean Tatar */
- {"crx", HB_TAG('C','R','R',' ')}, /* Carrier */
- {"crx", HB_TAG('A','T','H',' ')}, /* Carrier -> Athapaskan */
- {"cs", HB_TAG('C','S','Y',' ')}, /* Czech */
- {"csa", HB_TAG('C','C','H','N')}, /* Chiltepec Chinantec -> Chinantec */
-/*{"csb", HB_TAG('C','S','B',' ')},*/ /* Kashubian */
- {"csh", HB_TAG('Q','I','N',' ')}, /* Asho Chin -> Chin */
- {"csj", HB_TAG('Q','I','N',' ')}, /* Songlai Chin -> Chin */
- {"csl", HB_TAG_NONE }, /* Chinese Sign Language != Church Slavonic */
- {"cso", HB_TAG('C','C','H','N')}, /* Sochiapam Chinantec -> Chinantec */
- {"csp", HB_TAG('Z','H','S',' ')}, /* Southern Ping Chinese -> Chinese, Simplified */
- {"csv", HB_TAG('Q','I','N',' ')}, /* Sumtu Chin -> Chin */
- {"csw", HB_TAG('N','C','R',' ')}, /* Swampy Cree -> N-Cree */
- {"csw", HB_TAG('N','H','C',' ')}, /* Swampy Cree -> Norway House Cree */
- {"csw", HB_TAG('C','R','E',' ')}, /* Swampy Cree -> Cree */
- {"csy", HB_TAG('Q','I','N',' ')}, /* Siyin Chin -> Chin */
- {"ctc", HB_TAG('A','T','H',' ')}, /* Chetco -> Athapaskan */
- {"ctd", HB_TAG('Q','I','N',' ')}, /* Tedim Chin -> Chin */
- {"cte", HB_TAG('C','C','H','N')}, /* Tepinapa Chinantec -> Chinantec */
-/*{"ctg", HB_TAG('C','T','G',' ')},*/ /* Chittagonian */
- {"cth", HB_TAG('Q','I','N',' ')}, /* Thaiphum Chin -> Chin */
- {"ctl", HB_TAG('C','C','H','N')}, /* Tlacoatzintepec Chinantec -> Chinantec */
- {"cts", HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol -> Bikol */
-/*{"ctt", HB_TAG('C','T','T',' ')},*/ /* Wayanad Chetti */
- {"ctu", HB_TAG('M','Y','N',' ')}, /* Chol -> Mayan */
- {"cu", HB_TAG('C','S','L',' ')}, /* Church Slavonic */
- {"cuc", HB_TAG('C','C','H','N')}, /* Usila Chinantec -> Chinantec */
-/*{"cuk", HB_TAG('C','U','K',' ')},*/ /* San Blas Kuna */
- {"cv", HB_TAG('C','H','U',' ')}, /* Chuvash */
- {"cvn", HB_TAG('C','C','H','N')}, /* Valle Nacional Chinantec -> Chinantec */
- {"cwd", HB_TAG('D','C','R',' ')}, /* Woods Cree */
- {"cwd", HB_TAG('T','C','R',' ')}, /* Woods Cree -> TH-Cree */
- {"cwd", HB_TAG('C','R','E',' ')}, /* Woods Cree -> Cree */
- {"cy", HB_TAG('W','E','L',' ')}, /* Welsh */
- {"czh", HB_TAG('Z','H','S',' ')}, /* Huizhou Chinese -> Chinese, Simplified */
- {"czo", HB_TAG('Z','H','S',' ')}, /* Min Zhong Chinese -> Chinese, Simplified */
- {"czt", HB_TAG('Q','I','N',' ')}, /* Zotung Chin -> Chin */
- {"da", HB_TAG('D','A','N',' ')}, /* Danish */
-/*{"dag", HB_TAG('D','A','G',' ')},*/ /* Dagbani */
- {"dao", HB_TAG('Q','I','N',' ')}, /* Daai Chin -> Chin */
- {"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) (retired code) */
-/*{"dar", HB_TAG('D','A','R',' ')},*/ /* Dargwa */
-/*{"dax", HB_TAG('D','A','X',' ')},*/ /* Dayi */
- {"dcr", HB_TAG('C','P','P',' ')}, /* Negerhollands -> Creoles */
- {"de", HB_TAG('D','E','U',' ')}, /* German */
- {"den", HB_TAG('S','L','A',' ')}, /* Slave (Athapascan) [macrolanguage] -> Slavey */
- {"den", HB_TAG('A','T','H',' ')}, /* Slave (Athapascan) [macrolanguage] -> Athapaskan */
- {"dep", HB_TAG('C','P','P',' ')}, /* Pidgin Delaware -> Creoles */
- {"dgo", HB_TAG('D','G','O',' ')}, /* Dogri (individual language) */
- {"dgo", HB_TAG('D','G','R',' ')}, /* Dogri (macrolanguage) */
- {"dgr", HB_TAG('A','T','H',' ')}, /* Dogrib -> Athapaskan */
- {"dhd", HB_TAG('M','A','W',' ')}, /* Dhundari -> Marwari */
-/*{"dhg", HB_TAG('D','H','G',' ')},*/ /* Dhangu */
- {"dhv", HB_TAG_NONE }, /* Dehu != Divehi (Dhivehi, Maldivian) (deprecated) */
- {"dib", HB_TAG('D','N','K',' ')}, /* South Central Dinka -> Dinka */
- {"dik", HB_TAG('D','N','K',' ')}, /* Southwestern Dinka -> Dinka */
- {"din", HB_TAG('D','N','K',' ')}, /* Dinka [macrolanguage] */
- {"dip", HB_TAG('D','N','K',' ')}, /* Northeastern Dinka -> Dinka */
- {"diq", HB_TAG('D','I','Q',' ')}, /* Dimli */
- {"diq", HB_TAG('Z','Z','A',' ')}, /* Dimli -> Zazaki */
- {"diw", HB_TAG('D','N','K',' ')}, /* Northwestern Dinka -> Dinka */
- {"dje", HB_TAG('D','J','R',' ')}, /* Zarma */
- {"djk", HB_TAG('C','P','P',' ')}, /* Eastern Maroon Creole -> Creoles */
- {"djr", HB_TAG('D','J','R','0')}, /* Djambarrpuyngu */
- {"dks", HB_TAG('D','N','K',' ')}, /* Southeastern Dinka -> Dinka */
- {"dng", HB_TAG('D','U','N',' ')}, /* Dungan */
-/*{"dnj", HB_TAG('D','N','J',' ')},*/ /* Dan */
- {"dnk", HB_TAG_NONE }, /* Dengka != Dinka */
- {"doi", HB_TAG('D','G','R',' ')}, /* Dogri (macrolanguage) [macrolanguage] */
- {"drh", HB_TAG('M','N','G',' ')}, /* Darkhat (retired code) -> Mongolian */
- {"dri", HB_TAG_NONE }, /* C'Lela != Dari */
- {"drw", HB_TAG('D','R','I',' ')}, /* Darwazi (retired code) -> Dari */
- {"drw", HB_TAG('F','A','R',' ')}, /* Darwazi (retired code) -> Persian */
- {"dsb", HB_TAG('L','S','B',' ')}, /* Lower Sorbian */
- {"dty", HB_TAG('N','E','P',' ')}, /* Dotyali -> Nepali */
-/*{"duj", HB_TAG('D','U','J',' ')},*/ /* Dhuwal (retired code) */
- {"dun", HB_TAG_NONE }, /* Dusun Deyah != Dungan */
- {"dup", HB_TAG('M','L','Y',' ')}, /* Duano -> Malay */
- {"dv", HB_TAG('D','I','V',' ')}, /* Divehi (Dhivehi, Maldivian) */
- {"dv", HB_TAG('D','H','V',' ')}, /* Divehi (Dhivehi, Maldivian) (deprecated) */
- {"dwk", HB_TAG('K','U','I',' ')}, /* Dawik Kui -> Kui */
- {"dwu", HB_TAG('D','U','J',' ')}, /* Dhuwal */
- {"dwy", HB_TAG('D','U','J',' ')}, /* Dhuwaya -> Dhuwal */
- {"dyu", HB_TAG('J','U','L',' ')}, /* Dyula -> Jula */
- {"dz", HB_TAG('D','Z','N',' ')}, /* Dzongkha */
- {"dzn", HB_TAG_NONE }, /* Dzando != Dzongkha */
- {"ecr", HB_TAG_NONE }, /* Eteocretan != Eastern Cree */
- {"ee", HB_TAG('E','W','E',' ')}, /* Ewe */
-/*{"efi", HB_TAG('E','F','I',' ')},*/ /* Efik */
- {"ekk", HB_TAG('E','T','I',' ')}, /* Standard Estonian -> Estonian */
- {"eky", HB_TAG('K','R','N',' ')}, /* Eastern Kayah -> Karen */
- {"el", HB_TAG('E','L','L',' ')}, /* Modern Greek (1453-) -> Greek */
- {"emk", HB_TAG('E','M','K',' ')}, /* Eastern Maninkakan */
- {"emk", HB_TAG('M','N','K',' ')}, /* Eastern Maninkakan -> Maninka */
- {"emy", HB_TAG('M','Y','N',' ')}, /* Epigraphic Mayan -> Mayan */
- {"en", HB_TAG('E','N','G',' ')}, /* English */
- {"enb", HB_TAG('K','A','L',' ')}, /* Markweeta -> Kalenjin */
- {"enf", HB_TAG('F','N','E',' ')}, /* Forest Enets */
- {"enh", HB_TAG('T','N','E',' ')}, /* Tundra Enets */
- {"eo", HB_TAG('N','T','O',' ')}, /* Esperanto */
- {"es", HB_TAG('E','S','P',' ')}, /* Spanish */
- {"esg", HB_TAG('G','O','N',' ')}, /* Aheri Gondi -> Gondi */
- {"esi", HB_TAG('I','P','K',' ')}, /* North Alaskan Inupiatun -> Inupiat */
- {"esk", HB_TAG('I','P','K',' ')}, /* Northwest Alaska Inupiatun -> Inupiat */
-/*{"esu", HB_TAG('E','S','U',' ')},*/ /* Central Yupik */
- {"et", HB_TAG('E','T','I',' ')}, /* Estonian [macrolanguage] */
- {"eto", HB_TAG('B','T','I',' ')}, /* Eton (Cameroon) -> Beti */
- {"eu", HB_TAG('E','U','Q',' ')}, /* Basque */
- {"euq", HB_TAG_NONE }, /* Basque [collection] != Basque */
- {"eve", HB_TAG('E','V','N',' ')}, /* Even */
- {"evn", HB_TAG('E','V','K',' ')}, /* Evenki */
- {"ewo", HB_TAG('B','T','I',' ')}, /* Ewondo -> Beti */
- {"eyo", HB_TAG('K','A','L',' ')}, /* Keiyo -> Kalenjin */
- {"fa", HB_TAG('F','A','R',' ')}, /* Persian [macrolanguage] */
- {"fab", HB_TAG('C','P','P',' ')}, /* Fa d'Ambu -> Creoles */
- {"fan", HB_TAG('F','A','N','0')}, /* Fang (Equatorial Guinea) */
- {"fan", HB_TAG('B','T','I',' ')}, /* Fang (Equatorial Guinea) -> Beti */
- {"far", HB_TAG_NONE }, /* Fataleka != Persian */
- {"fat", HB_TAG('F','A','T',' ')}, /* Fanti */
- {"fat", HB_TAG('A','K','A',' ')}, /* Fanti -> Akan */
- {"fbl", HB_TAG('B','I','K',' ')}, /* West Albay Bikol -> Bikol */
- {"ff", HB_TAG('F','U','L',' ')}, /* Fulah [macrolanguage] */
- {"ffm", HB_TAG('F','U','L',' ')}, /* Maasina Fulfulde -> Fulah */
- {"fi", HB_TAG('F','I','N',' ')}, /* Finnish */
- {"fil", HB_TAG('P','I','L',' ')}, /* Filipino */
- {"fj", HB_TAG('F','J','I',' ')}, /* Fijian */
- {"flm", HB_TAG('H','A','L',' ')}, /* Halam (Falam Chin) (retired code) */
- {"flm", HB_TAG('Q','I','N',' ')}, /* Falam Chin (retired code) -> Chin */
- {"fmp", HB_TAG('F','M','P',' ')}, /* Fe’fe’ */
- {"fmp", HB_TAG('B','M','L',' ')}, /* Fe'fe' -> Bamileke */
- {"fng", HB_TAG('C','P','P',' ')}, /* Fanagalo -> Creoles */
- {"fo", HB_TAG('F','O','S',' ')}, /* Faroese */
-/*{"fon", HB_TAG('F','O','N',' ')},*/ /* Fon */
- {"fos", HB_TAG_NONE }, /* Siraya != Faroese */
- {"fpe", HB_TAG('C','P','P',' ')}, /* Fernando Po Creole English -> Creoles */
- {"fr", HB_TAG('F','R','A',' ')}, /* French */
-/*{"frc", HB_TAG('F','R','C',' ')},*/ /* Cajun French */
-/*{"frp", HB_TAG('F','R','P',' ')},*/ /* Arpitan */
- {"fub", HB_TAG('F','U','L',' ')}, /* Adamawa Fulfulde -> Fulah */
- {"fuc", HB_TAG('F','U','L',' ')}, /* Pulaar -> Fulah */
- {"fue", HB_TAG('F','U','L',' ')}, /* Borgu Fulfulde -> Fulah */
- {"fuf", HB_TAG('F','T','A',' ')}, /* Pular -> Futa */
- {"fuf", HB_TAG('F','U','L',' ')}, /* Pular -> Fulah */
- {"fuh", HB_TAG('F','U','L',' ')}, /* Western Niger Fulfulde -> Fulah */
- {"fui", HB_TAG('F','U','L',' ')}, /* Bagirmi Fulfulde -> Fulah */
- {"fuq", HB_TAG('F','U','L',' ')}, /* Central-Eastern Niger Fulfulde -> Fulah */
- {"fur", HB_TAG('F','R','L',' ')}, /* Friulian */
- {"fuv", HB_TAG('F','U','V',' ')}, /* Nigerian Fulfulde */
- {"fuv", HB_TAG('F','U','L',' ')}, /* Nigerian Fulfulde -> Fulah */
- {"fy", HB_TAG('F','R','I',' ')}, /* Western Frisian -> Frisian */
- {"ga", HB_TAG('I','R','I',' ')}, /* Irish */
- {"gaa", HB_TAG('G','A','D',' ')}, /* Ga */
- {"gac", HB_TAG('C','P','P',' ')}, /* Mixed Great Andamanese -> Creoles */
- {"gad", HB_TAG_NONE }, /* Gaddang != Ga */
- {"gae", HB_TAG_NONE }, /* Guarequena != Scottish Gaelic (Gaelic) */
-/*{"gag", HB_TAG('G','A','G',' ')},*/ /* Gagauz */
- {"gal", HB_TAG_NONE }, /* Galolen != Galician */
- {"gan", HB_TAG('Z','H','S',' ')}, /* Gan Chinese -> Chinese, Simplified */
- {"gar", HB_TAG_NONE }, /* Galeya != Garshuni */
- {"gaw", HB_TAG_NONE }, /* Nobonob != Garhwali */
- {"gax", HB_TAG('O','R','O',' ')}, /* Borana-Arsi-Guji Oromo -> Oromo */
- {"gaz", HB_TAG('O','R','O',' ')}, /* West Central Oromo -> Oromo */
- {"gbm", HB_TAG('G','A','W',' ')}, /* Garhwali */
- {"gce", HB_TAG('A','T','H',' ')}, /* Galice -> Athapaskan */
- {"gcf", HB_TAG('C','P','P',' ')}, /* Guadeloupean Creole French -> Creoles */
- {"gcl", HB_TAG('C','P','P',' ')}, /* Grenadian Creole English -> Creoles */
- {"gcr", HB_TAG('C','P','P',' ')}, /* Guianese Creole French -> Creoles */
- {"gd", HB_TAG('G','A','E',' ')}, /* Scottish Gaelic (Gaelic) */
- {"gda", HB_TAG('R','A','J',' ')}, /* Gade Lohar -> Rajasthani */
-/*{"gez", HB_TAG('G','E','Z',' ')},*/ /* Geez */
- {"ggo", HB_TAG('G','O','N',' ')}, /* Southern Gondi (retired code) -> Gondi */
- {"gha", HB_TAG('B','B','R',' ')}, /* Ghadamès -> Berber */
- {"ghk", HB_TAG('K','R','N',' ')}, /* Geko Karen -> Karen */
- {"gho", HB_TAG('B','B','R',' ')}, /* Ghomara -> Berber */
- {"gib", HB_TAG('C','P','P',' ')}, /* Gibanawa -> Creoles */
-/*{"gih", HB_TAG('G','I','H',' ')},*/ /* Githabul */
- {"gil", HB_TAG('G','I','L','0')}, /* Kiribati (Gilbertese) */
- {"gju", HB_TAG('R','A','J',' ')}, /* Gujari -> Rajasthani */
- {"gkp", HB_TAG('G','K','P',' ')}, /* Guinea Kpelle -> Kpelle (Guinea) */
- {"gkp", HB_TAG('K','P','L',' ')}, /* Guinea Kpelle -> Kpelle */
- {"gl", HB_TAG('G','A','L',' ')}, /* Galician */
- {"gld", HB_TAG('N','A','N',' ')}, /* Nanai */
-/*{"glk", HB_TAG('G','L','K',' ')},*/ /* Gilaki */
- {"gmz", HB_TAG_NONE }, /* Mgbolizhia != Gumuz */
- {"gn", HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */
- {"gnb", HB_TAG('Q','I','N',' ')}, /* Gangte -> Chin */
-/*{"gnn", HB_TAG('G','N','N',' ')},*/ /* Gumatj */
- {"gno", HB_TAG('G','O','N',' ')}, /* Northern Gondi -> Gondi */
- {"gnw", HB_TAG('G','U','A',' ')}, /* Western Bolivian Guaraní -> Guarani */
-/*{"gog", HB_TAG('G','O','G',' ')},*/ /* Gogo */
- {"gom", HB_TAG('K','O','K',' ')}, /* Goan Konkani -> Konkani */
-/*{"gon", HB_TAG('G','O','N',' ')},*/ /* Gondi [macrolanguage] */
- {"goq", HB_TAG('C','P','P',' ')}, /* Gorap -> Creoles */
- {"gox", HB_TAG('B','A','D','0')}, /* Gobu -> Banda */
- {"gpe", HB_TAG('C','P','P',' ')}, /* Ghanaian Pidgin English -> Creoles */
- {"gro", HB_TAG_NONE }, /* Groma != Garo */
- {"grr", HB_TAG('B','B','R',' ')}, /* Taznatit -> Berber */
- {"grt", HB_TAG('G','R','O',' ')}, /* Garo */
- {"gru", HB_TAG('S','O','G',' ')}, /* Kistane -> Sodo Gurage */
- {"gsw", HB_TAG('A','L','S',' ')}, /* Alsatian */
- {"gu", HB_TAG('G','U','J',' ')}, /* Gujarati */
- {"gua", HB_TAG_NONE }, /* Shiki != Guarani */
-/*{"guc", HB_TAG('G','U','C',' ')},*/ /* Wayuu */
-/*{"guf", HB_TAG('G','U','F',' ')},*/ /* Gupapuyngu */
- {"gug", HB_TAG('G','U','A',' ')}, /* Paraguayan Guaraní -> Guarani */
- {"gui", HB_TAG('G','U','A',' ')}, /* Eastern Bolivian Guaraní -> Guarani */
- {"guk", HB_TAG('G','M','Z',' ')}, /* Gumuz */
- {"gul", HB_TAG('C','P','P',' ')}, /* Sea Island Creole English -> Creoles */
- {"gun", HB_TAG('G','U','A',' ')}, /* Mbyá Guaraní -> Guarani */
-/*{"guz", HB_TAG('G','U','Z',' ')},*/ /* Gusii */
- {"gv", HB_TAG('M','N','X',' ')}, /* Manx */
- {"gwi", HB_TAG('A','T','H',' ')}, /* Gwichʼin -> Athapaskan */
- {"gyn", HB_TAG('C','P','P',' ')}, /* Guyanese Creole English -> Creoles */
- {"ha", HB_TAG('H','A','U',' ')}, /* Hausa */
- {"haa", HB_TAG('A','T','H',' ')}, /* Han -> Athapaskan */
- {"hae", HB_TAG('O','R','O',' ')}, /* Eastern Oromo -> Oromo */
- {"hai", HB_TAG('H','A','I','0')}, /* Haida [macrolanguage] */
- {"hak", HB_TAG('Z','H','S',' ')}, /* Hakka Chinese -> Chinese, Simplified */
- {"hal", HB_TAG_NONE }, /* Halang != Halam (Falam Chin) */
- {"har", HB_TAG('H','R','I',' ')}, /* Harari */
-/*{"haw", HB_TAG('H','A','W',' ')},*/ /* Hawaiian */
- {"hax", HB_TAG('H','A','I','0')}, /* Southern Haida -> Haida */
-/*{"hay", HB_TAG('H','A','Y',' ')},*/ /* Haya */
-/*{"haz", HB_TAG('H','A','Z',' ')},*/ /* Hazaragi */
- {"hbn", HB_TAG_NONE }, /* Heiban != Hammer-Banna */
- {"hca", HB_TAG('C','P','P',' ')}, /* Andaman Creole Hindi -> Creoles */
- {"hdn", HB_TAG('H','A','I','0')}, /* Northern Haida -> Haida */
- {"he", HB_TAG('I','W','R',' ')}, /* Hebrew */
- {"hea", HB_TAG('H','M','N',' ')}, /* Northern Qiandong Miao -> Hmong */
-/*{"hei", HB_TAG('H','E','I',' ')},*/ /* Heiltsuk */
- {"hi", HB_TAG('H','I','N',' ')}, /* Hindi */
-/*{"hil", HB_TAG('H','I','L',' ')},*/ /* Hiligaynon */
- {"hji", HB_TAG('M','L','Y',' ')}, /* Haji -> Malay */
- {"hlt", HB_TAG('Q','I','N',' ')}, /* Matu Chin -> Chin */
- {"hma", HB_TAG('H','M','N',' ')}, /* Southern Mashan Hmong -> Hmong */
- {"hmc", HB_TAG('H','M','N',' ')}, /* Central Huishui Hmong -> Hmong */
- {"hmd", HB_TAG('H','M','D',' ')}, /* Large Flowery Miao -> A-Hmao */
- {"hmd", HB_TAG('H','M','N',' ')}, /* Large Flowery Miao -> Hmong */
- {"hme", HB_TAG('H','M','N',' ')}, /* Eastern Huishui Hmong -> Hmong */
- {"hmg", HB_TAG('H','M','N',' ')}, /* Southwestern Guiyang Hmong -> Hmong */
- {"hmh", HB_TAG('H','M','N',' ')}, /* Southwestern Huishui Hmong -> Hmong */
- {"hmi", HB_TAG('H','M','N',' ')}, /* Northern Huishui Hmong -> Hmong */
- {"hmj", HB_TAG('H','M','N',' ')}, /* Ge -> Hmong */
- {"hml", HB_TAG('H','M','N',' ')}, /* Luopohe Hmong -> Hmong */
- {"hmm", HB_TAG('H','M','N',' ')}, /* Central Mashan Hmong -> Hmong */
-/*{"hmn", HB_TAG('H','M','N',' ')},*/ /* Hmong [macrolanguage] */
- {"hmp", HB_TAG('H','M','N',' ')}, /* Northern Mashan Hmong -> Hmong */
- {"hmq", HB_TAG('H','M','N',' ')}, /* Eastern Qiandong Miao -> Hmong */
- {"hmr", HB_TAG('Q','I','N',' ')}, /* Hmar -> Chin */
- {"hms", HB_TAG('H','M','N',' ')}, /* Southern Qiandong Miao -> Hmong */
- {"hmw", HB_TAG('H','M','N',' ')}, /* Western Mashan Hmong -> Hmong */
- {"hmy", HB_TAG('H','M','N',' ')}, /* Southern Guiyang Hmong -> Hmong */
- {"hmz", HB_TAG('H','M','Z',' ')}, /* Hmong Shua -> Hmong Shuat */
- {"hmz", HB_TAG('H','M','N',' ')}, /* Hmong Shua -> Hmong */
-/*{"hnd", HB_TAG('H','N','D',' ')},*/ /* Southern Hindko -> Hindko */
- {"hne", HB_TAG('C','H','H',' ')}, /* Chhattisgarhi -> Chattisgarhi */
- {"hnj", HB_TAG('H','M','N',' ')}, /* Hmong Njua -> Hmong */
- {"hno", HB_TAG('H','N','D',' ')}, /* Northern Hindko -> Hindko */
- {"ho", HB_TAG('H','M','O',' ')}, /* Hiri Motu */
- {"ho", HB_TAG('C','P','P',' ')}, /* Hiri Motu -> Creoles */
- {"hoc", HB_TAG('H','O',' ',' ')}, /* Ho */
- {"hoi", HB_TAG('A','T','H',' ')}, /* Holikachuk -> Athapaskan */
- {"hoj", HB_TAG('H','A','R',' ')}, /* Hadothi -> Harauti */
- {"hoj", HB_TAG('R','A','J',' ')}, /* Hadothi -> Rajasthani */
- {"hr", HB_TAG('H','R','V',' ')}, /* Croatian */
- {"hra", HB_TAG('Q','I','N',' ')}, /* Hrangkhol -> Chin */
- {"hrm", HB_TAG('H','M','N',' ')}, /* Horned Miao -> Hmong */
- {"hsb", HB_TAG('U','S','B',' ')}, /* Upper Sorbian */
- {"hsn", HB_TAG('Z','H','S',' ')}, /* Xiang Chinese -> Chinese, Simplified */
- {"ht", HB_TAG('H','A','I',' ')}, /* Haitian (Haitian Creole) */
- {"ht", HB_TAG('C','P','P',' ')}, /* Haitian -> Creoles */
- {"hu", HB_TAG('H','U','N',' ')}, /* Hungarian */
- {"huj", HB_TAG('H','M','N',' ')}, /* Northern Guiyang Hmong -> Hmong */
- {"hup", HB_TAG('A','T','H',' ')}, /* Hupa -> Athapaskan */
- {"hus", HB_TAG('M','Y','N',' ')}, /* Huastec -> Mayan */
- {"hwc", HB_TAG('C','P','P',' ')}, /* Hawai'i Creole English -> Creoles */
- {"hy", HB_TAG('H','Y','E','0')}, /* Armenian -> Armenian East */
- {"hy", HB_TAG('H','Y','E',' ')}, /* Armenian */
- {"hyw", HB_TAG('H','Y','E',' ')}, /* Western Armenian -> Armenian */
- {"hz", HB_TAG('H','E','R',' ')}, /* Herero */
- {"ia", HB_TAG('I','N','A',' ')}, /* Interlingua (International Auxiliary Language Association) */
-/*{"iba", HB_TAG('I','B','A',' ')},*/ /* Iban */
-/*{"ibb", HB_TAG('I','B','B',' ')},*/ /* Ibibio */
- {"iby", HB_TAG('I','J','O',' ')}, /* Ibani -> Ijo */
- {"icr", HB_TAG('C','P','P',' ')}, /* Islander Creole English -> Creoles */
- {"id", HB_TAG('I','N','D',' ')}, /* Indonesian */
- {"id", HB_TAG('M','L','Y',' ')}, /* Indonesian -> Malay */
- {"ida", HB_TAG('L','U','H',' ')}, /* Idakho-Isukha-Tiriki -> Luyia */
- {"idb", HB_TAG('C','P','P',' ')}, /* Indo-Portuguese -> Creoles */
- {"ie", HB_TAG('I','L','E',' ')}, /* Interlingue */
- {"ig", HB_TAG('I','B','O',' ')}, /* Igbo */
- {"igb", HB_TAG('E','B','I',' ')}, /* Ebira */
- {"ihb", HB_TAG('C','P','P',' ')}, /* Iha Based Pidgin -> Creoles */
- {"ii", HB_TAG('Y','I','M',' ')}, /* Sichuan Yi -> Yi Modern */
- {"ijc", HB_TAG('I','J','O',' ')}, /* Izon -> Ijo */
- {"ije", HB_TAG('I','J','O',' ')}, /* Biseni -> Ijo */
- {"ijn", HB_TAG('I','J','O',' ')}, /* Kalabari -> Ijo */
-/*{"ijo", HB_TAG('I','J','O',' ')},*/ /* Ijo [collection] */
- {"ijs", HB_TAG('I','J','O',' ')}, /* Southeast Ijo -> Ijo */
- {"ik", HB_TAG('I','P','K',' ')}, /* Inupiaq [macrolanguage] -> Inupiat */
- {"ike", HB_TAG('I','N','U',' ')}, /* Eastern Canadian Inuktitut -> Inuktitut */
- {"ike", HB_TAG('I','N','U','K')}, /* Eastern Canadian Inuktitut -> Nunavik Inuktitut */
- {"ikt", HB_TAG('I','N','U',' ')}, /* Inuinnaqtun -> Inuktitut */
-/*{"ilo", HB_TAG('I','L','O',' ')},*/ /* Iloko -> Ilokano */
- {"in", HB_TAG('I','N','D',' ')}, /* Indonesian (retired code) */
- {"in", HB_TAG('M','L','Y',' ')}, /* Indonesian (retired code) -> Malay */
- {"ing", HB_TAG('A','T','H',' ')}, /* Degexit'an -> Athapaskan */
- {"inh", HB_TAG('I','N','G',' ')}, /* Ingush */
- {"io", HB_TAG('I','D','O',' ')}, /* Ido */
- {"iri", HB_TAG_NONE }, /* Rigwe != Irish */
-/*{"iru", HB_TAG('I','R','U',' ')},*/ /* Irula */
- {"is", HB_TAG('I','S','L',' ')}, /* Icelandic */
- {"ism", HB_TAG_NONE }, /* Masimasi != Inari Sami */
- {"it", HB_TAG('I','T','A',' ')}, /* Italian */
- {"itz", HB_TAG('M','Y','N',' ')}, /* Itzá -> Mayan */
- {"iu", HB_TAG('I','N','U',' ')}, /* Inuktitut [macrolanguage] */
- {"iu", HB_TAG('I','N','U','K')}, /* Inuktitut [macrolanguage] -> Nunavik Inuktitut */
- {"iw", HB_TAG('I','W','R',' ')}, /* Hebrew (retired code) */
- {"ixl", HB_TAG('M','Y','N',' ')}, /* Ixil -> Mayan */
- {"ja", HB_TAG('J','A','N',' ')}, /* Japanese */
- {"jac", HB_TAG('M','Y','N',' ')}, /* Popti' -> Mayan */
- {"jak", HB_TAG('M','L','Y',' ')}, /* Jakun -> Malay */
- {"jam", HB_TAG('J','A','M',' ')}, /* Jamaican Creole English -> Jamaican Creole */
- {"jam", HB_TAG('C','P','P',' ')}, /* Jamaican Creole English -> Creoles */
- {"jan", HB_TAG_NONE }, /* Jandai != Japanese */
- {"jax", HB_TAG('M','L','Y',' ')}, /* Jambi Malay -> Malay */
- {"jbe", HB_TAG('B','B','R',' ')}, /* Judeo-Berber -> Berber */
- {"jbn", HB_TAG('B','B','R',' ')}, /* Nafusi -> Berber */
-/*{"jbo", HB_TAG('J','B','O',' ')},*/ /* Lojban */
-/*{"jct", HB_TAG('J','C','T',' ')},*/ /* Krymchak */
- {"jgo", HB_TAG('B','M','L',' ')}, /* Ngomba -> Bamileke */
- {"ji", HB_TAG('J','I','I',' ')}, /* Yiddish (retired code) */
- {"jii", HB_TAG_NONE }, /* Jiiddu != Yiddish */
- {"jkm", HB_TAG('K','R','N',' ')}, /* Mobwa Karen -> Karen */
- {"jkp", HB_TAG('K','R','N',' ')}, /* Paku Karen -> Karen */
- {"jud", HB_TAG_NONE }, /* Worodougou != Ladino */
- {"jul", HB_TAG_NONE }, /* Jirel != Jula */
- {"jv", HB_TAG('J','A','V',' ')}, /* Javanese */
- {"jvd", HB_TAG('C','P','P',' ')}, /* Javindo -> Creoles */
- {"jw", HB_TAG('J','A','V',' ')}, /* Javanese (retired code) */
- {"ka", HB_TAG('K','A','T',' ')}, /* Georgian */
- {"kaa", HB_TAG('K','R','K',' ')}, /* Karakalpak */
- {"kab", HB_TAG('K','A','B','0')}, /* Kabyle */
- {"kab", HB_TAG('B','B','R',' ')}, /* Kabyle -> Berber */
- {"kac", HB_TAG_NONE }, /* Kachin != Kachchi */
- {"kam", HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */
- {"kar", HB_TAG('K','R','N',' ')}, /* Karen [collection] */
-/*{"kaw", HB_TAG('K','A','W',' ')},*/ /* Kawi (Old Javanese) */
- {"kbd", HB_TAG('K','A','B',' ')}, /* Kabardian */
- {"kby", HB_TAG('K','N','R',' ')}, /* Manga Kanuri -> Kanuri */
- {"kca", HB_TAG('K','H','K',' ')}, /* Khanty -> Khanty-Kazim */
- {"kca", HB_TAG('K','H','S',' ')}, /* Khanty -> Khanty-Shurishkar */
- {"kca", HB_TAG('K','H','V',' ')}, /* Khanty -> Khanty-Vakhi */
- {"kcn", HB_TAG('C','P','P',' ')}, /* Nubi -> Creoles */
-/*{"kde", HB_TAG('K','D','E',' ')},*/ /* Makonde */
- {"kdr", HB_TAG('K','R','M',' ')}, /* Karaim */
- {"kdt", HB_TAG('K','U','Y',' ')}, /* Kuy */
- {"kea", HB_TAG('K','E','A',' ')}, /* Kabuverdianu (Crioulo) */
- {"kea", HB_TAG('C','P','P',' ')}, /* Kabuverdianu -> Creoles */
- {"keb", HB_TAG_NONE }, /* Kélé != Kebena */
- {"kek", HB_TAG('K','E','K',' ')}, /* Kekchi */
- {"kek", HB_TAG('M','Y','N',' ')}, /* Kekchí -> Mayan */
- {"kex", HB_TAG('K','K','N',' ')}, /* Kukna -> Kokni */
- {"kfa", HB_TAG('K','O','D',' ')}, /* Kodava -> Kodagu */
- {"kfr", HB_TAG('K','A','C',' ')}, /* Kachhi -> Kachchi */
- {"kfx", HB_TAG('K','U','L',' ')}, /* Kullu Pahari -> Kulvi */
- {"kfy", HB_TAG('K','M','N',' ')}, /* Kumaoni */
- {"kg", HB_TAG('K','O','N','0')}, /* Kongo [macrolanguage] */
- {"kge", HB_TAG_NONE }, /* Komering != Khutsuri Georgian */
- {"kha", HB_TAG('K','S','I',' ')}, /* Khasi */
- {"khb", HB_TAG('X','B','D',' ')}, /* Lü */
- {"khk", HB_TAG('M','N','G',' ')}, /* Halh Mongolian -> Mongolian */
- {"khn", HB_TAG_NONE }, /* Khandesi != Khamti Shan (Microsoft fonts) */
- {"khs", HB_TAG_NONE }, /* Kasua != Khanty-Shurishkar */
- {"kht", HB_TAG('K','H','T',' ')}, /* Khamti -> Khamti Shan */
- {"kht", HB_TAG('K','H','N',' ')}, /* Khamti -> Khamti Shan (Microsoft fonts) */
- {"khv", HB_TAG_NONE }, /* Khvarshi != Khanty-Vakhi */
-/*{"khw", HB_TAG('K','H','W',' ')},*/ /* Khowar */
- {"ki", HB_TAG('K','I','K',' ')}, /* Kikuyu (Gikuyu) */
- {"kis", HB_TAG_NONE }, /* Kis != Kisii */
- {"kiu", HB_TAG('K','I','U',' ')}, /* Kirmanjki */
- {"kiu", HB_TAG('Z','Z','A',' ')}, /* Kirmanjki -> Zazaki */
- {"kj", HB_TAG('K','U','A',' ')}, /* Kuanyama */
- {"kjb", HB_TAG('M','Y','N',' ')}, /* Q'anjob'al -> Mayan */
-/*{"kjd", HB_TAG('K','J','D',' ')},*/ /* Southern Kiwai */
- {"kjh", HB_TAG('K','H','A',' ')}, /* Khakas -> Khakass */
- {"kjp", HB_TAG('K','J','P',' ')}, /* Pwo Eastern Karen -> Eastern Pwo Karen */
- {"kjp", HB_TAG('K','R','N',' ')}, /* Pwo Eastern Karen -> Karen */
- {"kjt", HB_TAG('K','R','N',' ')}, /* Phrae Pwo Karen -> Karen */
-/*{"kjz", HB_TAG('K','J','Z',' ')},*/ /* Bumthangkha */
- {"kk", HB_TAG('K','A','Z',' ')}, /* Kazakh */
- {"kkn", HB_TAG_NONE }, /* Kon Keu != Kokni */
- {"kkz", HB_TAG('A','T','H',' ')}, /* Kaska -> Athapaskan */
- {"kl", HB_TAG('G','R','N',' ')}, /* Greenlandic */
- {"klm", HB_TAG_NONE }, /* Migum != Kalmyk */
- {"kln", HB_TAG('K','A','L',' ')}, /* Kalenjin [macrolanguage] */
- {"km", HB_TAG('K','H','M',' ')}, /* Khmer */
- {"kmb", HB_TAG('M','B','N',' ')}, /* Kimbundu -> Mbundu */
- {"kmn", HB_TAG_NONE }, /* Awtuw != Kumaoni */
- {"kmo", HB_TAG_NONE }, /* Kwoma != Komo */
- {"kmr", HB_TAG('K','U','R',' ')}, /* Northern Kurdish -> Kurdish */
- {"kms", HB_TAG_NONE }, /* Kamasau != Komso */
- {"kmv", HB_TAG('C','P','P',' ')}, /* Karipúna Creole French -> Creoles */
- {"kmw", HB_TAG('K','M','O',' ')}, /* Komo (Democratic Republic of Congo) */
-/*{"kmz", HB_TAG('K','M','Z',' ')},*/ /* Khorasani Turkish -> Khorasani Turkic */
- {"kn", HB_TAG('K','A','N',' ')}, /* Kannada */
- {"knc", HB_TAG('K','N','R',' ')}, /* Central Kanuri -> Kanuri */
- {"kng", HB_TAG('K','O','N','0')}, /* Koongo -> Kongo */
- {"knj", HB_TAG('M','Y','N',' ')}, /* Western Kanjobal -> Mayan */
- {"knn", HB_TAG('K','O','K',' ')}, /* Konkani */
- {"knr", HB_TAG_NONE }, /* Kaningra != Kanuri */
- {"ko", HB_TAG('K','O','R',' ')}, /* Korean */
- {"ko", HB_TAG('K','O','H',' ')}, /* Korean -> Korean Old Hangul */
- {"kod", HB_TAG_NONE }, /* Kodi != Kodagu */
- {"koh", HB_TAG_NONE }, /* Koyo != Korean Old Hangul */
- {"koi", HB_TAG('K','O','P',' ')}, /* Komi-Permyak */
- {"koi", HB_TAG('K','O','M',' ')}, /* Komi-Permyak -> Komi */
-/*{"kok", HB_TAG('K','O','K',' ')},*/ /* Konkani [macrolanguage] */
- {"kop", HB_TAG_NONE }, /* Waube != Komi-Permyak */
-/*{"kos", HB_TAG('K','O','S',' ')},*/ /* Kosraean */
- {"koy", HB_TAG('A','T','H',' ')}, /* Koyukon -> Athapaskan */
- {"koz", HB_TAG_NONE }, /* Korak != Komi-Zyrian */
- {"kpe", HB_TAG('K','P','L',' ')}, /* Kpelle [macrolanguage] */
- {"kpl", HB_TAG_NONE }, /* Kpala != Kpelle */
- {"kpp", HB_TAG('K','R','N',' ')}, /* Paku Karen (retired code) -> Karen */
- {"kpv", HB_TAG('K','O','Z',' ')}, /* Komi-Zyrian */
- {"kpv", HB_TAG('K','O','M',' ')}, /* Komi-Zyrian -> Komi */
- {"kpy", HB_TAG('K','Y','K',' ')}, /* Koryak */
- {"kqs", HB_TAG('K','I','S',' ')}, /* Northern Kissi -> Kisii */
- {"kqy", HB_TAG('K','R','T',' ')}, /* Koorete */
- {"kr", HB_TAG('K','N','R',' ')}, /* Kanuri [macrolanguage] */
- {"krc", HB_TAG('K','A','R',' ')}, /* Karachay-Balkar -> Karachay */
- {"krc", HB_TAG('B','A','L',' ')}, /* Karachay-Balkar -> Balkar */
- {"kri", HB_TAG('K','R','I',' ')}, /* Krio */
- {"kri", HB_TAG('C','P','P',' ')}, /* Krio -> Creoles */
- {"krk", HB_TAG_NONE }, /* Kerek != Karakalpak */
-/*{"krl", HB_TAG('K','R','L',' ')},*/ /* Karelian */
- {"krm", HB_TAG_NONE }, /* Krim (retired code) != Karaim */
- {"krn", HB_TAG_NONE }, /* Sapo != Karen */
- {"krt", HB_TAG('K','N','R',' ')}, /* Tumari Kanuri -> Kanuri */
- {"kru", HB_TAG('K','U','U',' ')}, /* Kurukh */
- {"ks", HB_TAG('K','S','H',' ')}, /* Kashmiri */
- {"ksh", HB_TAG('K','S','H','0')}, /* Kölsch -> Ripuarian */
- {"ksi", HB_TAG_NONE }, /* Krisa != Khasi */
- {"ksm", HB_TAG_NONE }, /* Kumba != Kildin Sami */
- {"kss", HB_TAG('K','I','S',' ')}, /* Southern Kisi -> Kisii */
- {"ksw", HB_TAG('K','S','W',' ')}, /* S’gaw Karen */
- {"ksw", HB_TAG('K','R','N',' ')}, /* S'gaw Karen -> Karen */
- {"ktb", HB_TAG('K','E','B',' ')}, /* Kambaata -> Kebena */
- {"ktu", HB_TAG('K','O','N',' ')}, /* Kituba (Democratic Republic of Congo) -> Kikongo */
- {"ktw", HB_TAG('A','T','H',' ')}, /* Kato -> Athapaskan */
- {"ku", HB_TAG('K','U','R',' ')}, /* Kurdish [macrolanguage] */
- {"kui", HB_TAG_NONE }, /* Kuikúro-Kalapálo != Kui */
- {"kul", HB_TAG_NONE }, /* Kulere != Kulvi */
-/*{"kum", HB_TAG('K','U','M',' ')},*/ /* Kumyk */
- {"kuu", HB_TAG('A','T','H',' ')}, /* Upper Kuskokwim -> Athapaskan */
- {"kuw", HB_TAG('B','A','D','0')}, /* Kpagua -> Banda */
- {"kuy", HB_TAG_NONE }, /* Kuuku-Ya'u != Kuy */
- {"kv", HB_TAG('K','O','M',' ')}, /* Komi [macrolanguage] */
- {"kvb", HB_TAG('M','L','Y',' ')}, /* Kubu -> Malay */
- {"kvl", HB_TAG('K','R','N',' ')}, /* Kayaw -> Karen */
- {"kvq", HB_TAG('K','R','N',' ')}, /* Geba Karen -> Karen */
- {"kvr", HB_TAG('M','L','Y',' ')}, /* Kerinci -> Malay */
- {"kvt", HB_TAG('K','R','N',' ')}, /* Lahta Karen -> Karen */
- {"kvu", HB_TAG('K','R','N',' ')}, /* Yinbaw Karen -> Karen */
- {"kvy", HB_TAG('K','R','N',' ')}, /* Yintale Karen -> Karen */
- {"kw", HB_TAG('C','O','R',' ')}, /* Cornish */
-/*{"kwk", HB_TAG('K','W','K',' ')},*/ /* Kwakiutl -> Kwakʼwala */
- {"kww", HB_TAG('C','P','P',' ')}, /* Kwinti -> Creoles */
- {"kwy", HB_TAG('K','O','N','0')}, /* San Salvador Kongo -> Kongo */
- {"kxc", HB_TAG('K','M','S',' ')}, /* Konso -> Komso */
- {"kxd", HB_TAG('M','L','Y',' ')}, /* Brunei -> Malay */
- {"kxf", HB_TAG('K','R','N',' ')}, /* Manumanaw Karen -> Karen */
- {"kxk", HB_TAG('K','R','N',' ')}, /* Zayein Karen -> Karen */
- {"kxl", HB_TAG('K','U','U',' ')}, /* Nepali Kurux (retired code) -> Kurukh */
- {"kxu", HB_TAG('K','U','I',' ')}, /* Kui (India) (retired code) */
- {"ky", HB_TAG('K','I','R',' ')}, /* Kirghiz (Kyrgyz) */
- {"kyk", HB_TAG_NONE }, /* Kamayo != Koryak */
- {"kyu", HB_TAG('K','Y','U',' ')}, /* Western Kayah */
- {"kyu", HB_TAG('K','R','N',' ')}, /* Western Kayah -> Karen */
- {"la", HB_TAG('L','A','T',' ')}, /* Latin */
- {"lac", HB_TAG('M','Y','N',' ')}, /* Lacandon -> Mayan */
- {"lad", HB_TAG('J','U','D',' ')}, /* Ladino */
- {"lah", HB_TAG_NONE }, /* Lahnda [macrolanguage] != Lahuli */
- {"lak", HB_TAG_NONE }, /* Laka (Nigeria) (retired code) != Lak */
- {"lam", HB_TAG_NONE }, /* Lamba != Lambani */
- {"laz", HB_TAG_NONE }, /* Aribwatsa != Laz */
- {"lb", HB_TAG('L','T','Z',' ')}, /* Luxembourgish */
- {"lbe", HB_TAG('L','A','K',' ')}, /* Lak */
- {"lbj", HB_TAG('L','D','K',' ')}, /* Ladakhi */
- {"lbl", HB_TAG('B','I','K',' ')}, /* Libon Bikol -> Bikol */
- {"lce", HB_TAG('M','L','Y',' ')}, /* Loncong -> Malay */
- {"lcf", HB_TAG('M','L','Y',' ')}, /* Lubu -> Malay */
- {"ldi", HB_TAG('K','O','N','0')}, /* Laari -> Kongo */
- {"ldk", HB_TAG_NONE }, /* Leelau != Ladakhi */
-/*{"lef", HB_TAG('L','E','F',' ')},*/ /* Lelemi */
-/*{"lez", HB_TAG('L','E','Z',' ')},*/ /* Lezghian -> Lezgi */
- {"lg", HB_TAG('L','U','G',' ')}, /* Ganda */
- {"li", HB_TAG('L','I','M',' ')}, /* Limburgish */
- {"lif", HB_TAG('L','M','B',' ')}, /* Limbu */
-/*{"lij", HB_TAG('L','I','J',' ')},*/ /* Ligurian */
- {"lir", HB_TAG('C','P','P',' ')}, /* Liberian English -> Creoles */
-/*{"lis", HB_TAG('L','I','S',' ')},*/ /* Lisu */
- {"liw", HB_TAG('M','L','Y',' ')}, /* Col -> Malay */
- {"liy", HB_TAG('B','A','D','0')}, /* Banda-Bambari -> Banda */
-/*{"ljp", HB_TAG('L','J','P',' ')},*/ /* Lampung Api -> Lampung */
- {"lkb", HB_TAG('L','U','H',' ')}, /* Kabras -> Luyia */
-/*{"lki", HB_TAG('L','K','I',' ')},*/ /* Laki */
- {"lko", HB_TAG('L','U','H',' ')}, /* Khayo -> Luyia */
- {"lks", HB_TAG('L','U','H',' ')}, /* Kisa -> Luyia */
- {"lld", HB_TAG('L','A','D',' ')}, /* Ladin */
- {"lma", HB_TAG_NONE }, /* East Limba != Low Mari */
- {"lmb", HB_TAG_NONE }, /* Merei != Limbu */
- {"lmn", HB_TAG('L','A','M',' ')}, /* Lambadi -> Lambani */
-/*{"lmo", HB_TAG('L','M','O',' ')},*/ /* Lombard */
- {"lmw", HB_TAG_NONE }, /* Lake Miwok != Lomwe */
- {"ln", HB_TAG('L','I','N',' ')}, /* Lingala */
- {"lna", HB_TAG('B','A','D','0')}, /* Langbashe -> Banda */
- {"lnl", HB_TAG('B','A','D','0')}, /* South Central Banda -> Banda */
- {"lo", HB_TAG('L','A','O',' ')}, /* Lao */
-/*{"lom", HB_TAG('L','O','M',' ')},*/ /* Loma (Liberia) */
- {"lou", HB_TAG('C','P','P',' ')}, /* Louisiana Creole -> Creoles */
-/*{"lpo", HB_TAG('L','P','O',' ')},*/ /* Lipo */
-/*{"lrc", HB_TAG('L','R','C',' ')},*/ /* Northern Luri -> Luri */
- {"lri", HB_TAG('L','U','H',' ')}, /* Marachi -> Luyia */
- {"lrm", HB_TAG('L','U','H',' ')}, /* Marama -> Luyia */
- {"lrt", HB_TAG('C','P','P',' ')}, /* Larantuka Malay -> Creoles */
- {"lsb", HB_TAG_NONE }, /* Burundian Sign Language != Lower Sorbian */
- {"lsm", HB_TAG('L','U','H',' ')}, /* Saamia -> Luyia */
- {"lt", HB_TAG('L','T','H',' ')}, /* Lithuanian */
- {"ltg", HB_TAG('L','V','I',' ')}, /* Latgalian -> Latvian */
- {"lth", HB_TAG_NONE }, /* Thur != Lithuanian */
- {"lto", HB_TAG('L','U','H',' ')}, /* Tsotso -> Luyia */
- {"lts", HB_TAG('L','U','H',' ')}, /* Tachoni -> Luyia */
- {"lu", HB_TAG('L','U','B',' ')}, /* Luba-Katanga */
-/*{"lua", HB_TAG('L','U','A',' ')},*/ /* Luba-Lulua */
-/*{"luo", HB_TAG('L','U','O',' ')},*/ /* Luo (Kenya and Tanzania) */
- {"lus", HB_TAG('M','I','Z',' ')}, /* Lushai -> Mizo */
- {"lus", HB_TAG('Q','I','N',' ')}, /* Lushai -> Chin */
- {"luy", HB_TAG('L','U','H',' ')}, /* Luyia [macrolanguage] */
- {"luz", HB_TAG('L','R','C',' ')}, /* Southern Luri -> Luri */
- {"lv", HB_TAG('L','V','I',' ')}, /* Latvian [macrolanguage] */
- {"lvi", HB_TAG_NONE }, /* Lavi != Latvian */
- {"lvs", HB_TAG('L','V','I',' ')}, /* Standard Latvian -> Latvian */
- {"lwg", HB_TAG('L','U','H',' ')}, /* Wanga -> Luyia */
- {"lzh", HB_TAG('Z','H','T',' ')}, /* Literary Chinese -> Chinese, Traditional */
- {"lzz", HB_TAG('L','A','Z',' ')}, /* Laz */
-/*{"mad", HB_TAG('M','A','D',' ')},*/ /* Madurese -> Madura */
-/*{"mag", HB_TAG('M','A','G',' ')},*/ /* Magahi */
- {"mai", HB_TAG('M','T','H',' ')}, /* Maithili */
- {"maj", HB_TAG_NONE }, /* Jalapa De Díaz Mazatec != Majang */
- {"mak", HB_TAG('M','K','R',' ')}, /* Makasar */
- {"mam", HB_TAG('M','A','M',' ')}, /* Mam */
- {"mam", HB_TAG('M','Y','N',' ')}, /* Mam -> Mayan */
- {"man", HB_TAG('M','N','K',' ')}, /* Mandingo [macrolanguage] -> Maninka */
- {"map", HB_TAG_NONE }, /* Austronesian [collection] != Mapudungun */
- {"maw", HB_TAG_NONE }, /* Mampruli != Marwari */
- {"max", HB_TAG('M','L','Y',' ')}, /* North Moluccan Malay -> Malay */
- {"max", HB_TAG('C','P','P',' ')}, /* North Moluccan Malay -> Creoles */
- {"mbf", HB_TAG('C','P','P',' ')}, /* Baba Malay -> Creoles */
- {"mbn", HB_TAG_NONE }, /* Macaguán != Mbundu */
-/*{"mbo", HB_TAG('M','B','O',' ')},*/ /* Mbo (Cameroon) */
- {"mch", HB_TAG_NONE }, /* Maquiritari != Manchu */
- {"mcm", HB_TAG('C','P','P',' ')}, /* Malaccan Creole Portuguese -> Creoles */
- {"mcr", HB_TAG_NONE }, /* Menya != Moose Cree */
- {"mct", HB_TAG('B','T','I',' ')}, /* Mengisa -> Beti */
- {"mde", HB_TAG_NONE }, /* Maba (Chad) != Mende */
- {"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) */
- {"meo", HB_TAG('M','L','Y',' ')}, /* Kedah Malay -> Malay */
-/*{"mer", HB_TAG('M','E','R',' ')},*/ /* Meru */
- {"mfa", HB_TAG('M','F','A',' ')}, /* Pattani Malay */
- {"mfa", HB_TAG('M','L','Y',' ')}, /* Pattani Malay -> Malay */
- {"mfb", HB_TAG('M','L','Y',' ')}, /* Bangka -> Malay */
- {"mfe", HB_TAG('M','F','E',' ')}, /* Morisyen */
- {"mfe", HB_TAG('C','P','P',' ')}, /* Morisyen -> Creoles */
- {"mfp", HB_TAG('C','P','P',' ')}, /* Makassar Malay -> Creoles */
- {"mg", HB_TAG('M','L','G',' ')}, /* Malagasy [macrolanguage] */
- {"mh", HB_TAG('M','A','H',' ')}, /* Marshallese */
- {"mhc", HB_TAG('M','Y','N',' ')}, /* Mocho -> Mayan */
- {"mhr", HB_TAG('L','M','A',' ')}, /* Eastern Mari -> Low Mari */
- {"mhv", HB_TAG('A','R','K',' ')}, /* Arakanese (retired code) -> Rakhine */
- {"mi", HB_TAG('M','R','I',' ')}, /* Maori */
- {"min", HB_TAG('M','I','N',' ')}, /* Minangkabau */
- {"min", HB_TAG('M','L','Y',' ')}, /* Minangkabau -> Malay */
- {"miz", HB_TAG_NONE }, /* Coatzospan Mixtec != Mizo */
- {"mk", HB_TAG('M','K','D',' ')}, /* Macedonian */
- {"mkn", HB_TAG('C','P','P',' ')}, /* Kupang Malay -> Creoles */
- {"mkr", HB_TAG_NONE }, /* Malas != Makasar */
- {"mku", HB_TAG('M','N','K',' ')}, /* Konyanka Maninka -> Maninka */
-/*{"mkw", HB_TAG('M','K','W',' ')},*/ /* Kituba (Congo) */
- {"ml", HB_TAG('M','A','L',' ')}, /* Malayalam -> Malayalam Traditional */
- {"ml", HB_TAG('M','L','R',' ')}, /* Malayalam -> Malayalam Reformed */
- {"mle", HB_TAG_NONE }, /* Manambu != Male */
- {"mln", HB_TAG_NONE }, /* Malango != Malinke */
- {"mlq", HB_TAG('M','L','N',' ')}, /* Western Maninkakan -> Malinke */
- {"mlq", HB_TAG('M','N','K',' ')}, /* Western Maninkakan -> Maninka */
- {"mlr", HB_TAG_NONE }, /* Vame != Malayalam Reformed */
- {"mmr", HB_TAG('H','M','N',' ')}, /* Western Xiangxi Miao -> Hmong */
- {"mn", HB_TAG('M','N','G',' ')}, /* Mongolian [macrolanguage] */
- {"mnc", HB_TAG('M','C','H',' ')}, /* Manchu */
- {"mnd", HB_TAG_NONE }, /* Mondé != Mandinka */
- {"mng", HB_TAG_NONE }, /* Eastern Mnong != Mongolian */
- {"mnh", HB_TAG('B','A','D','0')}, /* Mono (Democratic Republic of Congo) -> Banda */
-/*{"mni", HB_TAG('M','N','I',' ')},*/ /* Manipuri */
- {"mnk", HB_TAG('M','N','D',' ')}, /* Mandinka */
- {"mnk", HB_TAG('M','N','K',' ')}, /* Mandinka -> Maninka */
- {"mnp", HB_TAG('Z','H','S',' ')}, /* Min Bei Chinese -> Chinese, Simplified */
- {"mns", HB_TAG('M','A','N',' ')}, /* Mansi */
- {"mnw", HB_TAG('M','O','N',' ')}, /* Mon */
- {"mnw", HB_TAG('M','O','N','T')}, /* Mon -> Thailand Mon */
- {"mnx", HB_TAG_NONE }, /* Manikion != Manx */
- {"mo", HB_TAG('M','O','L',' ')}, /* Moldavian (retired code) */
- {"mo", HB_TAG('R','O','M',' ')}, /* Moldavian (retired code) -> Romanian */
- {"mod", HB_TAG('C','P','P',' ')}, /* Mobilian -> Creoles */
-/*{"moh", HB_TAG('M','O','H',' ')},*/ /* Mohawk */
- {"mok", HB_TAG_NONE }, /* Morori != Moksha */
- {"mop", HB_TAG('M','Y','N',' ')}, /* Mopán Maya -> Mayan */
- {"mor", HB_TAG_NONE }, /* Moro != Moroccan */
-/*{"mos", HB_TAG('M','O','S',' ')},*/ /* Mossi */
- {"mpe", HB_TAG('M','A','J',' ')}, /* Majang */
- {"mqg", HB_TAG('M','L','Y',' ')}, /* Kota Bangun Kutai Malay -> Malay */
- {"mr", HB_TAG('M','A','R',' ')}, /* Marathi */
- {"mrh", HB_TAG('Q','I','N',' ')}, /* Mara Chin -> Chin */
- {"mrj", HB_TAG('H','M','A',' ')}, /* Western Mari -> High Mari */
- {"ms", HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */
- {"msc", HB_TAG('M','N','K',' ')}, /* Sankaran Maninka -> Maninka */
- {"msh", HB_TAG('M','L','G',' ')}, /* Masikoro Malagasy -> Malagasy */
- {"msi", HB_TAG('M','L','Y',' ')}, /* Sabah Malay -> Malay */
- {"msi", HB_TAG('C','P','P',' ')}, /* Sabah Malay -> Creoles */
- {"mt", HB_TAG('M','T','S',' ')}, /* Maltese */
- {"mth", HB_TAG_NONE }, /* Munggui != Maithili */
- {"mtr", HB_TAG('M','A','W',' ')}, /* Mewari -> Marwari */
- {"mts", HB_TAG_NONE }, /* Yora != Maltese */
- {"mud", HB_TAG('C','P','P',' ')}, /* Mednyj Aleut -> Creoles */
- {"mui", HB_TAG('M','L','Y',' ')}, /* Musi -> Malay */
- {"mun", HB_TAG_NONE }, /* Munda [collection] != Mundari */
- {"mup", HB_TAG('R','A','J',' ')}, /* Malvi -> Rajasthani */
- {"muq", HB_TAG('H','M','N',' ')}, /* Eastern Xiangxi Miao -> Hmong */
-/*{"mus", HB_TAG('M','U','S',' ')},*/ /* Creek -> Muscogee */
- {"mvb", HB_TAG('A','T','H',' ')}, /* Mattole -> Athapaskan */
- {"mve", HB_TAG('M','A','W',' ')}, /* Marwari (Pakistan) */
- {"mvf", HB_TAG('M','N','G',' ')}, /* Peripheral Mongolian -> Mongolian */
- {"mwk", HB_TAG('M','N','K',' ')}, /* Kita Maninkakan -> Maninka */
-/*{"mwl", HB_TAG('M','W','L',' ')},*/ /* Mirandese */
- {"mwq", HB_TAG('Q','I','N',' ')}, /* Mün Chin -> Chin */
- {"mwr", HB_TAG('M','A','W',' ')}, /* Marwari [macrolanguage] */
- {"mww", HB_TAG('M','W','W',' ')}, /* Hmong Daw */
- {"mww", HB_TAG('H','M','N',' ')}, /* Hmong Daw -> Hmong */
- {"my", HB_TAG('B','R','M',' ')}, /* Burmese */
- {"mym", HB_TAG('M','E','N',' ')}, /* Me’en */
-/*{"myn", HB_TAG('M','Y','N',' ')},*/ /* Mayan [collection] */
- {"myq", HB_TAG('M','N','K',' ')}, /* Forest Maninka (retired code) -> Maninka */
- {"myv", HB_TAG('E','R','Z',' ')}, /* Erzya */
- {"mzb", HB_TAG('B','B','R',' ')}, /* Tumzabt -> Berber */
-/*{"mzn", HB_TAG('M','Z','N',' ')},*/ /* Mazanderani */
- {"mzs", HB_TAG('C','P','P',' ')}, /* Macanese -> Creoles */
- {"na", HB_TAG('N','A','U',' ')}, /* Nauru -> Nauruan */
- {"nag", HB_TAG('N','A','G',' ')}, /* Naga Pidgin -> Naga-Assamese */
- {"nag", HB_TAG('C','P','P',' ')}, /* Naga Pidgin -> Creoles */
-/*{"nah", HB_TAG('N','A','H',' ')},*/ /* Nahuatl [collection] */
- {"nan", HB_TAG('Z','H','S',' ')}, /* Min Nan Chinese -> Chinese, Simplified */
-/*{"nap", HB_TAG('N','A','P',' ')},*/ /* Neapolitan */
- {"nas", HB_TAG_NONE }, /* Naasioi != Naskapi */
- {"naz", HB_TAG('N','A','H',' ')}, /* Coatepec Nahuatl -> Nahuatl */
- {"nb", HB_TAG('N','O','R',' ')}, /* Norwegian Bokmål -> Norwegian */
- {"nch", HB_TAG('N','A','H',' ')}, /* Central Huasteca Nahuatl -> Nahuatl */
- {"nci", HB_TAG('N','A','H',' ')}, /* Classical Nahuatl -> Nahuatl */
- {"ncj", HB_TAG('N','A','H',' ')}, /* Northern Puebla Nahuatl -> Nahuatl */
- {"ncl", HB_TAG('N','A','H',' ')}, /* Michoacán Nahuatl -> Nahuatl */
- {"ncr", HB_TAG_NONE }, /* Ncane != N-Cree */
- {"ncx", HB_TAG('N','A','H',' ')}, /* Central Puebla Nahuatl -> Nahuatl */
- {"nd", HB_TAG('N','D','B',' ')}, /* North Ndebele -> Ndebele */
- {"ndb", HB_TAG_NONE }, /* Kenswei Nsei != Ndebele */
-/*{"ndc", HB_TAG('N','D','C',' ')},*/ /* Ndau */
- {"ndg", HB_TAG_NONE }, /* Ndengereko != Ndonga */
-/*{"nds", HB_TAG('N','D','S',' ')},*/ /* Low Saxon */
- {"ne", HB_TAG('N','E','P',' ')}, /* Nepali [macrolanguage] */
- {"nef", HB_TAG('C','P','P',' ')}, /* Nefamese -> Creoles */
-/*{"new", HB_TAG('N','E','W',' ')},*/ /* Newari */
- {"ng", HB_TAG('N','D','G',' ')}, /* Ndonga */
-/*{"nga", HB_TAG('N','G','A',' ')},*/ /* Ngbaka */
- {"ngl", HB_TAG('L','M','W',' ')}, /* Lomwe */
- {"ngm", HB_TAG('C','P','P',' ')}, /* Ngatik Men's Creole -> Creoles */
- {"ngo", HB_TAG('S','X','T',' ')}, /* Ngoni (retired code) -> Sutu */
- {"ngr", HB_TAG_NONE }, /* Engdewu != Nagari */
- {"ngu", HB_TAG('N','A','H',' ')}, /* Guerrero Nahuatl -> Nahuatl */
- {"nhc", HB_TAG('N','A','H',' ')}, /* Tabasco Nahuatl -> Nahuatl */
- {"nhd", HB_TAG('G','U','A',' ')}, /* Chiripá -> Guarani */
- {"nhe", HB_TAG('N','A','H',' ')}, /* Eastern Huasteca Nahuatl -> Nahuatl */
- {"nhg", HB_TAG('N','A','H',' ')}, /* Tetelcingo Nahuatl -> Nahuatl */
- {"nhi", HB_TAG('N','A','H',' ')}, /* Zacatlán-Ahuacatlán-Tepetzintla Nahuatl -> Nahuatl */
- {"nhk", HB_TAG('N','A','H',' ')}, /* Isthmus-Cosoleacaque Nahuatl -> Nahuatl */
- {"nhm", HB_TAG('N','A','H',' ')}, /* Morelos Nahuatl -> Nahuatl */
- {"nhn", HB_TAG('N','A','H',' ')}, /* Central Nahuatl -> Nahuatl */
- {"nhp", HB_TAG('N','A','H',' ')}, /* Isthmus-Pajapan Nahuatl -> Nahuatl */
- {"nhq", HB_TAG('N','A','H',' ')}, /* Huaxcaleca Nahuatl -> Nahuatl */
- {"nht", HB_TAG('N','A','H',' ')}, /* Ometepec Nahuatl -> Nahuatl */
- {"nhv", HB_TAG('N','A','H',' ')}, /* Temascaltepec Nahuatl -> Nahuatl */
- {"nhw", HB_TAG('N','A','H',' ')}, /* Western Huasteca Nahuatl -> Nahuatl */
- {"nhx", HB_TAG('N','A','H',' ')}, /* Isthmus-Mecayapan Nahuatl -> Nahuatl */
- {"nhy", HB_TAG('N','A','H',' ')}, /* Northern Oaxaca Nahuatl -> Nahuatl */
- {"nhz", HB_TAG('N','A','H',' ')}, /* Santa María La Alta Nahuatl -> Nahuatl */
- {"niq", HB_TAG('K','A','L',' ')}, /* Nandi -> Kalenjin */
- {"nis", HB_TAG_NONE }, /* Nimi != Nisi */
-/*{"niu", HB_TAG('N','I','U',' ')},*/ /* Niuean */
- {"niv", HB_TAG('G','I','L',' ')}, /* Gilyak */
- {"njt", HB_TAG('C','P','P',' ')}, /* Ndyuka-Trio Pidgin -> Creoles */
- {"njz", HB_TAG('N','I','S',' ')}, /* Nyishi -> Nisi */
- {"nko", HB_TAG_NONE }, /* Nkonya != N’Ko */
- {"nkx", HB_TAG('I','J','O',' ')}, /* Nkoroo -> Ijo */
- {"nl", HB_TAG('N','L','D',' ')}, /* Dutch */
- {"nla", HB_TAG('B','M','L',' ')}, /* Ngombale -> Bamileke */
- {"nle", HB_TAG('L','U','H',' ')}, /* East Nyala -> Luyia */
- {"nln", HB_TAG('N','A','H',' ')}, /* Durango Nahuatl (retired code) -> Nahuatl */
- {"nlv", HB_TAG('N','A','H',' ')}, /* Orizaba Nahuatl -> Nahuatl */
- {"nn", HB_TAG('N','Y','N',' ')}, /* Norwegian Nynorsk (Nynorsk, Norwegian) */
- {"nnh", HB_TAG('B','M','L',' ')}, /* Ngiemboon -> Bamileke */
- {"nnz", HB_TAG('B','M','L',' ')}, /* Nda'nda' -> Bamileke */
- {"no", HB_TAG('N','O','R',' ')}, /* Norwegian [macrolanguage] */
- {"nod", HB_TAG('N','T','A',' ')}, /* Northern Thai -> Northern Tai */
-/*{"noe", HB_TAG('N','O','E',' ')},*/ /* Nimadi */
-/*{"nog", HB_TAG('N','O','G',' ')},*/ /* Nogai */
-/*{"nov", HB_TAG('N','O','V',' ')},*/ /* Novial */
- {"npi", HB_TAG('N','E','P',' ')}, /* Nepali */
- {"npl", HB_TAG('N','A','H',' ')}, /* Southeastern Puebla Nahuatl -> Nahuatl */
- {"nqo", HB_TAG('N','K','O',' ')}, /* N’Ko */
- {"nr", HB_TAG('N','D','B',' ')}, /* South Ndebele -> Ndebele */
- {"nsk", HB_TAG('N','A','S',' ')}, /* Naskapi */
- {"nsm", HB_TAG_NONE }, /* Sumi Naga != Northern Sami */
-/*{"nso", HB_TAG('N','S','O',' ')},*/ /* Northern Sotho */
- {"nsu", HB_TAG('N','A','H',' ')}, /* Sierra Negra Nahuatl -> Nahuatl */
- {"nto", HB_TAG_NONE }, /* Ntomba != Esperanto */
- {"nue", HB_TAG('B','A','D','0')}, /* Ngundu -> Banda */
- {"nuu", HB_TAG('B','A','D','0')}, /* Ngbundu -> Banda */
- {"nuz", HB_TAG('N','A','H',' ')}, /* Tlamacazapa Nahuatl -> Nahuatl */
- {"nv", HB_TAG('N','A','V',' ')}, /* Navajo */
- {"nv", HB_TAG('A','T','H',' ')}, /* Navajo -> Athapaskan */
- {"nwe", HB_TAG('B','M','L',' ')}, /* Ngwe -> Bamileke */
- {"ny", HB_TAG('C','H','I',' ')}, /* Chichewa (Chewa, Nyanja) */
- {"nyd", HB_TAG('L','U','H',' ')}, /* Nyore -> Luyia */
-/*{"nym", HB_TAG('N','Y','M',' ')},*/ /* Nyamwezi */
- {"nyn", HB_TAG('N','K','L',' ')}, /* Nyankole */
-/*{"nza", HB_TAG('N','Z','A',' ')},*/ /* Tigon Mbembe -> Mbembe Tigon */
- {"oc", HB_TAG('O','C','I',' ')}, /* Occitan (post 1500) */
- {"oj", HB_TAG('O','J','B',' ')}, /* Ojibwa [macrolanguage] -> Ojibway */
-/*{"ojb", HB_TAG('O','J','B',' ')},*/ /* Northwestern Ojibwa -> Ojibway */
- {"ojc", HB_TAG('O','J','B',' ')}, /* Central Ojibwa -> Ojibway */
- {"ojg", HB_TAG('O','J','B',' ')}, /* Eastern Ojibwa -> Ojibway */
- {"ojs", HB_TAG('O','C','R',' ')}, /* Severn Ojibwa -> Oji-Cree */
- {"ojs", HB_TAG('O','J','B',' ')}, /* Severn Ojibwa -> Ojibway */
- {"ojw", HB_TAG('O','J','B',' ')}, /* Western Ojibwa -> Ojibway */
- {"okd", HB_TAG('I','J','O',' ')}, /* Okodia -> Ijo */
- {"oki", HB_TAG('K','A','L',' ')}, /* Okiek -> Kalenjin */
- {"okm", HB_TAG('K','O','H',' ')}, /* Middle Korean (10th-16th cent.) -> Korean Old Hangul */
- {"okr", HB_TAG('I','J','O',' ')}, /* Kirike -> Ijo */
- {"om", HB_TAG('O','R','O',' ')}, /* Oromo [macrolanguage] */
- {"onx", HB_TAG('C','P','P',' ')}, /* Onin Based Pidgin -> Creoles */
- {"oor", HB_TAG('C','P','P',' ')}, /* Oorlams -> Creoles */
- {"or", HB_TAG('O','R','I',' ')}, /* Odia (formerly Oriya) [macrolanguage] */
- {"orc", HB_TAG('O','R','O',' ')}, /* Orma -> Oromo */
- {"orn", HB_TAG('M','L','Y',' ')}, /* Orang Kanaq -> Malay */
- {"oro", HB_TAG_NONE }, /* Orokolo != Oromo */
- {"orr", HB_TAG('I','J','O',' ')}, /* Oruma -> Ijo */
- {"ors", HB_TAG('M','L','Y',' ')}, /* Orang Seletar -> Malay */
- {"ory", HB_TAG('O','R','I',' ')}, /* Odia (formerly Oriya) */
- {"os", HB_TAG('O','S','S',' ')}, /* Ossetian */
- {"otw", HB_TAG('O','J','B',' ')}, /* Ottawa -> Ojibway */
- {"oua", HB_TAG('B','B','R',' ')}, /* Tagargrent -> Berber */
- {"pa", HB_TAG('P','A','N',' ')}, /* Punjabi */
- {"paa", HB_TAG_NONE }, /* Papuan [collection] != Palestinian Aramaic */
-/*{"pag", HB_TAG('P','A','G',' ')},*/ /* Pangasinan */
- {"pal", HB_TAG_NONE }, /* Pahlavi != Pali */
-/*{"pam", HB_TAG('P','A','M',' ')},*/ /* Pampanga -> Pampangan */
- {"pap", HB_TAG('P','A','P','0')}, /* Papiamento -> Papiamentu */
- {"pap", HB_TAG('C','P','P',' ')}, /* Papiamento -> Creoles */
- {"pas", HB_TAG_NONE }, /* Papasena != Pashto */
-/*{"pau", HB_TAG('P','A','U',' ')},*/ /* Palauan */
- {"pbt", HB_TAG('P','A','S',' ')}, /* Southern Pashto -> Pashto */
- {"pbu", HB_TAG('P','A','S',' ')}, /* Northern Pashto -> Pashto */
-/*{"pcc", HB_TAG('P','C','C',' ')},*/ /* Bouyei */
-/*{"pcd", HB_TAG('P','C','D',' ')},*/ /* Picard */
- {"pce", HB_TAG('P','L','G',' ')}, /* Ruching Palaung -> Palaung */
- {"pck", HB_TAG('Q','I','N',' ')}, /* Paite Chin -> Chin */
- {"pcm", HB_TAG('C','P','P',' ')}, /* Nigerian Pidgin -> Creoles */
-/*{"pdc", HB_TAG('P','D','C',' ')},*/ /* Pennsylvania German */
- {"pdu", HB_TAG('K','R','N',' ')}, /* Kayan -> Karen */
- {"pea", HB_TAG('C','P','P',' ')}, /* Peranakan Indonesian -> Creoles */
- {"pel", HB_TAG('M','L','Y',' ')}, /* Pekal -> Malay */
- {"pes", HB_TAG('F','A','R',' ')}, /* Iranian Persian -> Persian */
- {"pey", HB_TAG('C','P','P',' ')}, /* Petjo -> Creoles */
- {"pga", HB_TAG('A','R','A',' ')}, /* Sudanese Creole Arabic -> Arabic */
- {"pga", HB_TAG('C','P','P',' ')}, /* Sudanese Creole Arabic -> Creoles */
-/*{"phk", HB_TAG('P','H','K',' ')},*/ /* Phake */
- {"pi", HB_TAG('P','A','L',' ')}, /* Pali */
- {"pih", HB_TAG('P','I','H',' ')}, /* Pitcairn-Norfolk -> Norfolk */
- {"pih", HB_TAG('C','P','P',' ')}, /* Pitcairn-Norfolk -> Creoles */
- {"pil", HB_TAG_NONE }, /* Yom != Filipino */
- {"pis", HB_TAG('C','P','P',' ')}, /* Pijin -> Creoles */
- {"pkh", HB_TAG('Q','I','N',' ')}, /* Pankhu -> Chin */
- {"pko", HB_TAG('K','A','L',' ')}, /* Pökoot -> Kalenjin */
- {"pl", HB_TAG('P','L','K',' ')}, /* Polish */
- {"plg", HB_TAG_NONE }, /* Pilagá != Palaung */
- {"plk", HB_TAG_NONE }, /* Kohistani Shina != Polish */
- {"pll", HB_TAG('P','L','G',' ')}, /* Shwe Palaung -> Palaung */
- {"pln", HB_TAG('C','P','P',' ')}, /* Palenquero -> Creoles */
- {"plp", HB_TAG('P','A','P',' ')}, /* Palpa (retired code) */
- {"plt", HB_TAG('M','L','G',' ')}, /* Plateau Malagasy -> Malagasy */
- {"pml", HB_TAG('C','P','P',' ')}, /* Lingua Franca -> Creoles */
-/*{"pms", HB_TAG('P','M','S',' ')},*/ /* Piemontese */
- {"pmy", HB_TAG('C','P','P',' ')}, /* Papuan Malay -> Creoles */
-/*{"pnb", HB_TAG('P','N','B',' ')},*/ /* Western Panjabi */
- {"poc", HB_TAG('M','Y','N',' ')}, /* Poqomam -> Mayan */
- {"poh", HB_TAG('P','O','H',' ')}, /* Poqomchi' -> Pocomchi */
- {"poh", HB_TAG('M','Y','N',' ')}, /* Poqomchi' -> Mayan */
-/*{"pon", HB_TAG('P','O','N',' ')},*/ /* Pohnpeian */
- {"pov", HB_TAG('C','P','P',' ')}, /* Upper Guinea Crioulo -> Creoles */
- {"ppa", HB_TAG('B','A','G',' ')}, /* Pao (retired code) -> Baghelkhandi */
- {"pre", HB_TAG('C','P','P',' ')}, /* Principense -> Creoles */
-/*{"pro", HB_TAG('P','R','O',' ')},*/ /* Old Provençal (to 1500) -> Provençal / Old Provençal */
- {"prs", HB_TAG('D','R','I',' ')}, /* Dari */
- {"prs", HB_TAG('F','A','R',' ')}, /* Dari -> Persian */
- {"ps", HB_TAG('P','A','S',' ')}, /* Pashto [macrolanguage] */
- {"pse", HB_TAG('M','L','Y',' ')}, /* Central Malay -> Malay */
- {"pst", HB_TAG('P','A','S',' ')}, /* Central Pashto -> Pashto */
- {"pt", HB_TAG('P','T','G',' ')}, /* Portuguese */
- {"pub", HB_TAG('Q','I','N',' ')}, /* Purum -> Chin */
- {"puz", HB_TAG('Q','I','N',' ')}, /* Purum Naga (retired code) -> Chin */
- {"pwo", HB_TAG('P','W','O',' ')}, /* Pwo Western Karen -> Western Pwo Karen */
- {"pwo", HB_TAG('K','R','N',' ')}, /* Pwo Western Karen -> Karen */
- {"pww", HB_TAG('K','R','N',' ')}, /* Pwo Northern Karen -> Karen */
- {"qu", HB_TAG('Q','U','Z',' ')}, /* Quechua [macrolanguage] */
- {"qub", HB_TAG('Q','W','H',' ')}, /* Huallaga Huánuco Quechua -> Quechua (Peru) */
- {"qub", HB_TAG('Q','U','Z',' ')}, /* Huallaga Huánuco Quechua -> Quechua */
- {"quc", HB_TAG('Q','U','C',' ')}, /* K’iche’ */
- {"quc", HB_TAG('M','Y','N',' ')}, /* K'iche' -> Mayan */
- {"qud", HB_TAG('Q','V','I',' ')}, /* Calderón Highland Quichua -> Quechua (Ecuador) */
- {"qud", HB_TAG('Q','U','Z',' ')}, /* Calderón Highland Quichua -> Quechua */
- {"quf", HB_TAG('Q','U','Z',' ')}, /* Lambayeque Quechua -> Quechua */
- {"qug", HB_TAG('Q','V','I',' ')}, /* Chimborazo Highland Quichua -> Quechua (Ecuador) */
- {"qug", HB_TAG('Q','U','Z',' ')}, /* Chimborazo Highland Quichua -> Quechua */
- {"quh", HB_TAG('Q','U','H',' ')}, /* South Bolivian Quechua -> Quechua (Bolivia) */
- {"quh", HB_TAG('Q','U','Z',' ')}, /* South Bolivian Quechua -> Quechua */
- {"quk", HB_TAG('Q','U','Z',' ')}, /* Chachapoyas Quechua -> Quechua */
- {"qul", HB_TAG('Q','U','H',' ')}, /* North Bolivian Quechua -> Quechua (Bolivia) */
- {"qul", HB_TAG('Q','U','Z',' ')}, /* North Bolivian Quechua -> Quechua */
- {"qum", HB_TAG('M','Y','N',' ')}, /* Sipacapense -> Mayan */
- {"qup", HB_TAG('Q','V','I',' ')}, /* Southern Pastaza Quechua -> Quechua (Ecuador) */
- {"qup", HB_TAG('Q','U','Z',' ')}, /* Southern Pastaza Quechua -> Quechua */
- {"qur", HB_TAG('Q','W','H',' ')}, /* Yanahuanca Pasco Quechua -> Quechua (Peru) */
- {"qur", HB_TAG('Q','U','Z',' ')}, /* Yanahuanca Pasco Quechua -> Quechua */
- {"qus", HB_TAG('Q','U','H',' ')}, /* Santiago del Estero Quichua -> Quechua (Bolivia) */
- {"qus", HB_TAG('Q','U','Z',' ')}, /* Santiago del Estero Quichua -> Quechua */
- {"quv", HB_TAG('M','Y','N',' ')}, /* Sacapulteco -> Mayan */
- {"quw", HB_TAG('Q','V','I',' ')}, /* Tena Lowland Quichua -> Quechua (Ecuador) */
- {"quw", HB_TAG('Q','U','Z',' ')}, /* Tena Lowland Quichua -> Quechua */
- {"qux", HB_TAG('Q','W','H',' ')}, /* Yauyos Quechua -> Quechua (Peru) */
- {"qux", HB_TAG('Q','U','Z',' ')}, /* Yauyos Quechua -> Quechua */
- {"quy", HB_TAG('Q','U','Z',' ')}, /* Ayacucho Quechua -> Quechua */
-/*{"quz", HB_TAG('Q','U','Z',' ')},*/ /* Cusco Quechua -> Quechua */
- {"qva", HB_TAG('Q','W','H',' ')}, /* Ambo-Pasco Quechua -> Quechua (Peru) */
- {"qva", HB_TAG('Q','U','Z',' ')}, /* Ambo-Pasco Quechua -> Quechua */
- {"qvc", HB_TAG('Q','U','Z',' ')}, /* Cajamarca Quechua -> Quechua */
- {"qve", HB_TAG('Q','U','Z',' ')}, /* Eastern Apurímac Quechua -> Quechua */
- {"qvh", HB_TAG('Q','W','H',' ')}, /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua (Peru) */
- {"qvh", HB_TAG('Q','U','Z',' ')}, /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua */
- {"qvi", HB_TAG('Q','V','I',' ')}, /* Imbabura Highland Quichua -> Quechua (Ecuador) */
- {"qvi", HB_TAG('Q','U','Z',' ')}, /* Imbabura Highland Quichua -> Quechua */
- {"qvj", HB_TAG('Q','V','I',' ')}, /* Loja Highland Quichua -> Quechua (Ecuador) */
- {"qvj", HB_TAG('Q','U','Z',' ')}, /* Loja Highland Quichua -> Quechua */
- {"qvl", HB_TAG('Q','W','H',' ')}, /* Cajatambo North Lima Quechua -> Quechua (Peru) */
- {"qvl", HB_TAG('Q','U','Z',' ')}, /* Cajatambo North Lima Quechua -> Quechua */
- {"qvm", HB_TAG('Q','W','H',' ')}, /* Margos-Yarowilca-Lauricocha Quechua -> Quechua (Peru) */
- {"qvm", HB_TAG('Q','U','Z',' ')}, /* Margos-Yarowilca-Lauricocha Quechua -> Quechua */
- {"qvn", HB_TAG('Q','W','H',' ')}, /* North Junín Quechua -> Quechua (Peru) */
- {"qvn", HB_TAG('Q','U','Z',' ')}, /* North Junín Quechua -> Quechua */
- {"qvo", HB_TAG('Q','V','I',' ')}, /* Napo Lowland Quechua -> Quechua (Ecuador) */
- {"qvo", HB_TAG('Q','U','Z',' ')}, /* Napo Lowland Quechua -> Quechua */
- {"qvp", HB_TAG('Q','W','H',' ')}, /* Pacaraos Quechua -> Quechua (Peru) */
- {"qvp", HB_TAG('Q','U','Z',' ')}, /* Pacaraos Quechua -> Quechua */
- {"qvs", HB_TAG('Q','U','Z',' ')}, /* San Martín Quechua -> Quechua */
- {"qvw", HB_TAG('Q','W','H',' ')}, /* Huaylla Wanca Quechua -> Quechua (Peru) */
- {"qvw", HB_TAG('Q','U','Z',' ')}, /* Huaylla Wanca Quechua -> Quechua */
- {"qvz", HB_TAG('Q','V','I',' ')}, /* Northern Pastaza Quichua -> Quechua (Ecuador) */
- {"qvz", HB_TAG('Q','U','Z',' ')}, /* Northern Pastaza Quichua -> Quechua */
- {"qwa", HB_TAG('Q','W','H',' ')}, /* Corongo Ancash Quechua -> Quechua (Peru) */
- {"qwa", HB_TAG('Q','U','Z',' ')}, /* Corongo Ancash Quechua -> Quechua */
- {"qwc", HB_TAG('Q','U','Z',' ')}, /* Classical Quechua -> Quechua */
- {"qwh", HB_TAG('Q','W','H',' ')}, /* Huaylas Ancash Quechua -> Quechua (Peru) */
- {"qwh", HB_TAG('Q','U','Z',' ')}, /* Huaylas Ancash Quechua -> Quechua */
- {"qws", HB_TAG('Q','W','H',' ')}, /* Sihuas Ancash Quechua -> Quechua (Peru) */
- {"qws", HB_TAG('Q','U','Z',' ')}, /* Sihuas Ancash Quechua -> Quechua */
- {"qwt", HB_TAG('A','T','H',' ')}, /* Kwalhioqua-Tlatskanai -> Athapaskan */
- {"qxa", HB_TAG('Q','W','H',' ')}, /* Chiquián Ancash Quechua -> Quechua (Peru) */
- {"qxa", HB_TAG('Q','U','Z',' ')}, /* Chiquián Ancash Quechua -> Quechua */
- {"qxc", HB_TAG('Q','W','H',' ')}, /* Chincha Quechua -> Quechua (Peru) */
- {"qxc", HB_TAG('Q','U','Z',' ')}, /* Chincha Quechua -> Quechua */
- {"qxh", HB_TAG('Q','W','H',' ')}, /* Panao Huánuco Quechua -> Quechua (Peru) */
- {"qxh", HB_TAG('Q','U','Z',' ')}, /* Panao Huánuco Quechua -> Quechua */
- {"qxl", HB_TAG('Q','V','I',' ')}, /* Salasaca Highland Quichua -> Quechua (Ecuador) */
- {"qxl", HB_TAG('Q','U','Z',' ')}, /* Salasaca Highland Quichua -> Quechua */
- {"qxn", HB_TAG('Q','W','H',' ')}, /* Northern Conchucos Ancash Quechua -> Quechua (Peru) */
- {"qxn", HB_TAG('Q','U','Z',' ')}, /* Northern Conchucos Ancash Quechua -> Quechua */
- {"qxo", HB_TAG('Q','W','H',' ')}, /* Southern Conchucos Ancash Quechua -> Quechua (Peru) */
- {"qxo", HB_TAG('Q','U','Z',' ')}, /* Southern Conchucos Ancash Quechua -> Quechua */
- {"qxp", HB_TAG('Q','U','Z',' ')}, /* Puno Quechua -> Quechua */
- {"qxr", HB_TAG('Q','V','I',' ')}, /* Cañar Highland Quichua -> Quechua (Ecuador) */
- {"qxr", HB_TAG('Q','U','Z',' ')}, /* Cañar Highland Quichua -> Quechua */
- {"qxt", HB_TAG('Q','W','H',' ')}, /* Santa Ana de Tusi Pasco Quechua -> Quechua (Peru) */
- {"qxt", HB_TAG('Q','U','Z',' ')}, /* Santa Ana de Tusi Pasco Quechua -> Quechua */
- {"qxu", HB_TAG('Q','U','Z',' ')}, /* Arequipa-La Unión Quechua -> Quechua */
- {"qxw", HB_TAG('Q','W','H',' ')}, /* Jauja Wanca Quechua -> Quechua (Peru) */
- {"qxw", HB_TAG('Q','U','Z',' ')}, /* Jauja Wanca Quechua -> Quechua */
- {"rag", HB_TAG('L','U','H',' ')}, /* Logooli -> Luyia */
-/*{"raj", HB_TAG('R','A','J',' ')},*/ /* Rajasthani [macrolanguage] */
- {"ral", HB_TAG('Q','I','N',' ')}, /* Ralte -> Chin */
-/*{"rar", HB_TAG('R','A','R',' ')},*/ /* Rarotongan */
- {"rbb", HB_TAG('P','L','G',' ')}, /* Rumai Palaung -> Palaung */
- {"rbl", HB_TAG('B','I','K',' ')}, /* Miraya Bikol -> Bikol */
- {"rcf", HB_TAG('C','P','P',' ')}, /* Réunion Creole French -> Creoles */
-/*{"rej", HB_TAG('R','E','J',' ')},*/ /* Rejang */
-/*{"rhg", HB_TAG('R','H','G',' ')},*/ /* Rohingya */
-/*{"ria", HB_TAG('R','I','A',' ')},*/ /* Riang (India) */
- {"rif", HB_TAG('R','I','F',' ')}, /* Tarifit */
- {"rif", HB_TAG('B','B','R',' ')}, /* Tarifit -> Berber */
-/*{"rit", HB_TAG('R','I','T',' ')},*/ /* Ritharrngu -> Ritarungo */
- {"rki", HB_TAG('A','R','K',' ')}, /* Rakhine */
-/*{"rkw", HB_TAG('R','K','W',' ')},*/ /* Arakwal */
- {"rm", HB_TAG('R','M','S',' ')}, /* Romansh */
- {"rmc", HB_TAG('R','O','Y',' ')}, /* Carpathian Romani -> Romany */
- {"rmf", HB_TAG('R','O','Y',' ')}, /* Kalo Finnish Romani -> Romany */
- {"rml", HB_TAG('R','O','Y',' ')}, /* Baltic Romani -> Romany */
- {"rmn", HB_TAG('R','O','Y',' ')}, /* Balkan Romani -> Romany */
- {"rmo", HB_TAG('R','O','Y',' ')}, /* Sinte Romani -> Romany */
- {"rms", HB_TAG_NONE }, /* Romanian Sign Language != Romansh */
- {"rmw", HB_TAG('R','O','Y',' ')}, /* Welsh Romani -> Romany */
- {"rmy", HB_TAG('R','M','Y',' ')}, /* Vlax Romani */
- {"rmy", HB_TAG('R','O','Y',' ')}, /* Vlax Romani -> Romany */
- {"rmz", HB_TAG('A','R','K',' ')}, /* Marma -> Rakhine */
- {"rn", HB_TAG('R','U','N',' ')}, /* Rundi */
- {"ro", HB_TAG('R','O','M',' ')}, /* Romanian */
- {"rom", HB_TAG('R','O','Y',' ')}, /* Romany [macrolanguage] */
- {"rop", HB_TAG('C','P','P',' ')}, /* Kriol -> Creoles */
- {"rtc", HB_TAG('Q','I','N',' ')}, /* Rungtu Chin -> Chin */
-/*{"rtm", HB_TAG('R','T','M',' ')},*/ /* Rotuman */
- {"ru", HB_TAG('R','U','S',' ')}, /* Russian */
- {"rue", HB_TAG('R','S','Y',' ')}, /* Rusyn */
-/*{"rup", HB_TAG('R','U','P',' ')},*/ /* Aromanian */
- {"rw", HB_TAG('R','U','A',' ')}, /* Kinyarwanda */
- {"rwr", HB_TAG('M','A','W',' ')}, /* Marwari (India) */
- {"sa", HB_TAG('S','A','N',' ')}, /* Sanskrit */
- {"sad", HB_TAG_NONE }, /* Sandawe != Sadri */
- {"sah", HB_TAG('Y','A','K',' ')}, /* Yakut -> Sakha */
- {"sam", HB_TAG('P','A','A',' ')}, /* Samaritan Aramaic -> Palestinian Aramaic */
-/*{"sas", HB_TAG('S','A','S',' ')},*/ /* Sasak */
-/*{"sat", HB_TAG('S','A','T',' ')},*/ /* Santali */
- {"say", HB_TAG_NONE }, /* Saya != Sayisi */
- {"sc", HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */
- {"scf", HB_TAG('C','P','P',' ')}, /* San Miguel Creole French -> Creoles */
- {"sch", HB_TAG('Q','I','N',' ')}, /* Sakachep -> Chin */
- {"sci", HB_TAG('C','P','P',' ')}, /* Sri Lankan Creole Malay -> Creoles */
- {"sck", HB_TAG('S','A','D',' ')}, /* Sadri */
-/*{"scn", HB_TAG('S','C','N',' ')},*/ /* Sicilian */
-/*{"sco", HB_TAG('S','C','O',' ')},*/ /* Scots */
- {"scs", HB_TAG('S','C','S',' ')}, /* North Slavey */
- {"scs", HB_TAG('S','L','A',' ')}, /* North Slavey -> Slavey */
- {"scs", HB_TAG('A','T','H',' ')}, /* North Slavey -> Athapaskan */
- {"sd", HB_TAG('S','N','D',' ')}, /* Sindhi */
- {"sdc", HB_TAG('S','R','D',' ')}, /* Sassarese Sardinian -> Sardinian */
- {"sdh", HB_TAG('K','U','R',' ')}, /* Southern Kurdish -> Kurdish */
- {"sdn", HB_TAG('S','R','D',' ')}, /* Gallurese Sardinian -> Sardinian */
- {"sds", HB_TAG('B','B','R',' ')}, /* Sened -> Berber */
- {"se", HB_TAG('N','S','M',' ')}, /* Northern Sami */
- {"seh", HB_TAG('S','N','A',' ')}, /* Sena */
- {"sek", HB_TAG('A','T','H',' ')}, /* Sekani -> Athapaskan */
-/*{"sel", HB_TAG('S','E','L',' ')},*/ /* Selkup */
- {"sez", HB_TAG('Q','I','N',' ')}, /* Senthang Chin -> Chin */
- {"sfm", HB_TAG('S','F','M',' ')}, /* Small Flowery Miao */
- {"sfm", HB_TAG('H','M','N',' ')}, /* Small Flowery Miao -> Hmong */
- {"sg", HB_TAG('S','G','O',' ')}, /* Sango */
-/*{"sga", HB_TAG('S','G','A',' ')},*/ /* Old Irish (to 900) */
- {"sgc", HB_TAG('K','A','L',' ')}, /* Kipsigis -> Kalenjin */
- {"sgo", HB_TAG_NONE }, /* Songa (retired code) != Sango */
-/*{"sgs", HB_TAG('S','G','S',' ')},*/ /* Samogitian */
- {"sgw", HB_TAG('C','H','G',' ')}, /* Sebat Bet Gurage -> Chaha Gurage */
- {"sh", HB_TAG('B','O','S',' ')}, /* Serbo-Croatian [macrolanguage] -> Bosnian */
- {"sh", HB_TAG('H','R','V',' ')}, /* Serbo-Croatian [macrolanguage] -> Croatian */
- {"sh", HB_TAG('S','R','B',' ')}, /* Serbo-Croatian [macrolanguage] -> Serbian */
- {"shi", HB_TAG('S','H','I',' ')}, /* Tachelhit */
- {"shi", HB_TAG('B','B','R',' ')}, /* Tachelhit -> Berber */
- {"shl", HB_TAG('Q','I','N',' ')}, /* Shendu -> Chin */
-/*{"shn", HB_TAG('S','H','N',' ')},*/ /* Shan */
- {"shu", HB_TAG('A','R','A',' ')}, /* Chadian Arabic -> Arabic */
- {"shy", HB_TAG('B','B','R',' ')}, /* Tachawit -> Berber */
- {"si", HB_TAG('S','N','H',' ')}, /* Sinhala (Sinhalese) */
- {"sib", HB_TAG_NONE }, /* Sebop != Sibe */
-/*{"sid", HB_TAG('S','I','D',' ')},*/ /* Sidamo */
- {"sig", HB_TAG_NONE }, /* Paasaal != Silte Gurage */
- {"siz", HB_TAG('B','B','R',' ')}, /* Siwi -> Berber */
- {"sjd", HB_TAG('K','S','M',' ')}, /* Kildin Sami */
- {"sjo", HB_TAG('S','I','B',' ')}, /* Xibe -> Sibe */
- {"sjs", HB_TAG('B','B','R',' ')}, /* Senhaja De Srair -> Berber */
- {"sk", HB_TAG('S','K','Y',' ')}, /* Slovak */
- {"skg", HB_TAG('M','L','G',' ')}, /* Sakalava Malagasy -> Malagasy */
- {"skr", HB_TAG('S','R','K',' ')}, /* Saraiki */
- {"sks", HB_TAG_NONE }, /* Maia != Skolt Sami */
- {"skw", HB_TAG('C','P','P',' ')}, /* Skepi Creole Dutch -> Creoles */
- {"sky", HB_TAG_NONE }, /* Sikaiana != Slovak */
- {"sl", HB_TAG('S','L','V',' ')}, /* Slovenian */
- {"sla", HB_TAG_NONE }, /* Slavic [collection] != Slavey */
- {"sm", HB_TAG('S','M','O',' ')}, /* Samoan */
- {"sma", HB_TAG('S','S','M',' ')}, /* Southern Sami */
- {"smd", HB_TAG('M','B','N',' ')}, /* Sama (retired code) -> Mbundu */
- {"smj", HB_TAG('L','S','M',' ')}, /* Lule Sami */
- {"sml", HB_TAG_NONE }, /* Central Sama != Somali */
- {"smn", HB_TAG('I','S','M',' ')}, /* Inari Sami */
- {"sms", HB_TAG('S','K','S',' ')}, /* Skolt Sami */
- {"smt", HB_TAG('Q','I','N',' ')}, /* Simte -> Chin */
- {"sn", HB_TAG('S','N','A','0')}, /* Shona */
- {"snb", HB_TAG('I','B','A',' ')}, /* Sebuyau (retired code) -> Iban */
- {"snh", HB_TAG_NONE }, /* Shinabo (retired code) != Sinhala (Sinhalese) */
-/*{"snk", HB_TAG('S','N','K',' ')},*/ /* Soninke */
- {"so", HB_TAG('S','M','L',' ')}, /* Somali */
- {"sog", HB_TAG_NONE }, /* Sogdian != Sodo Gurage */
-/*{"sop", HB_TAG('S','O','P',' ')},*/ /* Songe */
- {"spv", HB_TAG('O','R','I',' ')}, /* Sambalpuri -> Odia (formerly Oriya) */
- {"spy", HB_TAG('K','A','L',' ')}, /* Sabaot -> Kalenjin */
- {"sq", HB_TAG('S','Q','I',' ')}, /* Albanian [macrolanguage] */
- {"sr", HB_TAG('S','R','B',' ')}, /* Serbian */
- {"srb", HB_TAG_NONE }, /* Sora != Serbian */
- {"src", HB_TAG('S','R','D',' ')}, /* Logudorese Sardinian -> Sardinian */
- {"srk", HB_TAG_NONE }, /* Serudung Murut != Saraiki */
- {"srm", HB_TAG('C','P','P',' ')}, /* Saramaccan -> Creoles */
- {"srn", HB_TAG('C','P','P',' ')}, /* Sranan Tongo -> Creoles */
- {"sro", HB_TAG('S','R','D',' ')}, /* Campidanese Sardinian -> Sardinian */
-/*{"srr", HB_TAG('S','R','R',' ')},*/ /* Serer */
- {"srs", HB_TAG('A','T','H',' ')}, /* Sarsi -> Athapaskan */
- {"ss", HB_TAG('S','W','Z',' ')}, /* Swati */
- {"ssh", HB_TAG('A','R','A',' ')}, /* Shihhi Arabic -> Arabic */
- {"ssl", HB_TAG_NONE }, /* Western Sisaala != South Slavey */
- {"ssm", HB_TAG_NONE }, /* Semnam != Southern Sami */
- {"st", HB_TAG('S','O','T',' ')}, /* Southern Sotho */
- {"sta", HB_TAG('C','P','P',' ')}, /* Settla -> Creoles */
-/*{"stq", HB_TAG('S','T','Q',' ')},*/ /* Saterfriesisch -> Saterland Frisian */
- {"stv", HB_TAG('S','I','G',' ')}, /* Silt'e -> Silte Gurage */
- {"su", HB_TAG('S','U','N',' ')}, /* Sundanese */
-/*{"suk", HB_TAG('S','U','K',' ')},*/ /* Sukuma */
- {"suq", HB_TAG('S','U','R',' ')}, /* Suri */
- {"sur", HB_TAG_NONE }, /* Mwaghavul != Suri */
- {"sv", HB_TAG('S','V','E',' ')}, /* Swedish */
-/*{"sva", HB_TAG('S','V','A',' ')},*/ /* Svan */
- {"svc", HB_TAG('C','P','P',' ')}, /* Vincentian Creole English -> Creoles */
- {"sve", HB_TAG_NONE }, /* Serili != Swedish */
- {"sw", HB_TAG('S','W','K',' ')}, /* Swahili [macrolanguage] */
- {"swb", HB_TAG('C','M','R',' ')}, /* Maore Comorian -> Comorian */
- {"swc", HB_TAG('S','W','K',' ')}, /* Congo Swahili -> Swahili */
- {"swh", HB_TAG('S','W','K',' ')}, /* Swahili */
- {"swk", HB_TAG_NONE }, /* Malawi Sena != Swahili */
- {"swn", HB_TAG('B','B','R',' ')}, /* Sawknah -> Berber */
- {"swv", HB_TAG('M','A','W',' ')}, /* Shekhawati -> Marwari */
-/*{"sxu", HB_TAG('S','X','U',' ')},*/ /* Upper Saxon */
- {"syc", HB_TAG('S','Y','R',' ')}, /* Classical Syriac -> Syriac */
-/*{"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 */
- {"taa", HB_TAG('A','T','H',' ')}, /* Lower Tanana -> Athapaskan */
-/*{"tab", HB_TAG('T','A','B',' ')},*/ /* Tabassaran -> Tabasaran */
- {"taj", HB_TAG_NONE }, /* Eastern Tamang != Tajiki */
- {"taq", HB_TAG('T','M','H',' ')}, /* Tamasheq -> Tamashek */
- {"taq", HB_TAG('B','B','R',' ')}, /* Tamasheq -> Berber */
- {"tas", HB_TAG('C','P','P',' ')}, /* Tay Boi -> Creoles */
- {"tau", HB_TAG('A','T','H',' ')}, /* Upper Tanana -> Athapaskan */
- {"tcb", HB_TAG('A','T','H',' ')}, /* Tanacross -> Athapaskan */
- {"tce", HB_TAG('A','T','H',' ')}, /* Southern Tutchone -> Athapaskan */
- {"tch", HB_TAG('C','P','P',' ')}, /* Turks And Caicos Creole English -> Creoles */
- {"tcp", HB_TAG('Q','I','N',' ')}, /* Tawr Chin -> Chin */
- {"tcs", HB_TAG('C','P','P',' ')}, /* Torres Strait Creole -> Creoles */
- {"tcy", HB_TAG('T','U','L',' ')}, /* Tulu -> Tumbuka */
- {"tcz", HB_TAG('Q','I','N',' ')}, /* Thado Chin -> Chin */
-/*{"tdd", HB_TAG('T','D','D',' ')},*/ /* Tai Nüa -> Dehong Dai */
- {"tdx", HB_TAG('M','L','G',' ')}, /* Tandroy-Mahafaly Malagasy -> Malagasy */
- {"te", HB_TAG('T','E','L',' ')}, /* Telugu */
- {"tec", HB_TAG('K','A','L',' ')}, /* Terik -> Kalenjin */
- {"tem", HB_TAG('T','M','N',' ')}, /* Timne -> Temne */
-/*{"tet", HB_TAG('T','E','T',' ')},*/ /* Tetum */
- {"tez", HB_TAG('B','B','R',' ')}, /* Tetserret -> Berber */
- {"tfn", HB_TAG('A','T','H',' ')}, /* Tanaina -> Athapaskan */
- {"tg", HB_TAG('T','A','J',' ')}, /* Tajik -> Tajiki */
- {"tgh", HB_TAG('C','P','P',' ')}, /* Tobagonian Creole English -> Creoles */
- {"tgj", HB_TAG('N','I','S',' ')}, /* Tagin -> Nisi */
- {"tgn", HB_TAG_NONE }, /* Tandaganon != Tongan */
- {"tgr", HB_TAG_NONE }, /* Tareng != Tigre */
- {"tgx", HB_TAG('A','T','H',' ')}, /* Tagish -> Athapaskan */
- {"tgy", HB_TAG_NONE }, /* Togoyo != Tigrinya */
- {"th", HB_TAG('T','H','A',' ')}, /* Thai */
- {"tht", HB_TAG('A','T','H',' ')}, /* Tahltan -> Athapaskan */
- {"thv", HB_TAG('T','M','H',' ')}, /* Tahaggart Tamahaq -> Tamashek */
- {"thv", HB_TAG('B','B','R',' ')}, /* Tahaggart Tamahaq -> Berber */
- {"thz", HB_TAG('T','M','H',' ')}, /* Tayart Tamajeq -> Tamashek */
- {"thz", HB_TAG('B','B','R',' ')}, /* Tayart Tamajeq -> Berber */
- {"ti", HB_TAG('T','G','Y',' ')}, /* Tigrinya */
- {"tia", HB_TAG('B','B','R',' ')}, /* Tidikelt Tamazight -> Berber */
- {"tig", HB_TAG('T','G','R',' ')}, /* Tigre */
-/*{"tiv", HB_TAG('T','I','V',' ')},*/ /* Tiv */
-/*{"tjl", HB_TAG('T','J','L',' ')},*/ /* Tai Laing */
- {"tjo", HB_TAG('B','B','R',' ')}, /* Temacine Tamazight -> Berber */
- {"tk", HB_TAG('T','K','M',' ')}, /* Turkmen */
- {"tkg", HB_TAG('M','L','G',' ')}, /* Tesaka Malagasy -> Malagasy */
- {"tkm", HB_TAG_NONE }, /* Takelma != Turkmen */
- {"tl", HB_TAG('T','G','L',' ')}, /* Tagalog */
-/*{"tli", HB_TAG('T','L','I',' ')},*/ /* Tlingit */
- {"tmg", HB_TAG('C','P','P',' ')}, /* Ternateño -> Creoles */
- {"tmh", HB_TAG('T','M','H',' ')}, /* Tamashek [macrolanguage] */
- {"tmh", HB_TAG('B','B','R',' ')}, /* Tamashek [macrolanguage] -> Berber */
- {"tmn", HB_TAG_NONE }, /* Taman (Indonesia) != Temne */
- {"tmw", HB_TAG('M','L','Y',' ')}, /* Temuan -> Malay */
- {"tn", HB_TAG('T','N','A',' ')}, /* Tswana */
- {"tna", HB_TAG_NONE }, /* Tacana != Tswana */
- {"tne", HB_TAG_NONE }, /* Tinoc Kallahan (retired code) != Tundra Enets */
- {"tnf", HB_TAG('D','R','I',' ')}, /* Tangshewi (retired code) -> Dari */
- {"tnf", HB_TAG('F','A','R',' ')}, /* Tangshewi (retired code) -> Persian */
- {"tng", HB_TAG_NONE }, /* Tobanga != Tonga */
- {"to", HB_TAG('T','G','N',' ')}, /* Tonga (Tonga Islands) -> Tongan */
- {"tod", HB_TAG('T','O','D','0')}, /* Toma */
- {"toi", HB_TAG('T','N','G',' ')}, /* Tonga (Zambia) */
- {"toj", HB_TAG('M','Y','N',' ')}, /* Tojolabal -> Mayan */
- {"tol", HB_TAG('A','T','H',' ')}, /* Tolowa -> Athapaskan */
- {"tor", HB_TAG('B','A','D','0')}, /* Togbo-Vara Banda -> Banda */
- {"tpi", HB_TAG('T','P','I',' ')}, /* Tok Pisin */
- {"tpi", HB_TAG('C','P','P',' ')}, /* Tok Pisin -> Creoles */
- {"tr", HB_TAG('T','R','K',' ')}, /* Turkish */
- {"trf", HB_TAG('C','P','P',' ')}, /* Trinidadian Creole English -> Creoles */
- {"trk", HB_TAG_NONE }, /* Turkic [collection] != Turkish */
- {"tru", HB_TAG('T','U','A',' ')}, /* Turoyo -> Turoyo Aramaic */
- {"tru", HB_TAG('S','Y','R',' ')}, /* Turoyo -> Syriac */
- {"ts", HB_TAG('T','S','G',' ')}, /* Tsonga */
- {"tsg", HB_TAG_NONE }, /* Tausug != Tsonga */
-/*{"tsj", HB_TAG('T','S','J',' ')},*/ /* Tshangla */
- {"tt", HB_TAG('T','A','T',' ')}, /* Tatar */
- {"ttc", HB_TAG('M','Y','N',' ')}, /* Tektiteko -> Mayan */
- {"ttm", HB_TAG('A','T','H',' ')}, /* Northern Tutchone -> Athapaskan */
- {"ttq", HB_TAG('T','M','H',' ')}, /* Tawallammat Tamajaq -> Tamashek */
- {"ttq", HB_TAG('B','B','R',' ')}, /* Tawallammat Tamajaq -> Berber */
- {"tua", HB_TAG_NONE }, /* Wiarumus != Turoyo Aramaic */
- {"tul", HB_TAG_NONE }, /* Tula != Tumbuka */
-/*{"tum", HB_TAG('T','U','M',' ')},*/ /* Tumbuka -> Tulu */
- {"tuu", HB_TAG('A','T','H',' ')}, /* Tututni -> Athapaskan */
- {"tuv", HB_TAG_NONE }, /* Turkana != Tuvin */
- {"tuy", HB_TAG('K','A','L',' ')}, /* Tugen -> Kalenjin */
-/*{"tvl", HB_TAG('T','V','L',' ')},*/ /* Tuvalu */
- {"tvy", HB_TAG('C','P','P',' ')}, /* Timor Pidgin -> Creoles */
- {"tw", HB_TAG('T','W','I',' ')}, /* Twi */
- {"tw", HB_TAG('A','K','A',' ')}, /* Twi -> Akan */
- {"txc", HB_TAG('A','T','H',' ')}, /* Tsetsaut -> Athapaskan */
- {"txy", HB_TAG('M','L','G',' ')}, /* Tanosy Malagasy -> Malagasy */
- {"ty", HB_TAG('T','H','T',' ')}, /* Tahitian */
- {"tyv", HB_TAG('T','U','V',' ')}, /* Tuvinian -> Tuvin */
-/*{"tyz", HB_TAG('T','Y','Z',' ')},*/ /* Tày */
- {"tzh", HB_TAG('M','Y','N',' ')}, /* Tzeltal -> Mayan */
- {"tzj", HB_TAG('M','Y','N',' ')}, /* Tz'utujil -> Mayan */
- {"tzm", HB_TAG('T','Z','M',' ')}, /* Central Atlas Tamazight -> Tamazight */
- {"tzm", HB_TAG('B','B','R',' ')}, /* Central Atlas Tamazight -> Berber */
- {"tzo", HB_TAG('T','Z','O',' ')}, /* Tzotzil */
- {"tzo", HB_TAG('M','Y','N',' ')}, /* Tzotzil -> Mayan */
- {"ubl", HB_TAG('B','I','K',' ')}, /* Buhi'non Bikol -> Bikol */
-/*{"udm", HB_TAG('U','D','M',' ')},*/ /* Udmurt */
- {"ug", HB_TAG('U','Y','G',' ')}, /* Uyghur */
- {"uk", HB_TAG('U','K','R',' ')}, /* Ukrainian */
- {"uki", HB_TAG('K','U','I',' ')}, /* Kui (India) */
- {"uln", HB_TAG('C','P','P',' ')}, /* Unserdeutsch -> Creoles */
-/*{"umb", HB_TAG('U','M','B',' ')},*/ /* Umbundu */
- {"unr", HB_TAG('M','U','N',' ')}, /* Mundari */
- {"ur", HB_TAG('U','R','D',' ')}, /* Urdu */
- {"urk", HB_TAG('M','L','Y',' ')}, /* Urak Lawoi' -> Malay */
- {"usp", HB_TAG('M','Y','N',' ')}, /* Uspanteco -> Mayan */
- {"uz", HB_TAG('U','Z','B',' ')}, /* Uzbek [macrolanguage] */
- {"uzn", HB_TAG('U','Z','B',' ')}, /* Northern Uzbek -> Uzbek */
- {"uzs", HB_TAG('U','Z','B',' ')}, /* Southern Uzbek -> Uzbek */
- {"vap", HB_TAG('Q','I','N',' ')}, /* Vaiphei -> Chin */
- {"ve", HB_TAG('V','E','N',' ')}, /* Venda */
-/*{"vec", HB_TAG('V','E','C',' ')},*/ /* Venetian */
- {"vi", HB_TAG('V','I','T',' ')}, /* Vietnamese */
- {"vic", HB_TAG('C','P','P',' ')}, /* Virgin Islands Creole English -> Creoles */
- {"vit", HB_TAG_NONE }, /* Viti != Vietnamese */
- {"vkk", HB_TAG('M','L','Y',' ')}, /* Kaur -> Malay */
- {"vkp", HB_TAG('C','P','P',' ')}, /* Korlai Creole Portuguese -> Creoles */
- {"vkt", HB_TAG('M','L','Y',' ')}, /* Tenggarong Kutai Malay -> Malay */
- {"vls", HB_TAG('F','L','E',' ')}, /* Vlaams -> Dutch (Flemish) */
- {"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 */
- {"wag", HB_TAG_NONE }, /* Wa'ema != Wagdi */
-/*{"war", HB_TAG('W','A','R',' ')},*/ /* Waray (Philippines) -> Waray-Waray */
- {"wbm", HB_TAG('W','A',' ',' ')}, /* Wa */
- {"wbr", HB_TAG('W','A','G',' ')}, /* Wagdi */
- {"wbr", HB_TAG('R','A','J',' ')}, /* Wagdi -> Rajasthani */
-/*{"wci", HB_TAG('W','C','I',' ')},*/ /* Waci Gbe */
- {"wea", HB_TAG('K','R','N',' ')}, /* Wewaw -> Karen */
- {"wes", HB_TAG('C','P','P',' ')}, /* Cameroon Pidgin -> Creoles */
- {"weu", HB_TAG('Q','I','N',' ')}, /* Rawngtu Chin -> Chin */
- {"wlc", HB_TAG('C','M','R',' ')}, /* Mwali Comorian -> Comorian */
- {"wle", HB_TAG('S','I','G',' ')}, /* Wolane -> Silte Gurage */
- {"wlk", HB_TAG('A','T','H',' ')}, /* Wailaki -> Athapaskan */
- {"wni", HB_TAG('C','M','R',' ')}, /* Ndzwani Comorian -> Comorian */
- {"wo", HB_TAG('W','L','F',' ')}, /* Wolof */
- {"wry", HB_TAG('M','A','W',' ')}, /* Merwari -> Marwari */
- {"wsg", HB_TAG('G','O','N',' ')}, /* Adilabad Gondi -> Gondi */
-/*{"wtm", HB_TAG('W','T','M',' ')},*/ /* Mewati */
- {"wuu", HB_TAG('Z','H','S',' ')}, /* Wu Chinese -> Chinese, Simplified */
- {"xal", HB_TAG('K','L','M',' ')}, /* Kalmyk */
- {"xal", HB_TAG('T','O','D',' ')}, /* Kalmyk -> Todo */
- {"xan", HB_TAG('S','E','K',' ')}, /* Xamtanga -> Sekota */
- {"xbd", HB_TAG_NONE }, /* Bindal != Lü */
- {"xh", HB_TAG('X','H','S',' ')}, /* Xhosa */
-/*{"xjb", HB_TAG('X','J','B',' ')},*/ /* Minjungbal -> Minjangbal */
-/*{"xkf", HB_TAG('X','K','F',' ')},*/ /* Khengkha */
- {"xmg", HB_TAG('B','M','L',' ')}, /* Mengaka -> Bamileke */
- {"xmm", HB_TAG('M','L','Y',' ')}, /* Manado Malay -> Malay */
- {"xmm", HB_TAG('C','P','P',' ')}, /* Manado Malay -> Creoles */
- {"xmv", HB_TAG('M','L','G',' ')}, /* Antankarana Malagasy -> Malagasy */
- {"xmw", HB_TAG('M','L','G',' ')}, /* Tsimihety Malagasy -> Malagasy */
- {"xnj", HB_TAG('S','X','T',' ')}, /* Ngoni (Tanzania) -> Sutu */
- {"xnq", HB_TAG('S','X','T',' ')}, /* Ngoni (Mozambique) -> Sutu */
- {"xnr", HB_TAG('D','G','R',' ')}, /* Kangri -> Dogri (macrolanguage) */
-/*{"xog", HB_TAG('X','O','G',' ')},*/ /* Soga */
- {"xpe", HB_TAG('X','P','E',' ')}, /* Liberia Kpelle -> Kpelle (Liberia) */
- {"xpe", HB_TAG('K','P','L',' ')}, /* Liberia Kpelle -> Kpelle */
- {"xsl", HB_TAG('S','S','L',' ')}, /* South Slavey */
- {"xsl", HB_TAG('S','L','A',' ')}, /* South Slavey -> Slavey */
- {"xsl", HB_TAG('A','T','H',' ')}, /* South Slavey -> Athapaskan */
- {"xst", HB_TAG('S','I','G',' ')}, /* Silt'e (retired code) -> Silte Gurage */
-/*{"xub", HB_TAG('X','U','B',' ')},*/ /* Betta Kurumba -> Bette Kuruma */
-/*{"xuj", HB_TAG('X','U','J',' ')},*/ /* Jennu Kurumba -> Jennu Kuruma */
- {"xup", HB_TAG('A','T','H',' ')}, /* Upper Umpqua -> Athapaskan */
- {"xwo", HB_TAG('T','O','D',' ')}, /* Written Oirat -> Todo */
- {"yaj", HB_TAG('B','A','D','0')}, /* Banda-Yangere -> Banda */
- {"yak", HB_TAG_NONE }, /* Yakama != Sakha */
-/*{"yao", HB_TAG('Y','A','O',' ')},*/ /* Yao */
-/*{"yap", HB_TAG('Y','A','P',' ')},*/ /* Yapese */
- {"yba", HB_TAG_NONE }, /* Yala != Yoruba */
- {"ybb", HB_TAG('B','M','L',' ')}, /* Yemba -> Bamileke */
- {"ybd", HB_TAG('A','R','K',' ')}, /* Yangbye (retired code) -> Rakhine */
- {"ydd", HB_TAG('J','I','I',' ')}, /* Eastern Yiddish -> Yiddish */
-/*{"ygp", HB_TAG('Y','G','P',' ')},*/ /* Gepo */
- {"yi", HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */
- {"yih", HB_TAG('J','I','I',' ')}, /* Western Yiddish -> Yiddish */
- {"yim", HB_TAG_NONE }, /* Yimchungru Naga != Yi Modern */
-/*{"yna", HB_TAG('Y','N','A',' ')},*/ /* Aluo */
- {"yo", HB_TAG('Y','B','A',' ')}, /* Yoruba */
- {"yos", HB_TAG('Q','I','N',' ')}, /* Yos (retired code) -> Chin */
- {"yua", HB_TAG('M','Y','N',' ')}, /* Yucateco -> Mayan */
- {"yue", HB_TAG('Z','H','H',' ')}, /* Yue Chinese -> Chinese, Traditional, Hong Kong SAR */
-/*{"ywq", HB_TAG('Y','W','Q',' ')},*/ /* Wuding-Luquan Yi */
- {"za", HB_TAG('Z','H','A',' ')}, /* Zhuang [macrolanguage] */
- {"zch", HB_TAG('Z','H','A',' ')}, /* Central Hongshuihe Zhuang -> Zhuang */
- {"zdj", HB_TAG('C','M','R',' ')}, /* Ngazidja Comorian -> Comorian */
-/*{"zea", HB_TAG('Z','E','A',' ')},*/ /* Zeeuws -> Zealandic */
- {"zeh", HB_TAG('Z','H','A',' ')}, /* Eastern Hongshuihe Zhuang -> Zhuang */
- {"zen", HB_TAG('B','B','R',' ')}, /* Zenaga -> Berber */
- {"zgb", HB_TAG('Z','H','A',' ')}, /* Guibei Zhuang -> Zhuang */
- {"zgh", HB_TAG('Z','G','H',' ')}, /* Standard Moroccan Tamazight */
- {"zgh", HB_TAG('B','B','R',' ')}, /* Standard Moroccan Tamazight -> Berber */
- {"zgm", HB_TAG('Z','H','A',' ')}, /* Minz Zhuang -> Zhuang */
- {"zgn", HB_TAG('Z','H','A',' ')}, /* Guibian Zhuang -> Zhuang */
- {"zh", HB_TAG('Z','H','S',' ')}, /* Chinese, Simplified [macrolanguage] */
- {"zhd", HB_TAG('Z','H','A',' ')}, /* Dai Zhuang -> Zhuang */
- {"zhn", HB_TAG('Z','H','A',' ')}, /* Nong Zhuang -> Zhuang */
- {"zlj", HB_TAG('Z','H','A',' ')}, /* Liujiang Zhuang -> Zhuang */
- {"zlm", HB_TAG('M','L','Y',' ')}, /* Malay */
- {"zln", HB_TAG('Z','H','A',' ')}, /* Lianshan Zhuang -> Zhuang */
- {"zlq", HB_TAG('Z','H','A',' ')}, /* Liuqian Zhuang -> Zhuang */
- {"zmi", HB_TAG('M','L','Y',' ')}, /* Negeri Sembilan Malay -> Malay */
- {"zmz", HB_TAG('B','A','D','0')}, /* Mbandja -> Banda */
- {"znd", HB_TAG_NONE }, /* Zande [collection] != Zande */
- {"zne", HB_TAG('Z','N','D',' ')}, /* Zande */
- {"zom", HB_TAG('Q','I','N',' ')}, /* Zou -> Chin */
- {"zqe", HB_TAG('Z','H','A',' ')}, /* Qiubei Zhuang -> Zhuang */
- {"zsm", HB_TAG('M','L','Y',' ')}, /* Standard Malay -> Malay */
- {"zu", HB_TAG('Z','U','L',' ')}, /* Zulu */
- {"zum", HB_TAG('L','R','C',' ')}, /* Kumzari -> Luri */
- {"zyb", HB_TAG('Z','H','A',' ')}, /* Yongbei Zhuang -> Zhuang */
- {"zyg", HB_TAG('Z','H','A',' ')}, /* Yang Zhuang -> Zhuang */
- {"zyj", HB_TAG('Z','H','A',' ')}, /* Youjiang Zhuang -> Zhuang */
- {"zyn", HB_TAG('Z','H','A',' ')}, /* Yongnan Zhuang -> Zhuang */
- {"zyp", HB_TAG('Q','I','N',' ')}, /* Zyphe Chin -> Chin */
-/*{"zza", HB_TAG('Z','Z','A',' ')},*/ /* Zazaki [macrolanguage] */
- {"zzj", HB_TAG('Z','H','A',' ')}, /* Zuojiang Zhuang -> Zhuang */
+static const LangTag ot_languages2[] = {
+ {HB_TAG('a','a',' ',' '), HB_TAG('A','F','R',' ')}, /* Afar */
+ {HB_TAG('a','b',' ',' '), HB_TAG('A','B','K',' ')}, /* Abkhazian */
+ {HB_TAG('a','f',' ',' '), HB_TAG('A','F','K',' ')}, /* Afrikaans */
+ {HB_TAG('a','k',' ',' '), HB_TAG('A','K','A',' ')}, /* Akan [macrolanguage] */
+ {HB_TAG('a','m',' ',' '), HB_TAG('A','M','H',' ')}, /* Amharic */
+ {HB_TAG('a','n',' ',' '), HB_TAG('A','R','G',' ')}, /* Aragonese */
+ {HB_TAG('a','r',' ',' '), HB_TAG('A','R','A',' ')}, /* Arabic [macrolanguage] */
+ {HB_TAG('a','s',' ',' '), HB_TAG('A','S','M',' ')}, /* Assamese */
+ {HB_TAG('a','v',' ',' '), HB_TAG('A','V','R',' ')}, /* Avaric -> Avar */
+ {HB_TAG('a','y',' ',' '), HB_TAG('A','Y','M',' ')}, /* Aymara [macrolanguage] */
+ {HB_TAG('a','z',' ',' '), HB_TAG('A','Z','E',' ')}, /* Azerbaijani [macrolanguage] */
+ {HB_TAG('b','a',' ',' '), HB_TAG('B','S','H',' ')}, /* Bashkir */
+ {HB_TAG('b','e',' ',' '), HB_TAG('B','E','L',' ')}, /* Belarusian -> Belarussian */
+ {HB_TAG('b','g',' ',' '), HB_TAG('B','G','R',' ')}, /* Bulgarian */
+ {HB_TAG('b','i',' ',' '), HB_TAG('B','I','S',' ')}, /* Bislama */
+ {HB_TAG('b','i',' ',' '), HB_TAG('C','P','P',' ')}, /* Bislama -> Creoles */
+ {HB_TAG('b','m',' ',' '), HB_TAG('B','M','B',' ')}, /* Bambara (Bamanankan) */
+ {HB_TAG('b','n',' ',' '), HB_TAG('B','E','N',' ')}, /* Bengali */
+ {HB_TAG('b','o',' ',' '), HB_TAG('T','I','B',' ')}, /* Tibetan */
+ {HB_TAG('b','r',' ',' '), HB_TAG('B','R','E',' ')}, /* Breton */
+ {HB_TAG('b','s',' ',' '), HB_TAG('B','O','S',' ')}, /* Bosnian */
+ {HB_TAG('c','a',' ',' '), HB_TAG('C','A','T',' ')}, /* Catalan */
+ {HB_TAG('c','e',' ',' '), HB_TAG('C','H','E',' ')}, /* Chechen */
+ {HB_TAG('c','h',' ',' '), HB_TAG('C','H','A',' ')}, /* Chamorro */
+ {HB_TAG('c','o',' ',' '), HB_TAG('C','O','S',' ')}, /* Corsican */
+ {HB_TAG('c','r',' ',' '), HB_TAG('C','R','E',' ')}, /* Cree [macrolanguage] */
+ {HB_TAG('c','s',' ',' '), HB_TAG('C','S','Y',' ')}, /* Czech */
+ {HB_TAG('c','u',' ',' '), HB_TAG('C','S','L',' ')}, /* Church Slavonic */
+ {HB_TAG('c','v',' ',' '), HB_TAG('C','H','U',' ')}, /* Chuvash */
+ {HB_TAG('c','y',' ',' '), HB_TAG('W','E','L',' ')}, /* Welsh */
+ {HB_TAG('d','a',' ',' '), HB_TAG('D','A','N',' ')}, /* Danish */
+ {HB_TAG('d','e',' ',' '), HB_TAG('D','E','U',' ')}, /* German */
+ {HB_TAG('d','v',' ',' '), HB_TAG('D','I','V',' ')}, /* Divehi (Dhivehi, Maldivian) */
+ {HB_TAG('d','v',' ',' '), HB_TAG('D','H','V',' ')}, /* Divehi (Dhivehi, Maldivian) (deprecated) */
+ {HB_TAG('d','z',' ',' '), HB_TAG('D','Z','N',' ')}, /* Dzongkha */
+ {HB_TAG('e','e',' ',' '), HB_TAG('E','W','E',' ')}, /* Ewe */
+ {HB_TAG('e','l',' ',' '), HB_TAG('E','L','L',' ')}, /* Modern Greek (1453-) -> Greek */
+ {HB_TAG('e','n',' ',' '), HB_TAG('E','N','G',' ')}, /* English */
+ {HB_TAG('e','o',' ',' '), HB_TAG('N','T','O',' ')}, /* Esperanto */
+ {HB_TAG('e','s',' ',' '), HB_TAG('E','S','P',' ')}, /* Spanish */
+ {HB_TAG('e','t',' ',' '), HB_TAG('E','T','I',' ')}, /* Estonian [macrolanguage] */
+ {HB_TAG('e','u',' ',' '), HB_TAG('E','U','Q',' ')}, /* Basque */
+ {HB_TAG('f','a',' ',' '), HB_TAG('F','A','R',' ')}, /* Persian [macrolanguage] */
+ {HB_TAG('f','f',' ',' '), HB_TAG('F','U','L',' ')}, /* Fulah [macrolanguage] */
+ {HB_TAG('f','i',' ',' '), HB_TAG('F','I','N',' ')}, /* Finnish */
+ {HB_TAG('f','j',' ',' '), HB_TAG('F','J','I',' ')}, /* Fijian */
+ {HB_TAG('f','o',' ',' '), HB_TAG('F','O','S',' ')}, /* Faroese */
+ {HB_TAG('f','r',' ',' '), HB_TAG('F','R','A',' ')}, /* French */
+ {HB_TAG('f','y',' ',' '), HB_TAG('F','R','I',' ')}, /* Western Frisian -> Frisian */
+ {HB_TAG('g','a',' ',' '), HB_TAG('I','R','I',' ')}, /* Irish */
+ {HB_TAG('g','d',' ',' '), HB_TAG('G','A','E',' ')}, /* Scottish Gaelic (Gaelic) */
+ {HB_TAG('g','l',' ',' '), HB_TAG('G','A','L',' ')}, /* Galician */
+ {HB_TAG('g','n',' ',' '), HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */
+ {HB_TAG('g','u',' ',' '), HB_TAG('G','U','J',' ')}, /* Gujarati */
+ {HB_TAG('g','v',' ',' '), HB_TAG('M','N','X',' ')}, /* Manx */
+ {HB_TAG('h','a',' ',' '), HB_TAG('H','A','U',' ')}, /* Hausa */
+ {HB_TAG('h','e',' ',' '), HB_TAG('I','W','R',' ')}, /* Hebrew */
+ {HB_TAG('h','i',' ',' '), HB_TAG('H','I','N',' ')}, /* Hindi */
+ {HB_TAG('h','o',' ',' '), HB_TAG('H','M','O',' ')}, /* Hiri Motu */
+ {HB_TAG('h','o',' ',' '), HB_TAG('C','P','P',' ')}, /* Hiri Motu -> Creoles */
+ {HB_TAG('h','r',' ',' '), HB_TAG('H','R','V',' ')}, /* Croatian */
+ {HB_TAG('h','t',' ',' '), HB_TAG('H','A','I',' ')}, /* Haitian (Haitian Creole) */
+ {HB_TAG('h','t',' ',' '), HB_TAG('C','P','P',' ')}, /* Haitian -> Creoles */
+ {HB_TAG('h','u',' ',' '), HB_TAG('H','U','N',' ')}, /* Hungarian */
+ {HB_TAG('h','y',' ',' '), HB_TAG('H','Y','E','0')}, /* Armenian -> Armenian East */
+ {HB_TAG('h','y',' ',' '), HB_TAG('H','Y','E',' ')}, /* Armenian */
+ {HB_TAG('h','z',' ',' '), HB_TAG('H','E','R',' ')}, /* Herero */
+ {HB_TAG('i','a',' ',' '), HB_TAG('I','N','A',' ')}, /* Interlingua (International Auxiliary Language Association) */
+ {HB_TAG('i','d',' ',' '), HB_TAG('I','N','D',' ')}, /* Indonesian */
+ {HB_TAG('i','d',' ',' '), HB_TAG('M','L','Y',' ')}, /* Indonesian -> Malay */
+ {HB_TAG('i','e',' ',' '), HB_TAG('I','L','E',' ')}, /* Interlingue */
+ {HB_TAG('i','g',' ',' '), HB_TAG('I','B','O',' ')}, /* Igbo */
+ {HB_TAG('i','i',' ',' '), HB_TAG('Y','I','M',' ')}, /* Sichuan Yi -> Yi Modern */
+ {HB_TAG('i','k',' ',' '), HB_TAG('I','P','K',' ')}, /* Inupiaq [macrolanguage] -> Inupiat */
+ {HB_TAG('i','n',' ',' '), HB_TAG('I','N','D',' ')}, /* Indonesian (retired code) */
+ {HB_TAG('i','n',' ',' '), HB_TAG('M','L','Y',' ')}, /* Indonesian (retired code) -> Malay */
+ {HB_TAG('i','o',' ',' '), HB_TAG('I','D','O',' ')}, /* Ido */
+ {HB_TAG('i','s',' ',' '), HB_TAG('I','S','L',' ')}, /* Icelandic */
+ {HB_TAG('i','t',' ',' '), HB_TAG('I','T','A',' ')}, /* Italian */
+ {HB_TAG('i','u',' ',' '), HB_TAG('I','N','U',' ')}, /* Inuktitut [macrolanguage] */
+ {HB_TAG('i','u',' ',' '), HB_TAG('I','N','U','K')}, /* Inuktitut [macrolanguage] -> Nunavik Inuktitut */
+ {HB_TAG('i','w',' ',' '), HB_TAG('I','W','R',' ')}, /* Hebrew (retired code) */
+ {HB_TAG('j','a',' ',' '), HB_TAG('J','A','N',' ')}, /* Japanese */
+ {HB_TAG('j','i',' ',' '), HB_TAG('J','I','I',' ')}, /* Yiddish (retired code) */
+ {HB_TAG('j','v',' ',' '), HB_TAG('J','A','V',' ')}, /* Javanese */
+ {HB_TAG('j','w',' ',' '), HB_TAG('J','A','V',' ')}, /* Javanese (retired code) */
+ {HB_TAG('k','a',' ',' '), HB_TAG('K','A','T',' ')}, /* Georgian */
+ {HB_TAG('k','g',' ',' '), HB_TAG('K','O','N','0')}, /* Kongo [macrolanguage] */
+ {HB_TAG('k','i',' ',' '), HB_TAG('K','I','K',' ')}, /* Kikuyu (Gikuyu) */
+ {HB_TAG('k','j',' ',' '), HB_TAG('K','U','A',' ')}, /* Kuanyama */
+ {HB_TAG('k','k',' ',' '), HB_TAG('K','A','Z',' ')}, /* Kazakh */
+ {HB_TAG('k','l',' ',' '), HB_TAG('G','R','N',' ')}, /* Greenlandic */
+ {HB_TAG('k','m',' ',' '), HB_TAG('K','H','M',' ')}, /* Khmer */
+ {HB_TAG('k','n',' ',' '), HB_TAG('K','A','N',' ')}, /* Kannada */
+ {HB_TAG('k','o',' ',' '), HB_TAG('K','O','R',' ')}, /* Korean */
+ {HB_TAG('k','o',' ',' '), HB_TAG('K','O','H',' ')}, /* Korean -> Korean Old Hangul */
+ {HB_TAG('k','r',' ',' '), HB_TAG('K','N','R',' ')}, /* Kanuri [macrolanguage] */
+ {HB_TAG('k','s',' ',' '), HB_TAG('K','S','H',' ')}, /* Kashmiri */
+ {HB_TAG('k','u',' ',' '), HB_TAG('K','U','R',' ')}, /* Kurdish [macrolanguage] */
+ {HB_TAG('k','v',' ',' '), HB_TAG('K','O','M',' ')}, /* Komi [macrolanguage] */
+ {HB_TAG('k','w',' ',' '), HB_TAG('C','O','R',' ')}, /* Cornish */
+ {HB_TAG('k','y',' ',' '), HB_TAG('K','I','R',' ')}, /* Kirghiz (Kyrgyz) */
+ {HB_TAG('l','a',' ',' '), HB_TAG('L','A','T',' ')}, /* Latin */
+ {HB_TAG('l','b',' ',' '), HB_TAG('L','T','Z',' ')}, /* Luxembourgish */
+ {HB_TAG('l','g',' ',' '), HB_TAG('L','U','G',' ')}, /* Ganda */
+ {HB_TAG('l','i',' ',' '), HB_TAG('L','I','M',' ')}, /* Limburgish */
+ {HB_TAG('l','n',' ',' '), HB_TAG('L','I','N',' ')}, /* Lingala */
+ {HB_TAG('l','o',' ',' '), HB_TAG('L','A','O',' ')}, /* Lao */
+ {HB_TAG('l','t',' ',' '), HB_TAG('L','T','H',' ')}, /* Lithuanian */
+ {HB_TAG('l','u',' ',' '), HB_TAG('L','U','B',' ')}, /* Luba-Katanga */
+ {HB_TAG('l','v',' ',' '), HB_TAG('L','V','I',' ')}, /* Latvian [macrolanguage] */
+ {HB_TAG('m','g',' ',' '), HB_TAG('M','L','G',' ')}, /* Malagasy [macrolanguage] */
+ {HB_TAG('m','h',' ',' '), HB_TAG('M','A','H',' ')}, /* Marshallese */
+ {HB_TAG('m','i',' ',' '), HB_TAG('M','R','I',' ')}, /* Maori */
+ {HB_TAG('m','k',' ',' '), HB_TAG('M','K','D',' ')}, /* Macedonian */
+ {HB_TAG('m','l',' ',' '), HB_TAG('M','A','L',' ')}, /* Malayalam -> Malayalam Traditional */
+ {HB_TAG('m','l',' ',' '), HB_TAG('M','L','R',' ')}, /* Malayalam -> Malayalam Reformed */
+ {HB_TAG('m','n',' ',' '), HB_TAG('M','N','G',' ')}, /* Mongolian [macrolanguage] */
+ {HB_TAG('m','o',' ',' '), HB_TAG('M','O','L',' ')}, /* Moldavian (retired code) */
+ {HB_TAG('m','o',' ',' '), HB_TAG('R','O','M',' ')}, /* Moldavian (retired code) -> Romanian */
+ {HB_TAG('m','r',' ',' '), HB_TAG('M','A','R',' ')}, /* Marathi */
+ {HB_TAG('m','s',' ',' '), HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */
+ {HB_TAG('m','t',' ',' '), HB_TAG('M','T','S',' ')}, /* Maltese */
+ {HB_TAG('m','y',' ',' '), HB_TAG('B','R','M',' ')}, /* Burmese */
+ {HB_TAG('n','a',' ',' '), HB_TAG('N','A','U',' ')}, /* Nauru -> Nauruan */
+ {HB_TAG('n','b',' ',' '), HB_TAG('N','O','R',' ')}, /* Norwegian Bokmål -> Norwegian */
+ {HB_TAG('n','d',' ',' '), HB_TAG('N','D','B',' ')}, /* North Ndebele -> Ndebele */
+ {HB_TAG('n','e',' ',' '), HB_TAG('N','E','P',' ')}, /* Nepali [macrolanguage] */
+ {HB_TAG('n','g',' ',' '), HB_TAG('N','D','G',' ')}, /* Ndonga */
+ {HB_TAG('n','l',' ',' '), HB_TAG('N','L','D',' ')}, /* Dutch */
+ {HB_TAG('n','n',' ',' '), HB_TAG('N','Y','N',' ')}, /* Norwegian Nynorsk (Nynorsk, Norwegian) */
+ {HB_TAG('n','o',' ',' '), HB_TAG('N','O','R',' ')}, /* Norwegian [macrolanguage] */
+ {HB_TAG('n','r',' ',' '), HB_TAG('N','D','B',' ')}, /* South Ndebele -> Ndebele */
+ {HB_TAG('n','v',' ',' '), HB_TAG('N','A','V',' ')}, /* Navajo */
+ {HB_TAG('n','v',' ',' '), HB_TAG('A','T','H',' ')}, /* Navajo -> Athapaskan */
+ {HB_TAG('n','y',' ',' '), HB_TAG('C','H','I',' ')}, /* Chichewa (Chewa, Nyanja) */
+ {HB_TAG('o','c',' ',' '), HB_TAG('O','C','I',' ')}, /* Occitan (post 1500) */
+ {HB_TAG('o','j',' ',' '), HB_TAG('O','J','B',' ')}, /* Ojibwa [macrolanguage] -> Ojibway */
+ {HB_TAG('o','m',' ',' '), HB_TAG('O','R','O',' ')}, /* Oromo [macrolanguage] */
+ {HB_TAG('o','r',' ',' '), HB_TAG('O','R','I',' ')}, /* Odia (formerly Oriya) [macrolanguage] */
+ {HB_TAG('o','s',' ',' '), HB_TAG('O','S','S',' ')}, /* Ossetian */
+ {HB_TAG('p','a',' ',' '), HB_TAG('P','A','N',' ')}, /* Punjabi */
+ {HB_TAG('p','i',' ',' '), HB_TAG('P','A','L',' ')}, /* Pali */
+ {HB_TAG('p','l',' ',' '), HB_TAG('P','L','K',' ')}, /* Polish */
+ {HB_TAG('p','s',' ',' '), HB_TAG('P','A','S',' ')}, /* Pashto [macrolanguage] */
+ {HB_TAG('p','t',' ',' '), HB_TAG('P','T','G',' ')}, /* Portuguese */
+ {HB_TAG('q','u',' ',' '), HB_TAG('Q','U','Z',' ')}, /* Quechua [macrolanguage] */
+ {HB_TAG('r','m',' ',' '), HB_TAG('R','M','S',' ')}, /* Romansh */
+ {HB_TAG('r','n',' ',' '), HB_TAG('R','U','N',' ')}, /* Rundi */
+ {HB_TAG('r','o',' ',' '), HB_TAG('R','O','M',' ')}, /* Romanian */
+ {HB_TAG('r','u',' ',' '), HB_TAG('R','U','S',' ')}, /* Russian */
+ {HB_TAG('r','w',' ',' '), HB_TAG('R','U','A',' ')}, /* Kinyarwanda */
+ {HB_TAG('s','a',' ',' '), HB_TAG('S','A','N',' ')}, /* Sanskrit */
+ {HB_TAG('s','c',' ',' '), HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */
+ {HB_TAG('s','d',' ',' '), HB_TAG('S','N','D',' ')}, /* Sindhi */
+ {HB_TAG('s','e',' ',' '), HB_TAG('N','S','M',' ')}, /* Northern Sami */
+ {HB_TAG('s','g',' ',' '), HB_TAG('S','G','O',' ')}, /* Sango */
+ {HB_TAG('s','h',' ',' '), HB_TAG('B','O','S',' ')}, /* Serbo-Croatian [macrolanguage] -> Bosnian */
+ {HB_TAG('s','h',' ',' '), HB_TAG('H','R','V',' ')}, /* Serbo-Croatian [macrolanguage] -> Croatian */
+ {HB_TAG('s','h',' ',' '), HB_TAG('S','R','B',' ')}, /* Serbo-Croatian [macrolanguage] -> Serbian */
+ {HB_TAG('s','i',' ',' '), HB_TAG('S','N','H',' ')}, /* Sinhala (Sinhalese) */
+ {HB_TAG('s','k',' ',' '), HB_TAG('S','K','Y',' ')}, /* Slovak */
+ {HB_TAG('s','l',' ',' '), HB_TAG('S','L','V',' ')}, /* Slovenian */
+ {HB_TAG('s','m',' ',' '), HB_TAG('S','M','O',' ')}, /* Samoan */
+ {HB_TAG('s','n',' ',' '), HB_TAG('S','N','A','0')}, /* Shona */
+ {HB_TAG('s','o',' ',' '), HB_TAG('S','M','L',' ')}, /* Somali */
+ {HB_TAG('s','q',' ',' '), HB_TAG('S','Q','I',' ')}, /* Albanian [macrolanguage] */
+ {HB_TAG('s','r',' ',' '), HB_TAG('S','R','B',' ')}, /* Serbian */
+ {HB_TAG('s','s',' ',' '), HB_TAG('S','W','Z',' ')}, /* Swati */
+ {HB_TAG('s','t',' ',' '), HB_TAG('S','O','T',' ')}, /* Southern Sotho */
+ {HB_TAG('s','u',' ',' '), HB_TAG('S','U','N',' ')}, /* Sundanese */
+ {HB_TAG('s','v',' ',' '), HB_TAG('S','V','E',' ')}, /* Swedish */
+ {HB_TAG('s','w',' ',' '), HB_TAG('S','W','K',' ')}, /* Swahili [macrolanguage] */
+ {HB_TAG('t','a',' ',' '), HB_TAG('T','A','M',' ')}, /* Tamil */
+ {HB_TAG('t','e',' ',' '), HB_TAG('T','E','L',' ')}, /* Telugu */
+ {HB_TAG('t','g',' ',' '), HB_TAG('T','A','J',' ')}, /* Tajik -> Tajiki */
+ {HB_TAG('t','h',' ',' '), HB_TAG('T','H','A',' ')}, /* Thai */
+ {HB_TAG('t','i',' ',' '), HB_TAG('T','G','Y',' ')}, /* Tigrinya */
+ {HB_TAG('t','k',' ',' '), HB_TAG('T','K','M',' ')}, /* Turkmen */
+ {HB_TAG('t','l',' ',' '), HB_TAG('T','G','L',' ')}, /* Tagalog */
+ {HB_TAG('t','n',' ',' '), HB_TAG('T','N','A',' ')}, /* Tswana */
+ {HB_TAG('t','o',' ',' '), HB_TAG('T','G','N',' ')}, /* Tonga (Tonga Islands) -> Tongan */
+ {HB_TAG('t','r',' ',' '), HB_TAG('T','R','K',' ')}, /* Turkish */
+ {HB_TAG('t','s',' ',' '), HB_TAG('T','S','G',' ')}, /* Tsonga */
+ {HB_TAG('t','t',' ',' '), HB_TAG('T','A','T',' ')}, /* Tatar */
+ {HB_TAG('t','w',' ',' '), HB_TAG('T','W','I',' ')}, /* Twi */
+ {HB_TAG('t','w',' ',' '), HB_TAG('A','K','A',' ')}, /* Twi -> Akan */
+ {HB_TAG('t','y',' ',' '), HB_TAG('T','H','T',' ')}, /* Tahitian */
+ {HB_TAG('u','g',' ',' '), HB_TAG('U','Y','G',' ')}, /* Uyghur */
+ {HB_TAG('u','k',' ',' '), HB_TAG('U','K','R',' ')}, /* Ukrainian */
+ {HB_TAG('u','r',' ',' '), HB_TAG('U','R','D',' ')}, /* Urdu */
+ {HB_TAG('u','z',' ',' '), HB_TAG('U','Z','B',' ')}, /* Uzbek [macrolanguage] */
+ {HB_TAG('v','e',' ',' '), HB_TAG('V','E','N',' ')}, /* Venda */
+ {HB_TAG('v','i',' ',' '), HB_TAG('V','I','T',' ')}, /* Vietnamese */
+ {HB_TAG('v','o',' ',' '), HB_TAG('V','O','L',' ')}, /* Volapük */
+ {HB_TAG('w','a',' ',' '), HB_TAG('W','L','N',' ')}, /* Walloon */
+ {HB_TAG('w','o',' ',' '), HB_TAG('W','L','F',' ')}, /* Wolof */
+ {HB_TAG('x','h',' ',' '), HB_TAG('X','H','S',' ')}, /* Xhosa */
+ {HB_TAG('y','i',' ',' '), HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */
+ {HB_TAG('y','o',' ',' '), HB_TAG('Y','B','A',' ')}, /* Yoruba */
+ {HB_TAG('z','a',' ',' '), HB_TAG('Z','H','A',' ')}, /* Zhuang [macrolanguage] */
+ {HB_TAG('z','h',' ',' '), HB_TAG('Z','H','S',' ')}, /* Chinese, Simplified [macrolanguage] */
+ {HB_TAG('z','u',' ',' '), HB_TAG('Z','U','L',' ')}, /* Zulu */
+};
+
+static const LangTag ot_languages3[] = {
+ {HB_TAG('a','a','e',' '), HB_TAG('S','Q','I',' ')}, /* Arbëreshë Albanian -> Albanian */
+ {HB_TAG('a','a','o',' '), HB_TAG('A','R','A',' ')}, /* Algerian Saharan Arabic -> Arabic */
+ {HB_TAG('a','a','t',' '), HB_TAG('S','Q','I',' ')}, /* Arvanitika Albanian -> Albanian */
+ {HB_TAG('a','b','a',' '), HB_TAG_NONE }, /* Abé != Abaza */
+ {HB_TAG('a','b','h',' '), HB_TAG('A','R','A',' ')}, /* Tajiki Arabic -> Arabic */
+ {HB_TAG('a','b','q',' '), HB_TAG('A','B','A',' ')}, /* Abaza */
+ {HB_TAG('a','b','s',' '), HB_TAG('C','P','P',' ')}, /* Ambonese Malay -> Creoles */
+ {HB_TAG('a','b','v',' '), HB_TAG('A','R','A',' ')}, /* Baharna Arabic -> Arabic */
+ {HB_TAG('a','c','f',' '), HB_TAG('F','A','N',' ')}, /* Saint Lucian Creole French -> French Antillean */
+ {HB_TAG('a','c','f',' '), HB_TAG('C','P','P',' ')}, /* Saint Lucian Creole French -> Creoles */
+/*{HB_TAG('a','c','h',' '), HB_TAG('A','C','H',' ')},*/ /* Acoli -> Acholi */
+ {HB_TAG('a','c','m',' '), HB_TAG('A','R','A',' ')}, /* Mesopotamian Arabic -> Arabic */
+ {HB_TAG('a','c','q',' '), HB_TAG('A','R','A',' ')}, /* Ta'izzi-Adeni Arabic -> Arabic */
+ {HB_TAG('a','c','r',' '), HB_TAG('A','C','R',' ')}, /* Achi */
+ {HB_TAG('a','c','r',' '), HB_TAG('M','Y','N',' ')}, /* Achi -> Mayan */
+ {HB_TAG('a','c','w',' '), HB_TAG('A','R','A',' ')}, /* Hijazi Arabic -> Arabic */
+ {HB_TAG('a','c','x',' '), HB_TAG('A','R','A',' ')}, /* Omani Arabic -> Arabic */
+ {HB_TAG('a','c','y',' '), HB_TAG('A','R','A',' ')}, /* Cypriot Arabic -> Arabic */
+ {HB_TAG('a','d','a',' '), HB_TAG('D','N','G',' ')}, /* Adangme -> Dangme */
+ {HB_TAG('a','d','f',' '), HB_TAG('A','R','A',' ')}, /* Dhofari Arabic -> Arabic */
+ {HB_TAG('a','d','p',' '), HB_TAG('D','Z','N',' ')}, /* Adap (retired code) -> Dzongkha */
+/*{HB_TAG('a','d','y',' '), HB_TAG('A','D','Y',' ')},*/ /* Adyghe */
+ {HB_TAG('a','e','b',' '), HB_TAG('A','R','A',' ')}, /* Tunisian Arabic -> Arabic */
+ {HB_TAG('a','e','c',' '), HB_TAG('A','R','A',' ')}, /* Saidi Arabic -> Arabic */
+ {HB_TAG('a','f','b',' '), HB_TAG('A','R','A',' ')}, /* Gulf Arabic -> Arabic */
+ {HB_TAG('a','f','k',' '), HB_TAG_NONE }, /* Nanubae != Afrikaans */
+ {HB_TAG('a','f','s',' '), HB_TAG('C','P','P',' ')}, /* Afro-Seminole Creole -> Creoles */
+ {HB_TAG('a','g','u',' '), HB_TAG('M','Y','N',' ')}, /* Aguacateco -> Mayan */
+ {HB_TAG('a','g','w',' '), HB_TAG_NONE }, /* Kahua != Agaw */
+ {HB_TAG('a','h','g',' '), HB_TAG('A','G','W',' ')}, /* Qimant -> Agaw */
+ {HB_TAG('a','h','t',' '), HB_TAG('A','T','H',' ')}, /* Ahtena -> Athapaskan */
+ {HB_TAG('a','i','g',' '), HB_TAG('C','P','P',' ')}, /* Antigua and Barbuda Creole English -> Creoles */
+ {HB_TAG('a','i','i',' '), HB_TAG('S','W','A',' ')}, /* Assyrian Neo-Aramaic -> Swadaya Aramaic */
+ {HB_TAG('a','i','i',' '), HB_TAG('S','Y','R',' ')}, /* Assyrian Neo-Aramaic -> Syriac */
+/*{HB_TAG('a','i','o',' '), HB_TAG('A','I','O',' ')},*/ /* Aiton */
+ {HB_TAG('a','i','w',' '), HB_TAG('A','R','I',' ')}, /* Aari */
+ {HB_TAG('a','j','p',' '), HB_TAG('A','R','A',' ')}, /* South Levantine Arabic -> Arabic */
+ {HB_TAG('a','j','t',' '), HB_TAG('A','R','A',' ')}, /* Judeo-Tunisian Arabic (retired code) -> Arabic */
+ {HB_TAG('a','k','b',' '), HB_TAG('A','K','B',' ')}, /* Batak Angkola */
+ {HB_TAG('a','k','b',' '), HB_TAG('B','T','K',' ')}, /* Batak Angkola -> Batak */
+ {HB_TAG('a','l','n',' '), HB_TAG('S','Q','I',' ')}, /* Gheg Albanian -> Albanian */
+ {HB_TAG('a','l','s',' '), HB_TAG('S','Q','I',' ')}, /* Tosk Albanian -> Albanian */
+/*{HB_TAG('a','l','t',' '), HB_TAG('A','L','T',' ')},*/ /* Southern Altai -> Altai */
+ {HB_TAG('a','m','f',' '), HB_TAG('H','B','N',' ')}, /* Hamer-Banna -> Hammer-Banna */
+ {HB_TAG('a','m','w',' '), HB_TAG('S','Y','R',' ')}, /* Western Neo-Aramaic -> Syriac */
+/*{HB_TAG('a','n','g',' '), HB_TAG('A','N','G',' ')},*/ /* Old English (ca. 450-1100) -> Anglo-Saxon */
+ {HB_TAG('a','o','a',' '), HB_TAG('C','P','P',' ')}, /* Angolar -> Creoles */
+ {HB_TAG('a','p','a',' '), HB_TAG('A','T','H',' ')}, /* Apache [collection] -> Athapaskan */
+ {HB_TAG('a','p','c',' '), HB_TAG('A','R','A',' ')}, /* North Levantine Arabic -> Arabic */
+ {HB_TAG('a','p','d',' '), HB_TAG('A','R','A',' ')}, /* Sudanese Arabic -> Arabic */
+ {HB_TAG('a','p','j',' '), HB_TAG('A','T','H',' ')}, /* Jicarilla Apache -> Athapaskan */
+ {HB_TAG('a','p','k',' '), HB_TAG('A','T','H',' ')}, /* Kiowa Apache -> Athapaskan */
+ {HB_TAG('a','p','l',' '), HB_TAG('A','T','H',' ')}, /* Lipan Apache -> Athapaskan */
+ {HB_TAG('a','p','m',' '), HB_TAG('A','T','H',' ')}, /* Mescalero-Chiricahua Apache -> Athapaskan */
+ {HB_TAG('a','p','w',' '), HB_TAG('A','T','H',' ')}, /* Western Apache -> Athapaskan */
+ {HB_TAG('a','r','b',' '), HB_TAG('A','R','A',' ')}, /* Standard Arabic -> Arabic */
+ {HB_TAG('a','r','i',' '), HB_TAG_NONE }, /* Arikara != Aari */
+ {HB_TAG('a','r','k',' '), HB_TAG_NONE }, /* Arikapú != Rakhine */
+ {HB_TAG('a','r','n',' '), HB_TAG('M','A','P',' ')}, /* Mapudungun */
+ {HB_TAG('a','r','q',' '), HB_TAG('A','R','A',' ')}, /* Algerian Arabic -> Arabic */
+ {HB_TAG('a','r','s',' '), HB_TAG('A','R','A',' ')}, /* Najdi Arabic -> Arabic */
+ {HB_TAG('a','r','y',' '), HB_TAG('M','O','R',' ')}, /* Moroccan Arabic -> Moroccan */
+ {HB_TAG('a','r','y',' '), HB_TAG('A','R','A',' ')}, /* Moroccan Arabic -> Arabic */
+ {HB_TAG('a','r','z',' '), HB_TAG('A','R','A',' ')}, /* Egyptian Arabic -> Arabic */
+/*{HB_TAG('a','s','t',' '), HB_TAG('A','S','T',' ')},*/ /* Asturian */
+/*{HB_TAG('a','t','h',' '), HB_TAG('A','T','H',' ')},*/ /* Athapascan [collection] -> Athapaskan */
+ {HB_TAG('a','t','j',' '), HB_TAG('R','C','R',' ')}, /* Atikamekw -> R-Cree */
+ {HB_TAG('a','t','v',' '), HB_TAG('A','L','T',' ')}, /* Northern Altai -> Altai */
+ {HB_TAG('a','u','j',' '), HB_TAG('B','B','R',' ')}, /* Awjilah -> Berber */
+ {HB_TAG('a','u','z',' '), HB_TAG('A','R','A',' ')}, /* Uzbeki Arabic -> Arabic */
+ {HB_TAG('a','v','l',' '), HB_TAG('A','R','A',' ')}, /* Eastern Egyptian Bedawi Arabic -> Arabic */
+/*{HB_TAG('a','v','n',' '), HB_TAG('A','V','N',' ')},*/ /* Avatime */
+/*{HB_TAG('a','w','a',' '), HB_TAG('A','W','A',' ')},*/ /* Awadhi */
+ {HB_TAG('a','y','c',' '), HB_TAG('A','Y','M',' ')}, /* Southern Aymara -> Aymara */
+ {HB_TAG('a','y','h',' '), HB_TAG('A','R','A',' ')}, /* Hadrami Arabic -> Arabic */
+ {HB_TAG('a','y','l',' '), HB_TAG('A','R','A',' ')}, /* Libyan Arabic -> Arabic */
+ {HB_TAG('a','y','n',' '), HB_TAG('A','R','A',' ')}, /* Sanaani Arabic -> Arabic */
+ {HB_TAG('a','y','p',' '), HB_TAG('A','R','A',' ')}, /* North Mesopotamian Arabic -> Arabic */
+ {HB_TAG('a','y','r',' '), HB_TAG('A','Y','M',' ')}, /* Central Aymara -> Aymara */
+ {HB_TAG('a','z','b',' '), HB_TAG('A','Z','B',' ')}, /* South Azerbaijani -> Torki */
+ {HB_TAG('a','z','b',' '), HB_TAG('A','Z','E',' ')}, /* South Azerbaijani -> Azerbaijani */
+ {HB_TAG('a','z','d',' '), HB_TAG('N','A','H',' ')}, /* Eastern Durango Nahuatl -> Nahuatl */
+ {HB_TAG('a','z','j',' '), HB_TAG('A','Z','E',' ')}, /* North Azerbaijani -> Azerbaijani */
+ {HB_TAG('a','z','n',' '), HB_TAG('N','A','H',' ')}, /* Western Durango Nahuatl -> Nahuatl */
+ {HB_TAG('a','z','z',' '), HB_TAG('N','A','H',' ')}, /* Highland Puebla Nahuatl -> Nahuatl */
+ {HB_TAG('b','a','d',' '), HB_TAG('B','A','D','0')}, /* Banda [collection] */
+ {HB_TAG('b','a','g',' '), HB_TAG_NONE }, /* Tuki != Baghelkhandi */
+ {HB_TAG('b','a','h',' '), HB_TAG('C','P','P',' ')}, /* Bahamas Creole English -> Creoles */
+ {HB_TAG('b','a','i',' '), HB_TAG('B','M','L',' ')}, /* Bamileke [collection] */
+ {HB_TAG('b','a','l',' '), HB_TAG('B','L','I',' ')}, /* Baluchi [macrolanguage] */
+/*{HB_TAG('b','a','n',' '), HB_TAG('B','A','N',' ')},*/ /* Balinese */
+/*{HB_TAG('b','a','r',' '), HB_TAG('B','A','R',' ')},*/ /* Bavarian */
+ {HB_TAG('b','a','u',' '), HB_TAG_NONE }, /* Bada (Nigeria) != Baulé */
+ {HB_TAG('b','b','c',' '), HB_TAG('B','B','C',' ')}, /* Batak Toba */
+ {HB_TAG('b','b','c',' '), HB_TAG('B','T','K',' ')}, /* Batak Toba -> Batak */
+ {HB_TAG('b','b','j',' '), HB_TAG('B','M','L',' ')}, /* Ghomálá' -> Bamileke */
+ {HB_TAG('b','b','p',' '), HB_TAG('B','A','D','0')}, /* West Central Banda -> Banda */
+ {HB_TAG('b','b','r',' '), HB_TAG_NONE }, /* Girawa != Berber */
+ {HB_TAG('b','b','z',' '), HB_TAG('A','R','A',' ')}, /* Babalia Creole Arabic (retired code) -> Arabic */
+ {HB_TAG('b','c','c',' '), HB_TAG('B','L','I',' ')}, /* Southern Balochi -> Baluchi */
+ {HB_TAG('b','c','h',' '), HB_TAG_NONE }, /* Bariai != Bench */
+ {HB_TAG('b','c','i',' '), HB_TAG('B','A','U',' ')}, /* Baoulé -> Baulé */
+ {HB_TAG('b','c','l',' '), HB_TAG('B','I','K',' ')}, /* Central Bikol -> Bikol */
+ {HB_TAG('b','c','q',' '), HB_TAG('B','C','H',' ')}, /* Bench */
+ {HB_TAG('b','c','r',' '), HB_TAG('A','T','H',' ')}, /* Babine -> Athapaskan */
+/*{HB_TAG('b','d','y',' '), HB_TAG('B','D','Y',' ')},*/ /* Bandjalang */
+ {HB_TAG('b','e','a',' '), HB_TAG('A','T','H',' ')}, /* Beaver -> Athapaskan */
+ {HB_TAG('b','e','b',' '), HB_TAG('B','T','I',' ')}, /* Bebele -> Beti */
+/*{HB_TAG('b','e','m',' '), HB_TAG('B','E','M',' ')},*/ /* Bemba (Zambia) */
+ {HB_TAG('b','e','r',' '), HB_TAG('B','B','R',' ')}, /* Berber [collection] */
+ {HB_TAG('b','e','w',' '), HB_TAG('C','P','P',' ')}, /* Betawi -> Creoles */
+ {HB_TAG('b','f','l',' '), HB_TAG('B','A','D','0')}, /* Banda-Ndélé -> Banda */
+ {HB_TAG('b','f','q',' '), HB_TAG('B','A','D',' ')}, /* Badaga */
+ {HB_TAG('b','f','t',' '), HB_TAG('B','L','T',' ')}, /* Balti */
+ {HB_TAG('b','f','u',' '), HB_TAG('L','A','H',' ')}, /* Gahri -> Lahuli */
+ {HB_TAG('b','f','y',' '), HB_TAG('B','A','G',' ')}, /* Bagheli -> Baghelkhandi */
+/*{HB_TAG('b','g','c',' '), HB_TAG('B','G','C',' ')},*/ /* Haryanvi */
+ {HB_TAG('b','g','n',' '), HB_TAG('B','L','I',' ')}, /* Western Balochi -> Baluchi */
+ {HB_TAG('b','g','p',' '), HB_TAG('B','L','I',' ')}, /* Eastern Balochi -> Baluchi */
+ {HB_TAG('b','g','q',' '), HB_TAG('B','G','Q',' ')}, /* Bagri */
+ {HB_TAG('b','g','q',' '), HB_TAG('R','A','J',' ')}, /* Bagri -> Rajasthani */
+ {HB_TAG('b','g','r',' '), HB_TAG('Q','I','N',' ')}, /* Bawm Chin -> Chin */
+ {HB_TAG('b','h','b',' '), HB_TAG('B','H','I',' ')}, /* Bhili */
+/*{HB_TAG('b','h','i',' '), HB_TAG('B','H','I',' ')},*/ /* Bhilali -> Bhili */
+ {HB_TAG('b','h','k',' '), HB_TAG('B','I','K',' ')}, /* Albay Bicolano (retired code) -> Bikol */
+/*{HB_TAG('b','h','o',' '), HB_TAG('B','H','O',' ')},*/ /* Bhojpuri */
+ {HB_TAG('b','h','r',' '), HB_TAG('M','L','G',' ')}, /* Bara Malagasy -> Malagasy */
+/*{HB_TAG('b','i','k',' '), HB_TAG('B','I','K',' ')},*/ /* Bikol [macrolanguage] */
+ {HB_TAG('b','i','l',' '), HB_TAG_NONE }, /* Bile != Bilen */
+ {HB_TAG('b','i','n',' '), HB_TAG('E','D','O',' ')}, /* Edo */
+ {HB_TAG('b','i','u',' '), HB_TAG('Q','I','N',' ')}, /* Biete -> Chin */
+/*{HB_TAG('b','j','j',' '), HB_TAG('B','J','J',' ')},*/ /* Kanauji */
+ {HB_TAG('b','j','n',' '), HB_TAG('M','L','Y',' ')}, /* Banjar -> Malay */
+ {HB_TAG('b','j','o',' '), HB_TAG('B','A','D','0')}, /* Mid-Southern Banda -> Banda */
+ {HB_TAG('b','j','q',' '), HB_TAG('M','L','G',' ')}, /* Southern Betsimisaraka Malagasy (retired code) -> Malagasy */
+ {HB_TAG('b','j','s',' '), HB_TAG('C','P','P',' ')}, /* Bajan -> Creoles */
+ {HB_TAG('b','j','t',' '), HB_TAG('B','L','N',' ')}, /* Balanta-Ganja -> Balante */
+ {HB_TAG('b','k','f',' '), HB_TAG_NONE }, /* Beeke != Blackfoot */
+ {HB_TAG('b','k','o',' '), HB_TAG('B','M','L',' ')}, /* Kwa' -> Bamileke */
+ {HB_TAG('b','l','a',' '), HB_TAG('B','K','F',' ')}, /* Siksika -> Blackfoot */
+ {HB_TAG('b','l','e',' '), HB_TAG('B','L','N',' ')}, /* Balanta-Kentohe -> Balante */
+ {HB_TAG('b','l','g',' '), HB_TAG('I','B','A',' ')}, /* Balau (retired code) -> Iban */
+ {HB_TAG('b','l','i',' '), HB_TAG_NONE }, /* Bolia != Baluchi */
+ {HB_TAG('b','l','k',' '), HB_TAG('B','L','K',' ')}, /* Pa’o Karen */
+ {HB_TAG('b','l','k',' '), HB_TAG('K','R','N',' ')}, /* Pa'o Karen -> Karen */
+ {HB_TAG('b','l','n',' '), HB_TAG('B','I','K',' ')}, /* Southern Catanduanes Bikol -> Bikol */
+ {HB_TAG('b','l','t',' '), HB_TAG_NONE }, /* Tai Dam != Balti */
+ {HB_TAG('b','m','b',' '), HB_TAG_NONE }, /* Bembe != Bambara (Bamanankan) */
+ {HB_TAG('b','m','l',' '), HB_TAG_NONE }, /* Bomboli != Bamileke */
+ {HB_TAG('b','m','m',' '), HB_TAG('M','L','G',' ')}, /* Northern Betsimisaraka Malagasy -> Malagasy */
+ {HB_TAG('b','p','d',' '), HB_TAG('B','A','D','0')}, /* Banda-Banda -> Banda */
+ {HB_TAG('b','p','l',' '), HB_TAG('C','P','P',' ')}, /* Broome Pearling Lugger Pidgin -> Creoles */
+ {HB_TAG('b','p','q',' '), HB_TAG('C','P','P',' ')}, /* Banda Malay -> Creoles */
+/*{HB_TAG('b','p','y',' '), HB_TAG('B','P','Y',' ')},*/ /* Bishnupriya -> Bishnupriya Manipuri */
+ {HB_TAG('b','q','i',' '), HB_TAG('L','R','C',' ')}, /* Bakhtiari -> Luri */
+ {HB_TAG('b','q','k',' '), HB_TAG('B','A','D','0')}, /* Banda-Mbrès -> Banda */
+ {HB_TAG('b','r','a',' '), HB_TAG('B','R','I',' ')}, /* Braj -> Braj Bhasha */
+ {HB_TAG('b','r','c',' '), HB_TAG('C','P','P',' ')}, /* Berbice Creole Dutch -> Creoles */
+/*{HB_TAG('b','r','h',' '), HB_TAG('B','R','H',' ')},*/ /* Brahui */
+ {HB_TAG('b','r','i',' '), HB_TAG_NONE }, /* Mokpwe != Braj Bhasha */
+ {HB_TAG('b','r','m',' '), HB_TAG_NONE }, /* Barambu != Burmese */
+/*{HB_TAG('b','r','x',' '), HB_TAG('B','R','X',' ')},*/ /* Bodo (India) */
+ {HB_TAG('b','s','h',' '), HB_TAG_NONE }, /* Kati != Bashkir */
+/*{HB_TAG('b','s','k',' '), HB_TAG('B','S','K',' ')},*/ /* Burushaski */
+ {HB_TAG('b','t','b',' '), HB_TAG('B','T','I',' ')}, /* Beti (Cameroon) (retired code) */
+ {HB_TAG('b','t','d',' '), HB_TAG('B','T','D',' ')}, /* Batak Dairi (Pakpak) */
+ {HB_TAG('b','t','d',' '), HB_TAG('B','T','K',' ')}, /* Batak Dairi -> Batak */
+ {HB_TAG('b','t','i',' '), HB_TAG_NONE }, /* Burate != Beti */
+ {HB_TAG('b','t','j',' '), HB_TAG('M','L','Y',' ')}, /* Bacanese Malay -> Malay */
+/*{HB_TAG('b','t','k',' '), HB_TAG('B','T','K',' ')},*/ /* Batak [collection] */
+ {HB_TAG('b','t','m',' '), HB_TAG('B','T','M',' ')}, /* Batak Mandailing */
+ {HB_TAG('b','t','m',' '), HB_TAG('B','T','K',' ')}, /* Batak Mandailing -> Batak */
+ {HB_TAG('b','t','o',' '), HB_TAG('B','I','K',' ')}, /* Rinconada Bikol -> Bikol */
+ {HB_TAG('b','t','s',' '), HB_TAG('B','T','S',' ')}, /* Batak Simalungun */
+ {HB_TAG('b','t','s',' '), HB_TAG('B','T','K',' ')}, /* Batak Simalungun -> Batak */
+ {HB_TAG('b','t','x',' '), HB_TAG('B','T','X',' ')}, /* Batak Karo */
+ {HB_TAG('b','t','x',' '), HB_TAG('B','T','K',' ')}, /* Batak Karo -> Batak */
+ {HB_TAG('b','t','z',' '), HB_TAG('B','T','Z',' ')}, /* Batak Alas-Kluet */
+ {HB_TAG('b','t','z',' '), HB_TAG('B','T','K',' ')}, /* Batak Alas-Kluet -> Batak */
+/*{HB_TAG('b','u','g',' '), HB_TAG('B','U','G',' ')},*/ /* Buginese -> Bugis */
+ {HB_TAG('b','u','m',' '), HB_TAG('B','T','I',' ')}, /* Bulu (Cameroon) -> Beti */
+ {HB_TAG('b','v','e',' '), HB_TAG('M','L','Y',' ')}, /* Berau Malay -> Malay */
+ {HB_TAG('b','v','u',' '), HB_TAG('M','L','Y',' ')}, /* Bukit Malay -> Malay */
+ {HB_TAG('b','w','e',' '), HB_TAG('K','R','N',' ')}, /* Bwe Karen -> Karen */
+ {HB_TAG('b','x','k',' '), HB_TAG('L','U','H',' ')}, /* Bukusu -> Luyia */
+ {HB_TAG('b','x','o',' '), HB_TAG('C','P','P',' ')}, /* Barikanchi -> Creoles */
+ {HB_TAG('b','x','p',' '), HB_TAG('B','T','I',' ')}, /* Bebil -> Beti */
+ {HB_TAG('b','x','r',' '), HB_TAG('R','B','U',' ')}, /* Russia Buriat -> Russian Buriat */
+ {HB_TAG('b','y','n',' '), HB_TAG('B','I','L',' ')}, /* Bilin -> Bilen */
+ {HB_TAG('b','y','v',' '), HB_TAG('B','Y','V',' ')}, /* Medumba */
+ {HB_TAG('b','y','v',' '), HB_TAG('B','M','L',' ')}, /* Medumba -> Bamileke */
+ {HB_TAG('b','z','c',' '), HB_TAG('M','L','G',' ')}, /* Southern Betsimisaraka Malagasy -> Malagasy */
+ {HB_TAG('b','z','j',' '), HB_TAG('C','P','P',' ')}, /* Belize Kriol English -> Creoles */
+ {HB_TAG('b','z','k',' '), HB_TAG('C','P','P',' ')}, /* Nicaragua Creole English -> Creoles */
+ {HB_TAG('c','a','a',' '), HB_TAG('M','Y','N',' ')}, /* Chortí -> Mayan */
+ {HB_TAG('c','a','c',' '), HB_TAG('M','Y','N',' ')}, /* Chuj -> Mayan */
+ {HB_TAG('c','a','f',' '), HB_TAG('C','R','R',' ')}, /* Southern Carrier -> Carrier */
+ {HB_TAG('c','a','f',' '), HB_TAG('A','T','H',' ')}, /* Southern Carrier -> Athapaskan */
+ {HB_TAG('c','a','k',' '), HB_TAG('C','A','K',' ')}, /* Kaqchikel */
+ {HB_TAG('c','a','k',' '), HB_TAG('M','Y','N',' ')}, /* Kaqchikel -> Mayan */
+ {HB_TAG('c','b','k',' '), HB_TAG('C','B','K',' ')}, /* Chavacano -> Zamboanga Chavacano */
+ {HB_TAG('c','b','k',' '), HB_TAG('C','P','P',' ')}, /* Chavacano -> Creoles */
+ {HB_TAG('c','b','l',' '), HB_TAG('Q','I','N',' ')}, /* Bualkhaw Chin -> Chin */
+ {HB_TAG('c','c','l',' '), HB_TAG('C','P','P',' ')}, /* Cutchi-Swahili -> Creoles */
+ {HB_TAG('c','c','m',' '), HB_TAG('C','P','P',' ')}, /* Malaccan Creole Malay -> Creoles */
+ {HB_TAG('c','c','o',' '), HB_TAG('C','C','H','N')}, /* Comaltepec Chinantec -> Chinantec */
+ {HB_TAG('c','c','q',' '), HB_TAG('A','R','K',' ')}, /* Chaungtha (retired code) -> Rakhine */
+ {HB_TAG('c','d','o',' '), HB_TAG('Z','H','S',' ')}, /* Min Dong Chinese -> Chinese, Simplified */
+/*{HB_TAG('c','e','b',' '), HB_TAG('C','E','B',' ')},*/ /* Cebuano */
+ {HB_TAG('c','e','k',' '), HB_TAG('Q','I','N',' ')}, /* Eastern Khumi Chin -> Chin */
+ {HB_TAG('c','e','y',' '), HB_TAG('Q','I','N',' ')}, /* Ekai Chin -> Chin */
+ {HB_TAG('c','f','m',' '), HB_TAG('H','A','L',' ')}, /* Halam (Falam Chin) */
+ {HB_TAG('c','f','m',' '), HB_TAG('Q','I','N',' ')}, /* Falam Chin -> Chin */
+/*{HB_TAG('c','g','g',' '), HB_TAG('C','G','G',' ')},*/ /* Chiga */
+ {HB_TAG('c','h','f',' '), HB_TAG('M','Y','N',' ')}, /* Tabasco Chontal -> Mayan */
+ {HB_TAG('c','h','g',' '), HB_TAG_NONE }, /* Chagatai != Chaha Gurage */
+ {HB_TAG('c','h','h',' '), HB_TAG_NONE }, /* Chinook != Chattisgarhi */
+ {HB_TAG('c','h','j',' '), HB_TAG('C','C','H','N')}, /* Ojitlán Chinantec -> Chinantec */
+ {HB_TAG('c','h','k',' '), HB_TAG('C','H','K','0')}, /* Chuukese */
+ {HB_TAG('c','h','m',' '), HB_TAG('H','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> High Mari */
+ {HB_TAG('c','h','m',' '), HB_TAG('L','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> Low Mari */
+ {HB_TAG('c','h','n',' '), HB_TAG('C','P','P',' ')}, /* Chinook jargon -> Creoles */
+/*{HB_TAG('c','h','o',' '), HB_TAG('C','H','O',' ')},*/ /* Choctaw */
+ {HB_TAG('c','h','p',' '), HB_TAG('C','H','P',' ')}, /* Chipewyan */
+ {HB_TAG('c','h','p',' '), HB_TAG('S','A','Y',' ')}, /* Chipewyan -> Sayisi */
+ {HB_TAG('c','h','p',' '), HB_TAG('A','T','H',' ')}, /* Chipewyan -> Athapaskan */
+ {HB_TAG('c','h','q',' '), HB_TAG('C','C','H','N')}, /* Quiotepec Chinantec -> Chinantec */
+/*{HB_TAG('c','h','r',' '), HB_TAG('C','H','R',' ')},*/ /* Cherokee */
+/*{HB_TAG('c','h','y',' '), HB_TAG('C','H','Y',' ')},*/ /* Cheyenne */
+ {HB_TAG('c','h','z',' '), HB_TAG('C','C','H','N')}, /* Ozumacín Chinantec -> Chinantec */
+ {HB_TAG('c','i','w',' '), HB_TAG('O','J','B',' ')}, /* Chippewa -> Ojibway */
+/*{HB_TAG('c','j','a',' '), HB_TAG('C','J','A',' ')},*/ /* Western Cham */
+/*{HB_TAG('c','j','m',' '), HB_TAG('C','J','M',' ')},*/ /* Eastern Cham */
+ {HB_TAG('c','j','y',' '), HB_TAG('Z','H','S',' ')}, /* Jinyu Chinese -> Chinese, Simplified */
+ {HB_TAG('c','k','a',' '), HB_TAG('Q','I','N',' ')}, /* Khumi Awa Chin (retired code) -> Chin */
+ {HB_TAG('c','k','b',' '), HB_TAG('K','U','R',' ')}, /* Central Kurdish -> Kurdish */
+ {HB_TAG('c','k','n',' '), HB_TAG('Q','I','N',' ')}, /* Kaang Chin -> Chin */
+ {HB_TAG('c','k','s',' '), HB_TAG('C','P','P',' ')}, /* Tayo -> Creoles */
+ {HB_TAG('c','k','t',' '), HB_TAG('C','H','K',' ')}, /* Chukot -> Chukchi */
+ {HB_TAG('c','k','z',' '), HB_TAG('M','Y','N',' ')}, /* Cakchiquel-Quiché Mixed Language -> Mayan */
+ {HB_TAG('c','l','c',' '), HB_TAG('A','T','H',' ')}, /* Chilcotin -> Athapaskan */
+ {HB_TAG('c','l','d',' '), HB_TAG('S','Y','R',' ')}, /* Chaldean Neo-Aramaic -> Syriac */
+ {HB_TAG('c','l','e',' '), HB_TAG('C','C','H','N')}, /* Lealao Chinantec -> Chinantec */
+ {HB_TAG('c','l','j',' '), HB_TAG('Q','I','N',' ')}, /* Laitu Chin -> Chin */
+ {HB_TAG('c','l','t',' '), HB_TAG('Q','I','N',' ')}, /* Lautu Chin -> Chin */
+ {HB_TAG('c','m','n',' '), HB_TAG('Z','H','S',' ')}, /* Mandarin Chinese -> Chinese, Simplified */
+ {HB_TAG('c','m','r',' '), HB_TAG('Q','I','N',' ')}, /* Mro-Khimi Chin -> Chin */
+ {HB_TAG('c','n','b',' '), HB_TAG('Q','I','N',' ')}, /* Chinbon Chin -> Chin */
+ {HB_TAG('c','n','h',' '), HB_TAG('Q','I','N',' ')}, /* Hakha Chin -> Chin */
+ {HB_TAG('c','n','k',' '), HB_TAG('Q','I','N',' ')}, /* Khumi Chin -> Chin */
+ {HB_TAG('c','n','l',' '), HB_TAG('C','C','H','N')}, /* Lalana Chinantec -> Chinantec */
+ {HB_TAG('c','n','p',' '), HB_TAG('Z','H','S',' ')}, /* Northern Ping Chinese -> Chinese, Simplified */
+ {HB_TAG('c','n','r',' '), HB_TAG('S','R','B',' ')}, /* Montenegrin -> Serbian */
+ {HB_TAG('c','n','t',' '), HB_TAG('C','C','H','N')}, /* Tepetotutla Chinantec -> Chinantec */
+ {HB_TAG('c','n','u',' '), HB_TAG('B','B','R',' ')}, /* Chenoua -> Berber */
+ {HB_TAG('c','n','w',' '), HB_TAG('Q','I','N',' ')}, /* Ngawn Chin -> Chin */
+ {HB_TAG('c','o','a',' '), HB_TAG('M','L','Y',' ')}, /* Cocos Islands Malay -> Malay */
+ {HB_TAG('c','o','b',' '), HB_TAG('M','Y','N',' ')}, /* Chicomuceltec -> Mayan */
+/*{HB_TAG('c','o','p',' '), HB_TAG('C','O','P',' ')},*/ /* Coptic */
+ {HB_TAG('c','o','q',' '), HB_TAG('A','T','H',' ')}, /* Coquille -> Athapaskan */
+ {HB_TAG('c','p','a',' '), HB_TAG('C','C','H','N')}, /* Palantla Chinantec -> Chinantec */
+ {HB_TAG('c','p','e',' '), HB_TAG('C','P','P',' ')}, /* English-based creoles and pidgins [collection] -> Creoles */
+ {HB_TAG('c','p','f',' '), HB_TAG('C','P','P',' ')}, /* French-based creoles and pidgins [collection] -> Creoles */
+ {HB_TAG('c','p','i',' '), HB_TAG('C','P','P',' ')}, /* Chinese Pidgin English -> Creoles */
+/*{HB_TAG('c','p','p',' '), HB_TAG('C','P','P',' ')},*/ /* Portuguese-based creoles and pidgins [collection] -> Creoles */
+ {HB_TAG('c','p','x',' '), HB_TAG('Z','H','S',' ')}, /* Pu-Xian Chinese -> Chinese, Simplified */
+ {HB_TAG('c','q','d',' '), HB_TAG('H','M','N',' ')}, /* Chuanqiandian Cluster Miao -> Hmong */
+ {HB_TAG('c','q','u',' '), HB_TAG('Q','U','H',' ')}, /* Chilean Quechua (retired code) -> Quechua (Bolivia) */
+ {HB_TAG('c','q','u',' '), HB_TAG('Q','U','Z',' ')}, /* Chilean Quechua (retired code) -> Quechua */
+ {HB_TAG('c','r','h',' '), HB_TAG('C','R','T',' ')}, /* Crimean Tatar */
+ {HB_TAG('c','r','i',' '), HB_TAG('C','P','P',' ')}, /* Sãotomense -> Creoles */
+ {HB_TAG('c','r','j',' '), HB_TAG('E','C','R',' ')}, /* Southern East Cree -> Eastern Cree */
+ {HB_TAG('c','r','j',' '), HB_TAG('Y','C','R',' ')}, /* Southern East Cree -> Y-Cree */
+ {HB_TAG('c','r','j',' '), HB_TAG('C','R','E',' ')}, /* Southern East Cree -> Cree */
+ {HB_TAG('c','r','k',' '), HB_TAG('W','C','R',' ')}, /* Plains Cree -> West-Cree */
+ {HB_TAG('c','r','k',' '), HB_TAG('Y','C','R',' ')}, /* Plains Cree -> Y-Cree */
+ {HB_TAG('c','r','k',' '), HB_TAG('C','R','E',' ')}, /* Plains Cree -> Cree */
+ {HB_TAG('c','r','l',' '), HB_TAG('E','C','R',' ')}, /* Northern East Cree -> Eastern Cree */
+ {HB_TAG('c','r','l',' '), HB_TAG('Y','C','R',' ')}, /* Northern East Cree -> Y-Cree */
+ {HB_TAG('c','r','l',' '), HB_TAG('C','R','E',' ')}, /* Northern East Cree -> Cree */
+ {HB_TAG('c','r','m',' '), HB_TAG('M','C','R',' ')}, /* Moose Cree */
+ {HB_TAG('c','r','m',' '), HB_TAG('L','C','R',' ')}, /* Moose Cree -> L-Cree */
+ {HB_TAG('c','r','m',' '), HB_TAG('C','R','E',' ')}, /* Moose Cree -> Cree */
+ {HB_TAG('c','r','p',' '), HB_TAG('C','P','P',' ')}, /* Creoles and pidgins [collection] -> Creoles */
+ {HB_TAG('c','r','r',' '), HB_TAG_NONE }, /* Carolina Algonquian != Carrier */
+ {HB_TAG('c','r','s',' '), HB_TAG('C','P','P',' ')}, /* Seselwa Creole French -> Creoles */
+ {HB_TAG('c','r','t',' '), HB_TAG_NONE }, /* Iyojwa'ja Chorote != Crimean Tatar */
+ {HB_TAG('c','r','x',' '), HB_TAG('C','R','R',' ')}, /* Carrier */
+ {HB_TAG('c','r','x',' '), HB_TAG('A','T','H',' ')}, /* Carrier -> Athapaskan */
+ {HB_TAG('c','s','a',' '), HB_TAG('C','C','H','N')}, /* Chiltepec Chinantec -> Chinantec */
+/*{HB_TAG('c','s','b',' '), HB_TAG('C','S','B',' ')},*/ /* Kashubian */
+ {HB_TAG('c','s','h',' '), HB_TAG('Q','I','N',' ')}, /* Asho Chin -> Chin */
+ {HB_TAG('c','s','j',' '), HB_TAG('Q','I','N',' ')}, /* Songlai Chin -> Chin */
+ {HB_TAG('c','s','l',' '), HB_TAG_NONE }, /* Chinese Sign Language != Church Slavonic */
+ {HB_TAG('c','s','o',' '), HB_TAG('C','C','H','N')}, /* Sochiapam Chinantec -> Chinantec */
+ {HB_TAG('c','s','p',' '), HB_TAG('Z','H','S',' ')}, /* Southern Ping Chinese -> Chinese, Simplified */
+ {HB_TAG('c','s','v',' '), HB_TAG('Q','I','N',' ')}, /* Sumtu Chin -> Chin */
+ {HB_TAG('c','s','w',' '), HB_TAG('N','C','R',' ')}, /* Swampy Cree -> N-Cree */
+ {HB_TAG('c','s','w',' '), HB_TAG('N','H','C',' ')}, /* Swampy Cree -> Norway House Cree */
+ {HB_TAG('c','s','w',' '), HB_TAG('C','R','E',' ')}, /* Swampy Cree -> Cree */
+ {HB_TAG('c','s','y',' '), HB_TAG('Q','I','N',' ')}, /* Siyin Chin -> Chin */
+ {HB_TAG('c','t','c',' '), HB_TAG('A','T','H',' ')}, /* Chetco -> Athapaskan */
+ {HB_TAG('c','t','d',' '), HB_TAG('Q','I','N',' ')}, /* Tedim Chin -> Chin */
+ {HB_TAG('c','t','e',' '), HB_TAG('C','C','H','N')}, /* Tepinapa Chinantec -> Chinantec */
+/*{HB_TAG('c','t','g',' '), HB_TAG('C','T','G',' ')},*/ /* Chittagonian */
+ {HB_TAG('c','t','h',' '), HB_TAG('Q','I','N',' ')}, /* Thaiphum Chin -> Chin */
+ {HB_TAG('c','t','l',' '), HB_TAG('C','C','H','N')}, /* Tlacoatzintepec Chinantec -> Chinantec */
+ {HB_TAG('c','t','s',' '), HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol -> Bikol */
+/*{HB_TAG('c','t','t',' '), HB_TAG('C','T','T',' ')},*/ /* Wayanad Chetti */
+ {HB_TAG('c','t','u',' '), HB_TAG('M','Y','N',' ')}, /* Chol -> Mayan */
+ {HB_TAG('c','u','c',' '), HB_TAG('C','C','H','N')}, /* Usila Chinantec -> Chinantec */
+/*{HB_TAG('c','u','k',' '), HB_TAG('C','U','K',' ')},*/ /* San Blas Kuna */
+ {HB_TAG('c','v','n',' '), HB_TAG('C','C','H','N')}, /* Valle Nacional Chinantec -> Chinantec */
+ {HB_TAG('c','w','d',' '), HB_TAG('D','C','R',' ')}, /* Woods Cree */
+ {HB_TAG('c','w','d',' '), HB_TAG('T','C','R',' ')}, /* Woods Cree -> TH-Cree */
+ {HB_TAG('c','w','d',' '), HB_TAG('C','R','E',' ')}, /* Woods Cree -> Cree */
+ {HB_TAG('c','z','h',' '), HB_TAG('Z','H','S',' ')}, /* Huizhou Chinese -> Chinese, Simplified */
+ {HB_TAG('c','z','o',' '), HB_TAG('Z','H','S',' ')}, /* Min Zhong Chinese -> Chinese, Simplified */
+ {HB_TAG('c','z','t',' '), HB_TAG('Q','I','N',' ')}, /* Zotung Chin -> Chin */
+/*{HB_TAG('d','a','g',' '), HB_TAG('D','A','G',' ')},*/ /* Dagbani */
+ {HB_TAG('d','a','o',' '), HB_TAG('Q','I','N',' ')}, /* Daai Chin -> Chin */
+ {HB_TAG('d','a','p',' '), HB_TAG('N','I','S',' ')}, /* Nisi (India) (retired code) */
+/*{HB_TAG('d','a','r',' '), HB_TAG('D','A','R',' ')},*/ /* Dargwa */
+/*{HB_TAG('d','a','x',' '), HB_TAG('D','A','X',' ')},*/ /* Dayi */
+ {HB_TAG('d','c','r',' '), HB_TAG('C','P','P',' ')}, /* Negerhollands -> Creoles */
+ {HB_TAG('d','e','n',' '), HB_TAG('S','L','A',' ')}, /* Slave (Athapascan) [macrolanguage] -> Slavey */
+ {HB_TAG('d','e','n',' '), HB_TAG('A','T','H',' ')}, /* Slave (Athapascan) [macrolanguage] -> Athapaskan */
+ {HB_TAG('d','e','p',' '), HB_TAG('C','P','P',' ')}, /* Pidgin Delaware -> Creoles */
+ {HB_TAG('d','g','o',' '), HB_TAG('D','G','O',' ')}, /* Dogri (individual language) */
+ {HB_TAG('d','g','o',' '), HB_TAG('D','G','R',' ')}, /* Dogri (macrolanguage) */
+ {HB_TAG('d','g','r',' '), HB_TAG('A','T','H',' ')}, /* Dogrib -> Athapaskan */
+ {HB_TAG('d','h','d',' '), HB_TAG('M','A','W',' ')}, /* Dhundari -> Marwari */
+/*{HB_TAG('d','h','g',' '), HB_TAG('D','H','G',' ')},*/ /* Dhangu */
+ {HB_TAG('d','h','v',' '), HB_TAG_NONE }, /* Dehu != Divehi (Dhivehi, Maldivian) (deprecated) */
+ {HB_TAG('d','i','b',' '), HB_TAG('D','N','K',' ')}, /* South Central Dinka -> Dinka */
+ {HB_TAG('d','i','k',' '), HB_TAG('D','N','K',' ')}, /* Southwestern Dinka -> Dinka */
+ {HB_TAG('d','i','n',' '), HB_TAG('D','N','K',' ')}, /* Dinka [macrolanguage] */
+ {HB_TAG('d','i','p',' '), HB_TAG('D','N','K',' ')}, /* Northeastern Dinka -> Dinka */
+ {HB_TAG('d','i','q',' '), HB_TAG('D','I','Q',' ')}, /* Dimli */
+ {HB_TAG('d','i','q',' '), HB_TAG('Z','Z','A',' ')}, /* Dimli -> Zazaki */
+ {HB_TAG('d','i','w',' '), HB_TAG('D','N','K',' ')}, /* Northwestern Dinka -> Dinka */
+ {HB_TAG('d','j','e',' '), HB_TAG('D','J','R',' ')}, /* Zarma */
+ {HB_TAG('d','j','k',' '), HB_TAG('C','P','P',' ')}, /* Eastern Maroon Creole -> Creoles */
+ {HB_TAG('d','j','r',' '), HB_TAG('D','J','R','0')}, /* Djambarrpuyngu */
+ {HB_TAG('d','k','s',' '), HB_TAG('D','N','K',' ')}, /* Southeastern Dinka -> Dinka */
+ {HB_TAG('d','n','g',' '), HB_TAG('D','U','N',' ')}, /* Dungan */
+/*{HB_TAG('d','n','j',' '), HB_TAG('D','N','J',' ')},*/ /* Dan */
+ {HB_TAG('d','n','k',' '), HB_TAG_NONE }, /* Dengka != Dinka */
+ {HB_TAG('d','o','i',' '), HB_TAG('D','G','R',' ')}, /* Dogri (macrolanguage) [macrolanguage] */
+ {HB_TAG('d','r','h',' '), HB_TAG('M','N','G',' ')}, /* Darkhat (retired code) -> Mongolian */
+ {HB_TAG('d','r','i',' '), HB_TAG_NONE }, /* C'Lela != Dari */
+ {HB_TAG('d','r','w',' '), HB_TAG('D','R','I',' ')}, /* Darwazi (retired code) -> Dari */
+ {HB_TAG('d','r','w',' '), HB_TAG('F','A','R',' ')}, /* Darwazi (retired code) -> Persian */
+ {HB_TAG('d','s','b',' '), HB_TAG('L','S','B',' ')}, /* Lower Sorbian */
+ {HB_TAG('d','t','y',' '), HB_TAG('N','E','P',' ')}, /* Dotyali -> Nepali */
+/*{HB_TAG('d','u','j',' '), HB_TAG('D','U','J',' ')},*/ /* Dhuwal (retired code) */
+ {HB_TAG('d','u','n',' '), HB_TAG_NONE }, /* Dusun Deyah != Dungan */
+ {HB_TAG('d','u','p',' '), HB_TAG('M','L','Y',' ')}, /* Duano -> Malay */
+ {HB_TAG('d','w','k',' '), HB_TAG('K','U','I',' ')}, /* Dawik Kui -> Kui */
+ {HB_TAG('d','w','u',' '), HB_TAG('D','U','J',' ')}, /* Dhuwal */
+ {HB_TAG('d','w','y',' '), HB_TAG('D','U','J',' ')}, /* Dhuwaya -> Dhuwal */
+ {HB_TAG('d','y','u',' '), HB_TAG('J','U','L',' ')}, /* Dyula -> Jula */
+ {HB_TAG('d','z','n',' '), HB_TAG_NONE }, /* Dzando != Dzongkha */
+ {HB_TAG('e','c','r',' '), HB_TAG_NONE }, /* Eteocretan != Eastern Cree */
+/*{HB_TAG('e','f','i',' '), HB_TAG('E','F','I',' ')},*/ /* Efik */
+ {HB_TAG('e','k','k',' '), HB_TAG('E','T','I',' ')}, /* Standard Estonian -> Estonian */
+ {HB_TAG('e','k','y',' '), HB_TAG('K','R','N',' ')}, /* Eastern Kayah -> Karen */
+ {HB_TAG('e','m','k',' '), HB_TAG('E','M','K',' ')}, /* Eastern Maninkakan */
+ {HB_TAG('e','m','k',' '), HB_TAG('M','N','K',' ')}, /* Eastern Maninkakan -> Maninka */
+ {HB_TAG('e','m','y',' '), HB_TAG('M','Y','N',' ')}, /* Epigraphic Mayan -> Mayan */
+ {HB_TAG('e','n','b',' '), HB_TAG('K','A','L',' ')}, /* Markweeta -> Kalenjin */
+ {HB_TAG('e','n','f',' '), HB_TAG('F','N','E',' ')}, /* Forest Enets */
+ {HB_TAG('e','n','h',' '), HB_TAG('T','N','E',' ')}, /* Tundra Enets */
+ {HB_TAG('e','s','g',' '), HB_TAG('G','O','N',' ')}, /* Aheri Gondi -> Gondi */
+ {HB_TAG('e','s','i',' '), HB_TAG('I','P','K',' ')}, /* North Alaskan Inupiatun -> Inupiat */
+ {HB_TAG('e','s','k',' '), HB_TAG('I','P','K',' ')}, /* Northwest Alaska Inupiatun -> Inupiat */
+/*{HB_TAG('e','s','u',' '), HB_TAG('E','S','U',' ')},*/ /* Central Yupik */
+ {HB_TAG('e','t','o',' '), HB_TAG('B','T','I',' ')}, /* Eton (Cameroon) -> Beti */
+ {HB_TAG('e','u','q',' '), HB_TAG_NONE }, /* Basque [collection] != Basque */
+ {HB_TAG('e','v','e',' '), HB_TAG('E','V','N',' ')}, /* Even */
+ {HB_TAG('e','v','n',' '), HB_TAG('E','V','K',' ')}, /* Evenki */
+ {HB_TAG('e','w','o',' '), HB_TAG('B','T','I',' ')}, /* Ewondo -> Beti */
+ {HB_TAG('e','y','o',' '), HB_TAG('K','A','L',' ')}, /* Keiyo -> Kalenjin */
+ {HB_TAG('f','a','b',' '), HB_TAG('C','P','P',' ')}, /* Fa d'Ambu -> Creoles */
+ {HB_TAG('f','a','n',' '), HB_TAG('F','A','N','0')}, /* Fang (Equatorial Guinea) */
+ {HB_TAG('f','a','n',' '), HB_TAG('B','T','I',' ')}, /* Fang (Equatorial Guinea) -> Beti */
+ {HB_TAG('f','a','r',' '), HB_TAG_NONE }, /* Fataleka != Persian */
+ {HB_TAG('f','a','t',' '), HB_TAG('F','A','T',' ')}, /* Fanti */
+ {HB_TAG('f','a','t',' '), HB_TAG('A','K','A',' ')}, /* Fanti -> Akan */
+ {HB_TAG('f','b','l',' '), HB_TAG('B','I','K',' ')}, /* West Albay Bikol -> Bikol */
+ {HB_TAG('f','f','m',' '), HB_TAG('F','U','L',' ')}, /* Maasina Fulfulde -> Fulah */
+ {HB_TAG('f','i','l',' '), HB_TAG('P','I','L',' ')}, /* Filipino */
+ {HB_TAG('f','l','m',' '), HB_TAG('H','A','L',' ')}, /* Halam (Falam Chin) (retired code) */
+ {HB_TAG('f','l','m',' '), HB_TAG('Q','I','N',' ')}, /* Falam Chin (retired code) -> Chin */
+ {HB_TAG('f','m','p',' '), HB_TAG('F','M','P',' ')}, /* Fe’fe’ */
+ {HB_TAG('f','m','p',' '), HB_TAG('B','M','L',' ')}, /* Fe'fe' -> Bamileke */
+ {HB_TAG('f','n','g',' '), HB_TAG('C','P','P',' ')}, /* Fanagalo -> Creoles */
+/*{HB_TAG('f','o','n',' '), HB_TAG('F','O','N',' ')},*/ /* Fon */
+ {HB_TAG('f','o','s',' '), HB_TAG_NONE }, /* Siraya != Faroese */
+ {HB_TAG('f','p','e',' '), HB_TAG('C','P','P',' ')}, /* Fernando Po Creole English -> Creoles */
+/*{HB_TAG('f','r','c',' '), HB_TAG('F','R','C',' ')},*/ /* Cajun French */
+/*{HB_TAG('f','r','p',' '), HB_TAG('F','R','P',' ')},*/ /* Arpitan */
+ {HB_TAG('f','u','b',' '), HB_TAG('F','U','L',' ')}, /* Adamawa Fulfulde -> Fulah */
+ {HB_TAG('f','u','c',' '), HB_TAG('F','U','L',' ')}, /* Pulaar -> Fulah */
+ {HB_TAG('f','u','e',' '), HB_TAG('F','U','L',' ')}, /* Borgu Fulfulde -> Fulah */
+ {HB_TAG('f','u','f',' '), HB_TAG('F','T','A',' ')}, /* Pular -> Futa */
+ {HB_TAG('f','u','f',' '), HB_TAG('F','U','L',' ')}, /* Pular -> Fulah */
+ {HB_TAG('f','u','h',' '), HB_TAG('F','U','L',' ')}, /* Western Niger Fulfulde -> Fulah */
+ {HB_TAG('f','u','i',' '), HB_TAG('F','U','L',' ')}, /* Bagirmi Fulfulde -> Fulah */
+ {HB_TAG('f','u','q',' '), HB_TAG('F','U','L',' ')}, /* Central-Eastern Niger Fulfulde -> Fulah */
+ {HB_TAG('f','u','r',' '), HB_TAG('F','R','L',' ')}, /* Friulian */
+ {HB_TAG('f','u','v',' '), HB_TAG('F','U','V',' ')}, /* Nigerian Fulfulde */
+ {HB_TAG('f','u','v',' '), HB_TAG('F','U','L',' ')}, /* Nigerian Fulfulde -> Fulah */
+ {HB_TAG('g','a','a',' '), HB_TAG('G','A','D',' ')}, /* Ga */
+ {HB_TAG('g','a','c',' '), HB_TAG('C','P','P',' ')}, /* Mixed Great Andamanese -> Creoles */
+ {HB_TAG('g','a','d',' '), HB_TAG_NONE }, /* Gaddang != Ga */
+ {HB_TAG('g','a','e',' '), HB_TAG_NONE }, /* Guarequena != Scottish Gaelic (Gaelic) */
+/*{HB_TAG('g','a','g',' '), HB_TAG('G','A','G',' ')},*/ /* Gagauz */
+ {HB_TAG('g','a','l',' '), HB_TAG_NONE }, /* Galolen != Galician */
+ {HB_TAG('g','a','n',' '), HB_TAG('Z','H','S',' ')}, /* Gan Chinese -> Chinese, Simplified */
+ {HB_TAG('g','a','r',' '), HB_TAG_NONE }, /* Galeya != Garshuni */
+ {HB_TAG('g','a','w',' '), HB_TAG_NONE }, /* Nobonob != Garhwali */
+ {HB_TAG('g','a','x',' '), HB_TAG('O','R','O',' ')}, /* Borana-Arsi-Guji Oromo -> Oromo */
+ {HB_TAG('g','a','z',' '), HB_TAG('O','R','O',' ')}, /* West Central Oromo -> Oromo */
+ {HB_TAG('g','b','m',' '), HB_TAG('G','A','W',' ')}, /* Garhwali */
+ {HB_TAG('g','c','e',' '), HB_TAG('A','T','H',' ')}, /* Galice -> Athapaskan */
+ {HB_TAG('g','c','f',' '), HB_TAG('C','P','P',' ')}, /* Guadeloupean Creole French -> Creoles */
+ {HB_TAG('g','c','l',' '), HB_TAG('C','P','P',' ')}, /* Grenadian Creole English -> Creoles */
+ {HB_TAG('g','c','r',' '), HB_TAG('C','P','P',' ')}, /* Guianese Creole French -> Creoles */
+ {HB_TAG('g','d','a',' '), HB_TAG('R','A','J',' ')}, /* Gade Lohar -> Rajasthani */
+/*{HB_TAG('g','e','z',' '), HB_TAG('G','E','Z',' ')},*/ /* Geez */
+ {HB_TAG('g','g','o',' '), HB_TAG('G','O','N',' ')}, /* Southern Gondi (retired code) -> Gondi */
+ {HB_TAG('g','h','a',' '), HB_TAG('B','B','R',' ')}, /* Ghadamès -> Berber */
+ {HB_TAG('g','h','k',' '), HB_TAG('K','R','N',' ')}, /* Geko Karen -> Karen */
+ {HB_TAG('g','h','o',' '), HB_TAG('B','B','R',' ')}, /* Ghomara -> Berber */
+ {HB_TAG('g','i','b',' '), HB_TAG('C','P','P',' ')}, /* Gibanawa -> Creoles */
+/*{HB_TAG('g','i','h',' '), HB_TAG('G','I','H',' ')},*/ /* Githabul */
+ {HB_TAG('g','i','l',' '), HB_TAG('G','I','L','0')}, /* Kiribati (Gilbertese) */
+ {HB_TAG('g','j','u',' '), HB_TAG('R','A','J',' ')}, /* Gujari -> Rajasthani */
+ {HB_TAG('g','k','p',' '), HB_TAG('G','K','P',' ')}, /* Guinea Kpelle -> Kpelle (Guinea) */
+ {HB_TAG('g','k','p',' '), HB_TAG('K','P','L',' ')}, /* Guinea Kpelle -> Kpelle */
+ {HB_TAG('g','l','d',' '), HB_TAG('N','A','N',' ')}, /* Nanai */
+/*{HB_TAG('g','l','k',' '), HB_TAG('G','L','K',' ')},*/ /* Gilaki */
+ {HB_TAG('g','m','z',' '), HB_TAG_NONE }, /* Mgbolizhia != Gumuz */
+ {HB_TAG('g','n','b',' '), HB_TAG('Q','I','N',' ')}, /* Gangte -> Chin */
+/*{HB_TAG('g','n','n',' '), HB_TAG('G','N','N',' ')},*/ /* Gumatj */
+ {HB_TAG('g','n','o',' '), HB_TAG('G','O','N',' ')}, /* Northern Gondi -> Gondi */
+ {HB_TAG('g','n','w',' '), HB_TAG('G','U','A',' ')}, /* Western Bolivian Guaraní -> Guarani */
+/*{HB_TAG('g','o','g',' '), HB_TAG('G','O','G',' ')},*/ /* Gogo */
+ {HB_TAG('g','o','m',' '), HB_TAG('K','O','K',' ')}, /* Goan Konkani -> Konkani */
+/*{HB_TAG('g','o','n',' '), HB_TAG('G','O','N',' ')},*/ /* Gondi [macrolanguage] */
+ {HB_TAG('g','o','q',' '), HB_TAG('C','P','P',' ')}, /* Gorap -> Creoles */
+ {HB_TAG('g','o','x',' '), HB_TAG('B','A','D','0')}, /* Gobu -> Banda */
+ {HB_TAG('g','p','e',' '), HB_TAG('C','P','P',' ')}, /* Ghanaian Pidgin English -> Creoles */
+ {HB_TAG('g','r','o',' '), HB_TAG_NONE }, /* Groma != Garo */
+ {HB_TAG('g','r','r',' '), HB_TAG('B','B','R',' ')}, /* Taznatit -> Berber */
+ {HB_TAG('g','r','t',' '), HB_TAG('G','R','O',' ')}, /* Garo */
+ {HB_TAG('g','r','u',' '), HB_TAG('S','O','G',' ')}, /* Kistane -> Sodo Gurage */
+ {HB_TAG('g','s','w',' '), HB_TAG('A','L','S',' ')}, /* Alsatian */
+ {HB_TAG('g','u','a',' '), HB_TAG_NONE }, /* Shiki != Guarani */
+/*{HB_TAG('g','u','c',' '), HB_TAG('G','U','C',' ')},*/ /* Wayuu */
+/*{HB_TAG('g','u','f',' '), HB_TAG('G','U','F',' ')},*/ /* Gupapuyngu */
+ {HB_TAG('g','u','g',' '), HB_TAG('G','U','A',' ')}, /* Paraguayan Guaraní -> Guarani */
+ {HB_TAG('g','u','i',' '), HB_TAG('G','U','A',' ')}, /* Eastern Bolivian Guaraní -> Guarani */
+ {HB_TAG('g','u','k',' '), HB_TAG('G','M','Z',' ')}, /* Gumuz */
+ {HB_TAG('g','u','l',' '), HB_TAG('C','P','P',' ')}, /* Sea Island Creole English -> Creoles */
+ {HB_TAG('g','u','n',' '), HB_TAG('G','U','A',' ')}, /* Mbyá Guaraní -> Guarani */
+/*{HB_TAG('g','u','z',' '), HB_TAG('G','U','Z',' ')},*/ /* Gusii */
+ {HB_TAG('g','w','i',' '), HB_TAG('A','T','H',' ')}, /* Gwichʼin -> Athapaskan */
+ {HB_TAG('g','y','n',' '), HB_TAG('C','P','P',' ')}, /* Guyanese Creole English -> Creoles */
+ {HB_TAG('h','a','a',' '), HB_TAG('A','T','H',' ')}, /* Han -> Athapaskan */
+ {HB_TAG('h','a','e',' '), HB_TAG('O','R','O',' ')}, /* Eastern Oromo -> Oromo */
+ {HB_TAG('h','a','i',' '), HB_TAG('H','A','I','0')}, /* Haida [macrolanguage] */
+ {HB_TAG('h','a','k',' '), HB_TAG('Z','H','S',' ')}, /* Hakka Chinese -> Chinese, Simplified */
+ {HB_TAG('h','a','l',' '), HB_TAG_NONE }, /* Halang != Halam (Falam Chin) */
+ {HB_TAG('h','a','r',' '), HB_TAG('H','R','I',' ')}, /* Harari */
+/*{HB_TAG('h','a','w',' '), HB_TAG('H','A','W',' ')},*/ /* Hawaiian */
+ {HB_TAG('h','a','x',' '), HB_TAG('H','A','I','0')}, /* Southern Haida -> Haida */
+/*{HB_TAG('h','a','y',' '), HB_TAG('H','A','Y',' ')},*/ /* Haya */
+/*{HB_TAG('h','a','z',' '), HB_TAG('H','A','Z',' ')},*/ /* Hazaragi */
+ {HB_TAG('h','b','n',' '), HB_TAG_NONE }, /* Heiban != Hammer-Banna */
+ {HB_TAG('h','c','a',' '), HB_TAG('C','P','P',' ')}, /* Andaman Creole Hindi -> Creoles */
+ {HB_TAG('h','d','n',' '), HB_TAG('H','A','I','0')}, /* Northern Haida -> Haida */
+ {HB_TAG('h','e','a',' '), HB_TAG('H','M','N',' ')}, /* Northern Qiandong Miao -> Hmong */
+/*{HB_TAG('h','e','i',' '), HB_TAG('H','E','I',' ')},*/ /* Heiltsuk */
+/*{HB_TAG('h','i','l',' '), HB_TAG('H','I','L',' ')},*/ /* Hiligaynon */
+ {HB_TAG('h','j','i',' '), HB_TAG('M','L','Y',' ')}, /* Haji -> Malay */
+ {HB_TAG('h','l','t',' '), HB_TAG('Q','I','N',' ')}, /* Matu Chin -> Chin */
+ {HB_TAG('h','m','a',' '), HB_TAG('H','M','N',' ')}, /* Southern Mashan Hmong -> Hmong */
+ {HB_TAG('h','m','c',' '), HB_TAG('H','M','N',' ')}, /* Central Huishui Hmong -> Hmong */
+ {HB_TAG('h','m','d',' '), HB_TAG('H','M','D',' ')}, /* Large Flowery Miao -> A-Hmao */
+ {HB_TAG('h','m','d',' '), HB_TAG('H','M','N',' ')}, /* Large Flowery Miao -> Hmong */
+ {HB_TAG('h','m','e',' '), HB_TAG('H','M','N',' ')}, /* Eastern Huishui Hmong -> Hmong */
+ {HB_TAG('h','m','g',' '), HB_TAG('H','M','N',' ')}, /* Southwestern Guiyang Hmong -> Hmong */
+ {HB_TAG('h','m','h',' '), HB_TAG('H','M','N',' ')}, /* Southwestern Huishui Hmong -> Hmong */
+ {HB_TAG('h','m','i',' '), HB_TAG('H','M','N',' ')}, /* Northern Huishui Hmong -> Hmong */
+ {HB_TAG('h','m','j',' '), HB_TAG('H','M','N',' ')}, /* Ge -> Hmong */
+ {HB_TAG('h','m','l',' '), HB_TAG('H','M','N',' ')}, /* Luopohe Hmong -> Hmong */
+ {HB_TAG('h','m','m',' '), HB_TAG('H','M','N',' ')}, /* Central Mashan Hmong -> Hmong */
+/*{HB_TAG('h','m','n',' '), HB_TAG('H','M','N',' ')},*/ /* Hmong [macrolanguage] */
+ {HB_TAG('h','m','p',' '), HB_TAG('H','M','N',' ')}, /* Northern Mashan Hmong -> Hmong */
+ {HB_TAG('h','m','q',' '), HB_TAG('H','M','N',' ')}, /* Eastern Qiandong Miao -> Hmong */
+ {HB_TAG('h','m','r',' '), HB_TAG('Q','I','N',' ')}, /* Hmar -> Chin */
+ {HB_TAG('h','m','s',' '), HB_TAG('H','M','N',' ')}, /* Southern Qiandong Miao -> Hmong */
+ {HB_TAG('h','m','w',' '), HB_TAG('H','M','N',' ')}, /* Western Mashan Hmong -> Hmong */
+ {HB_TAG('h','m','y',' '), HB_TAG('H','M','N',' ')}, /* Southern Guiyang Hmong -> Hmong */
+ {HB_TAG('h','m','z',' '), HB_TAG('H','M','Z',' ')}, /* Hmong Shua -> Hmong Shuat */
+ {HB_TAG('h','m','z',' '), HB_TAG('H','M','N',' ')}, /* Hmong Shua -> Hmong */
+/*{HB_TAG('h','n','d',' '), HB_TAG('H','N','D',' ')},*/ /* Southern Hindko -> Hindko */
+ {HB_TAG('h','n','e',' '), HB_TAG('C','H','H',' ')}, /* Chhattisgarhi -> Chattisgarhi */
+ {HB_TAG('h','n','j',' '), HB_TAG('H','M','N',' ')}, /* Hmong Njua -> Hmong */
+ {HB_TAG('h','n','o',' '), HB_TAG('H','N','D',' ')}, /* Northern Hindko -> Hindko */
+ {HB_TAG('h','o','c',' '), HB_TAG('H','O',' ',' ')}, /* Ho */
+ {HB_TAG('h','o','i',' '), HB_TAG('A','T','H',' ')}, /* Holikachuk -> Athapaskan */
+ {HB_TAG('h','o','j',' '), HB_TAG('H','A','R',' ')}, /* Hadothi -> Harauti */
+ {HB_TAG('h','o','j',' '), HB_TAG('R','A','J',' ')}, /* Hadothi -> Rajasthani */
+ {HB_TAG('h','r','a',' '), HB_TAG('Q','I','N',' ')}, /* Hrangkhol -> Chin */
+ {HB_TAG('h','r','m',' '), HB_TAG('H','M','N',' ')}, /* Horned Miao -> Hmong */
+ {HB_TAG('h','s','b',' '), HB_TAG('U','S','B',' ')}, /* Upper Sorbian */
+ {HB_TAG('h','s','n',' '), HB_TAG('Z','H','S',' ')}, /* Xiang Chinese -> Chinese, Simplified */
+ {HB_TAG('h','u','j',' '), HB_TAG('H','M','N',' ')}, /* Northern Guiyang Hmong -> Hmong */
+ {HB_TAG('h','u','p',' '), HB_TAG('A','T','H',' ')}, /* Hupa -> Athapaskan */
+ {HB_TAG('h','u','s',' '), HB_TAG('M','Y','N',' ')}, /* Huastec -> Mayan */
+ {HB_TAG('h','w','c',' '), HB_TAG('C','P','P',' ')}, /* Hawai'i Creole English -> Creoles */
+ {HB_TAG('h','y','w',' '), HB_TAG('H','Y','E',' ')}, /* Western Armenian -> Armenian */
+/*{HB_TAG('i','b','a',' '), HB_TAG('I','B','A',' ')},*/ /* Iban */
+/*{HB_TAG('i','b','b',' '), HB_TAG('I','B','B',' ')},*/ /* Ibibio */
+ {HB_TAG('i','b','y',' '), HB_TAG('I','J','O',' ')}, /* Ibani -> Ijo */
+ {HB_TAG('i','c','r',' '), HB_TAG('C','P','P',' ')}, /* Islander Creole English -> Creoles */
+ {HB_TAG('i','d','a',' '), HB_TAG('L','U','H',' ')}, /* Idakho-Isukha-Tiriki -> Luyia */
+ {HB_TAG('i','d','b',' '), HB_TAG('C','P','P',' ')}, /* Indo-Portuguese -> Creoles */
+ {HB_TAG('i','g','b',' '), HB_TAG('E','B','I',' ')}, /* Ebira */
+ {HB_TAG('i','h','b',' '), HB_TAG('C','P','P',' ')}, /* Iha Based Pidgin -> Creoles */
+ {HB_TAG('i','j','c',' '), HB_TAG('I','J','O',' ')}, /* Izon -> Ijo */
+ {HB_TAG('i','j','e',' '), HB_TAG('I','J','O',' ')}, /* Biseni -> Ijo */
+ {HB_TAG('i','j','n',' '), HB_TAG('I','J','O',' ')}, /* Kalabari -> Ijo */
+/*{HB_TAG('i','j','o',' '), HB_TAG('I','J','O',' ')},*/ /* Ijo [collection] */
+ {HB_TAG('i','j','s',' '), HB_TAG('I','J','O',' ')}, /* Southeast Ijo -> Ijo */
+ {HB_TAG('i','k','e',' '), HB_TAG('I','N','U',' ')}, /* Eastern Canadian Inuktitut -> Inuktitut */
+ {HB_TAG('i','k','e',' '), HB_TAG('I','N','U','K')}, /* Eastern Canadian Inuktitut -> Nunavik Inuktitut */
+ {HB_TAG('i','k','t',' '), HB_TAG('I','N','U',' ')}, /* Inuinnaqtun -> Inuktitut */
+/*{HB_TAG('i','l','o',' '), HB_TAG('I','L','O',' ')},*/ /* Iloko -> Ilokano */
+ {HB_TAG('i','n','g',' '), HB_TAG('A','T','H',' ')}, /* Degexit'an -> Athapaskan */
+ {HB_TAG('i','n','h',' '), HB_TAG('I','N','G',' ')}, /* Ingush */
+ {HB_TAG('i','r','i',' '), HB_TAG_NONE }, /* Rigwe != Irish */
+/*{HB_TAG('i','r','u',' '), HB_TAG('I','R','U',' ')},*/ /* Irula */
+ {HB_TAG('i','s','m',' '), HB_TAG_NONE }, /* Masimasi != Inari Sami */
+ {HB_TAG('i','t','z',' '), HB_TAG('M','Y','N',' ')}, /* Itzá -> Mayan */
+ {HB_TAG('i','x','l',' '), HB_TAG('M','Y','N',' ')}, /* Ixil -> Mayan */
+ {HB_TAG('j','a','c',' '), HB_TAG('M','Y','N',' ')}, /* Popti' -> Mayan */
+ {HB_TAG('j','a','k',' '), HB_TAG('M','L','Y',' ')}, /* Jakun -> Malay */
+ {HB_TAG('j','a','m',' '), HB_TAG('J','A','M',' ')}, /* Jamaican Creole English -> Jamaican Creole */
+ {HB_TAG('j','a','m',' '), HB_TAG('C','P','P',' ')}, /* Jamaican Creole English -> Creoles */
+ {HB_TAG('j','a','n',' '), HB_TAG_NONE }, /* Jandai != Japanese */
+ {HB_TAG('j','a','x',' '), HB_TAG('M','L','Y',' ')}, /* Jambi Malay -> Malay */
+ {HB_TAG('j','b','e',' '), HB_TAG('B','B','R',' ')}, /* Judeo-Berber -> Berber */
+ {HB_TAG('j','b','n',' '), HB_TAG('B','B','R',' ')}, /* Nafusi -> Berber */
+/*{HB_TAG('j','b','o',' '), HB_TAG('J','B','O',' ')},*/ /* Lojban */
+/*{HB_TAG('j','c','t',' '), HB_TAG('J','C','T',' ')},*/ /* Krymchak */
+ {HB_TAG('j','g','o',' '), HB_TAG('B','M','L',' ')}, /* Ngomba -> Bamileke */
+ {HB_TAG('j','i','i',' '), HB_TAG_NONE }, /* Jiiddu != Yiddish */
+ {HB_TAG('j','k','m',' '), HB_TAG('K','R','N',' ')}, /* Mobwa Karen -> Karen */
+ {HB_TAG('j','k','p',' '), HB_TAG('K','R','N',' ')}, /* Paku Karen -> Karen */
+ {HB_TAG('j','u','d',' '), HB_TAG_NONE }, /* Worodougou != Ladino */
+ {HB_TAG('j','u','l',' '), HB_TAG_NONE }, /* Jirel != Jula */
+ {HB_TAG('j','v','d',' '), HB_TAG('C','P','P',' ')}, /* Javindo -> Creoles */
+ {HB_TAG('k','a','a',' '), HB_TAG('K','R','K',' ')}, /* Karakalpak */
+ {HB_TAG('k','a','b',' '), HB_TAG('K','A','B','0')}, /* Kabyle */
+ {HB_TAG('k','a','b',' '), HB_TAG('B','B','R',' ')}, /* Kabyle -> Berber */
+ {HB_TAG('k','a','c',' '), HB_TAG_NONE }, /* Kachin != Kachchi */
+ {HB_TAG('k','a','m',' '), HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */
+ {HB_TAG('k','a','r',' '), HB_TAG('K','R','N',' ')}, /* Karen [collection] */
+/*{HB_TAG('k','a','w',' '), HB_TAG('K','A','W',' ')},*/ /* Kawi (Old Javanese) */
+ {HB_TAG('k','b','d',' '), HB_TAG('K','A','B',' ')}, /* Kabardian */
+ {HB_TAG('k','b','y',' '), HB_TAG('K','N','R',' ')}, /* Manga Kanuri -> Kanuri */
+ {HB_TAG('k','c','a',' '), HB_TAG('K','H','K',' ')}, /* Khanty -> Khanty-Kazim */
+ {HB_TAG('k','c','a',' '), HB_TAG('K','H','S',' ')}, /* Khanty -> Khanty-Shurishkar */
+ {HB_TAG('k','c','a',' '), HB_TAG('K','H','V',' ')}, /* Khanty -> Khanty-Vakhi */
+ {HB_TAG('k','c','n',' '), HB_TAG('C','P','P',' ')}, /* Nubi -> Creoles */
+/*{HB_TAG('k','d','e',' '), HB_TAG('K','D','E',' ')},*/ /* Makonde */
+ {HB_TAG('k','d','r',' '), HB_TAG('K','R','M',' ')}, /* Karaim */
+ {HB_TAG('k','d','t',' '), HB_TAG('K','U','Y',' ')}, /* Kuy */
+ {HB_TAG('k','e','a',' '), HB_TAG('K','E','A',' ')}, /* Kabuverdianu (Crioulo) */
+ {HB_TAG('k','e','a',' '), HB_TAG('C','P','P',' ')}, /* Kabuverdianu -> Creoles */
+ {HB_TAG('k','e','b',' '), HB_TAG_NONE }, /* Kélé != Kebena */
+ {HB_TAG('k','e','k',' '), HB_TAG('K','E','K',' ')}, /* Kekchi */
+ {HB_TAG('k','e','k',' '), HB_TAG('M','Y','N',' ')}, /* Kekchí -> Mayan */
+ {HB_TAG('k','e','x',' '), HB_TAG('K','K','N',' ')}, /* Kukna -> Kokni */
+ {HB_TAG('k','f','a',' '), HB_TAG('K','O','D',' ')}, /* Kodava -> Kodagu */
+ {HB_TAG('k','f','r',' '), HB_TAG('K','A','C',' ')}, /* Kachhi -> Kachchi */
+ {HB_TAG('k','f','x',' '), HB_TAG('K','U','L',' ')}, /* Kullu Pahari -> Kulvi */
+ {HB_TAG('k','f','y',' '), HB_TAG('K','M','N',' ')}, /* Kumaoni */
+ {HB_TAG('k','g','e',' '), HB_TAG_NONE }, /* Komering != Khutsuri Georgian */
+ {HB_TAG('k','h','a',' '), HB_TAG('K','S','I',' ')}, /* Khasi */
+ {HB_TAG('k','h','b',' '), HB_TAG('X','B','D',' ')}, /* Lü */
+ {HB_TAG('k','h','k',' '), HB_TAG('M','N','G',' ')}, /* Halh Mongolian -> Mongolian */
+ {HB_TAG('k','h','n',' '), HB_TAG_NONE }, /* Khandesi != Khamti Shan (Microsoft fonts) */
+ {HB_TAG('k','h','s',' '), HB_TAG_NONE }, /* Kasua != Khanty-Shurishkar */
+ {HB_TAG('k','h','t',' '), HB_TAG('K','H','T',' ')}, /* Khamti -> Khamti Shan */
+ {HB_TAG('k','h','t',' '), HB_TAG('K','H','N',' ')}, /* Khamti -> Khamti Shan (Microsoft fonts) */
+ {HB_TAG('k','h','v',' '), HB_TAG_NONE }, /* Khvarshi != Khanty-Vakhi */
+/*{HB_TAG('k','h','w',' '), HB_TAG('K','H','W',' ')},*/ /* Khowar */
+ {HB_TAG('k','i','s',' '), HB_TAG_NONE }, /* Kis != Kisii */
+ {HB_TAG('k','i','u',' '), HB_TAG('K','I','U',' ')}, /* Kirmanjki */
+ {HB_TAG('k','i','u',' '), HB_TAG('Z','Z','A',' ')}, /* Kirmanjki -> Zazaki */
+ {HB_TAG('k','j','b',' '), HB_TAG('M','Y','N',' ')}, /* Q'anjob'al -> Mayan */
+/*{HB_TAG('k','j','d',' '), HB_TAG('K','J','D',' ')},*/ /* Southern Kiwai */
+ {HB_TAG('k','j','h',' '), HB_TAG('K','H','A',' ')}, /* Khakas -> Khakass */
+ {HB_TAG('k','j','p',' '), HB_TAG('K','J','P',' ')}, /* Pwo Eastern Karen -> Eastern Pwo Karen */
+ {HB_TAG('k','j','p',' '), HB_TAG('K','R','N',' ')}, /* Pwo Eastern Karen -> Karen */
+ {HB_TAG('k','j','t',' '), HB_TAG('K','R','N',' ')}, /* Phrae Pwo Karen -> Karen */
+/*{HB_TAG('k','j','z',' '), HB_TAG('K','J','Z',' ')},*/ /* Bumthangkha */
+ {HB_TAG('k','k','n',' '), HB_TAG_NONE }, /* Kon Keu != Kokni */
+ {HB_TAG('k','k','z',' '), HB_TAG('A','T','H',' ')}, /* Kaska -> Athapaskan */
+ {HB_TAG('k','l','m',' '), HB_TAG_NONE }, /* Migum != Kalmyk */
+ {HB_TAG('k','l','n',' '), HB_TAG('K','A','L',' ')}, /* Kalenjin [macrolanguage] */
+ {HB_TAG('k','m','b',' '), HB_TAG('M','B','N',' ')}, /* Kimbundu -> Mbundu */
+ {HB_TAG('k','m','n',' '), HB_TAG_NONE }, /* Awtuw != Kumaoni */
+ {HB_TAG('k','m','o',' '), HB_TAG_NONE }, /* Kwoma != Komo */
+ {HB_TAG('k','m','r',' '), HB_TAG('K','U','R',' ')}, /* Northern Kurdish -> Kurdish */
+ {HB_TAG('k','m','s',' '), HB_TAG_NONE }, /* Kamasau != Komso */
+ {HB_TAG('k','m','v',' '), HB_TAG('C','P','P',' ')}, /* Karipúna Creole French -> Creoles */
+ {HB_TAG('k','m','w',' '), HB_TAG('K','M','O',' ')}, /* Komo (Democratic Republic of Congo) */
+/*{HB_TAG('k','m','z',' '), HB_TAG('K','M','Z',' ')},*/ /* Khorasani Turkish -> Khorasani Turkic */
+ {HB_TAG('k','n','c',' '), HB_TAG('K','N','R',' ')}, /* Central Kanuri -> Kanuri */
+ {HB_TAG('k','n','g',' '), HB_TAG('K','O','N','0')}, /* Koongo -> Kongo */
+ {HB_TAG('k','n','j',' '), HB_TAG('M','Y','N',' ')}, /* Western Kanjobal -> Mayan */
+ {HB_TAG('k','n','n',' '), HB_TAG('K','O','K',' ')}, /* Konkani */
+ {HB_TAG('k','n','r',' '), HB_TAG_NONE }, /* Kaningra != Kanuri */
+ {HB_TAG('k','o','d',' '), HB_TAG_NONE }, /* Kodi != Kodagu */
+ {HB_TAG('k','o','h',' '), HB_TAG_NONE }, /* Koyo != Korean Old Hangul */
+ {HB_TAG('k','o','i',' '), HB_TAG('K','O','P',' ')}, /* Komi-Permyak */
+ {HB_TAG('k','o','i',' '), HB_TAG('K','O','M',' ')}, /* Komi-Permyak -> Komi */
+/*{HB_TAG('k','o','k',' '), HB_TAG('K','O','K',' ')},*/ /* Konkani [macrolanguage] */
+ {HB_TAG('k','o','p',' '), HB_TAG_NONE }, /* Waube != Komi-Permyak */
+/*{HB_TAG('k','o','s',' '), HB_TAG('K','O','S',' ')},*/ /* Kosraean */
+ {HB_TAG('k','o','y',' '), HB_TAG('A','T','H',' ')}, /* Koyukon -> Athapaskan */
+ {HB_TAG('k','o','z',' '), HB_TAG_NONE }, /* Korak != Komi-Zyrian */
+ {HB_TAG('k','p','e',' '), HB_TAG('K','P','L',' ')}, /* Kpelle [macrolanguage] */
+ {HB_TAG('k','p','l',' '), HB_TAG_NONE }, /* Kpala != Kpelle */
+ {HB_TAG('k','p','p',' '), HB_TAG('K','R','N',' ')}, /* Paku Karen (retired code) -> Karen */
+ {HB_TAG('k','p','v',' '), HB_TAG('K','O','Z',' ')}, /* Komi-Zyrian */
+ {HB_TAG('k','p','v',' '), HB_TAG('K','O','M',' ')}, /* Komi-Zyrian -> Komi */
+ {HB_TAG('k','p','y',' '), HB_TAG('K','Y','K',' ')}, /* Koryak */
+ {HB_TAG('k','q','s',' '), HB_TAG('K','I','S',' ')}, /* Northern Kissi -> Kisii */
+ {HB_TAG('k','q','y',' '), HB_TAG('K','R','T',' ')}, /* Koorete */
+ {HB_TAG('k','r','c',' '), HB_TAG('K','A','R',' ')}, /* Karachay-Balkar -> Karachay */
+ {HB_TAG('k','r','c',' '), HB_TAG('B','A','L',' ')}, /* Karachay-Balkar -> Balkar */
+ {HB_TAG('k','r','i',' '), HB_TAG('K','R','I',' ')}, /* Krio */
+ {HB_TAG('k','r','i',' '), HB_TAG('C','P','P',' ')}, /* Krio -> Creoles */
+ {HB_TAG('k','r','k',' '), HB_TAG_NONE }, /* Kerek != Karakalpak */
+/*{HB_TAG('k','r','l',' '), HB_TAG('K','R','L',' ')},*/ /* Karelian */
+ {HB_TAG('k','r','m',' '), HB_TAG_NONE }, /* Krim (retired code) != Karaim */
+ {HB_TAG('k','r','n',' '), HB_TAG_NONE }, /* Sapo != Karen */
+ {HB_TAG('k','r','t',' '), HB_TAG('K','N','R',' ')}, /* Tumari Kanuri -> Kanuri */
+ {HB_TAG('k','r','u',' '), HB_TAG('K','U','U',' ')}, /* Kurukh */
+ {HB_TAG('k','s','h',' '), HB_TAG('K','S','H','0')}, /* Kölsch -> Ripuarian */
+ {HB_TAG('k','s','i',' '), HB_TAG_NONE }, /* Krisa != Khasi */
+ {HB_TAG('k','s','m',' '), HB_TAG_NONE }, /* Kumba != Kildin Sami */
+ {HB_TAG('k','s','s',' '), HB_TAG('K','I','S',' ')}, /* Southern Kisi -> Kisii */
+ {HB_TAG('k','s','w',' '), HB_TAG('K','S','W',' ')}, /* S’gaw Karen */
+ {HB_TAG('k','s','w',' '), HB_TAG('K','R','N',' ')}, /* S'gaw Karen -> Karen */
+ {HB_TAG('k','t','b',' '), HB_TAG('K','E','B',' ')}, /* Kambaata -> Kebena */
+ {HB_TAG('k','t','u',' '), HB_TAG('K','O','N',' ')}, /* Kituba (Democratic Republic of Congo) -> Kikongo */
+ {HB_TAG('k','t','w',' '), HB_TAG('A','T','H',' ')}, /* Kato -> Athapaskan */
+ {HB_TAG('k','u','i',' '), HB_TAG_NONE }, /* Kuikúro-Kalapálo != Kui */
+ {HB_TAG('k','u','l',' '), HB_TAG_NONE }, /* Kulere != Kulvi */
+/*{HB_TAG('k','u','m',' '), HB_TAG('K','U','M',' ')},*/ /* Kumyk */
+ {HB_TAG('k','u','u',' '), HB_TAG('A','T','H',' ')}, /* Upper Kuskokwim -> Athapaskan */
+ {HB_TAG('k','u','w',' '), HB_TAG('B','A','D','0')}, /* Kpagua -> Banda */
+ {HB_TAG('k','u','y',' '), HB_TAG_NONE }, /* Kuuku-Ya'u != Kuy */
+ {HB_TAG('k','v','b',' '), HB_TAG('M','L','Y',' ')}, /* Kubu -> Malay */
+ {HB_TAG('k','v','l',' '), HB_TAG('K','R','N',' ')}, /* Kayaw -> Karen */
+ {HB_TAG('k','v','q',' '), HB_TAG('K','R','N',' ')}, /* Geba Karen -> Karen */
+ {HB_TAG('k','v','r',' '), HB_TAG('M','L','Y',' ')}, /* Kerinci -> Malay */
+ {HB_TAG('k','v','t',' '), HB_TAG('K','R','N',' ')}, /* Lahta Karen -> Karen */
+ {HB_TAG('k','v','u',' '), HB_TAG('K','R','N',' ')}, /* Yinbaw Karen -> Karen */
+ {HB_TAG('k','v','y',' '), HB_TAG('K','R','N',' ')}, /* Yintale Karen -> Karen */
+/*{HB_TAG('k','w','k',' '), HB_TAG('K','W','K',' ')},*/ /* Kwakiutl -> Kwakʼwala */
+ {HB_TAG('k','w','w',' '), HB_TAG('C','P','P',' ')}, /* Kwinti -> Creoles */
+ {HB_TAG('k','w','y',' '), HB_TAG('K','O','N','0')}, /* San Salvador Kongo -> Kongo */
+ {HB_TAG('k','x','c',' '), HB_TAG('K','M','S',' ')}, /* Konso -> Komso */
+ {HB_TAG('k','x','d',' '), HB_TAG('M','L','Y',' ')}, /* Brunei -> Malay */
+ {HB_TAG('k','x','f',' '), HB_TAG('K','R','N',' ')}, /* Manumanaw Karen -> Karen */
+ {HB_TAG('k','x','k',' '), HB_TAG('K','R','N',' ')}, /* Zayein Karen -> Karen */
+ {HB_TAG('k','x','l',' '), HB_TAG('K','U','U',' ')}, /* Nepali Kurux (retired code) -> Kurukh */
+ {HB_TAG('k','x','u',' '), HB_TAG('K','U','I',' ')}, /* Kui (India) (retired code) */
+ {HB_TAG('k','y','k',' '), HB_TAG_NONE }, /* Kamayo != Koryak */
+ {HB_TAG('k','y','u',' '), HB_TAG('K','Y','U',' ')}, /* Western Kayah */
+ {HB_TAG('k','y','u',' '), HB_TAG('K','R','N',' ')}, /* Western Kayah -> Karen */
+ {HB_TAG('l','a','c',' '), HB_TAG('M','Y','N',' ')}, /* Lacandon -> Mayan */
+ {HB_TAG('l','a','d',' '), HB_TAG('J','U','D',' ')}, /* Ladino */
+ {HB_TAG('l','a','h',' '), HB_TAG_NONE }, /* Lahnda [macrolanguage] != Lahuli */
+ {HB_TAG('l','a','k',' '), HB_TAG_NONE }, /* Laka (Nigeria) (retired code) != Lak */
+ {HB_TAG('l','a','m',' '), HB_TAG_NONE }, /* Lamba != Lambani */
+ {HB_TAG('l','a','z',' '), HB_TAG_NONE }, /* Aribwatsa != Laz */
+ {HB_TAG('l','b','e',' '), HB_TAG('L','A','K',' ')}, /* Lak */
+ {HB_TAG('l','b','j',' '), HB_TAG('L','D','K',' ')}, /* Ladakhi */
+ {HB_TAG('l','b','l',' '), HB_TAG('B','I','K',' ')}, /* Libon Bikol -> Bikol */
+ {HB_TAG('l','c','e',' '), HB_TAG('M','L','Y',' ')}, /* Loncong -> Malay */
+ {HB_TAG('l','c','f',' '), HB_TAG('M','L','Y',' ')}, /* Lubu -> Malay */
+ {HB_TAG('l','d','i',' '), HB_TAG('K','O','N','0')}, /* Laari -> Kongo */
+ {HB_TAG('l','d','k',' '), HB_TAG_NONE }, /* Leelau != Ladakhi */
+/*{HB_TAG('l','e','f',' '), HB_TAG('L','E','F',' ')},*/ /* Lelemi */
+/*{HB_TAG('l','e','z',' '), HB_TAG('L','E','Z',' ')},*/ /* Lezghian -> Lezgi */
+ {HB_TAG('l','i','f',' '), HB_TAG('L','M','B',' ')}, /* Limbu */
+/*{HB_TAG('l','i','j',' '), HB_TAG('L','I','J',' ')},*/ /* Ligurian */
+ {HB_TAG('l','i','r',' '), HB_TAG('C','P','P',' ')}, /* Liberian English -> Creoles */
+/*{HB_TAG('l','i','s',' '), HB_TAG('L','I','S',' ')},*/ /* Lisu */
+ {HB_TAG('l','i','w',' '), HB_TAG('M','L','Y',' ')}, /* Col -> Malay */
+ {HB_TAG('l','i','y',' '), HB_TAG('B','A','D','0')}, /* Banda-Bambari -> Banda */
+/*{HB_TAG('l','j','p',' '), HB_TAG('L','J','P',' ')},*/ /* Lampung Api -> Lampung */
+ {HB_TAG('l','k','b',' '), HB_TAG('L','U','H',' ')}, /* Kabras -> Luyia */
+/*{HB_TAG('l','k','i',' '), HB_TAG('L','K','I',' ')},*/ /* Laki */
+ {HB_TAG('l','k','o',' '), HB_TAG('L','U','H',' ')}, /* Khayo -> Luyia */
+ {HB_TAG('l','k','s',' '), HB_TAG('L','U','H',' ')}, /* Kisa -> Luyia */
+ {HB_TAG('l','l','d',' '), HB_TAG('L','A','D',' ')}, /* Ladin */
+ {HB_TAG('l','m','a',' '), HB_TAG_NONE }, /* East Limba != Low Mari */
+ {HB_TAG('l','m','b',' '), HB_TAG_NONE }, /* Merei != Limbu */
+ {HB_TAG('l','m','n',' '), HB_TAG('L','A','M',' ')}, /* Lambadi -> Lambani */
+/*{HB_TAG('l','m','o',' '), HB_TAG('L','M','O',' ')},*/ /* Lombard */
+ {HB_TAG('l','m','w',' '), HB_TAG_NONE }, /* Lake Miwok != Lomwe */
+ {HB_TAG('l','n','a',' '), HB_TAG('B','A','D','0')}, /* Langbashe -> Banda */
+ {HB_TAG('l','n','l',' '), HB_TAG('B','A','D','0')}, /* South Central Banda -> Banda */
+/*{HB_TAG('l','o','m',' '), HB_TAG('L','O','M',' ')},*/ /* Loma (Liberia) */
+ {HB_TAG('l','o','u',' '), HB_TAG('C','P','P',' ')}, /* Louisiana Creole -> Creoles */
+/*{HB_TAG('l','p','o',' '), HB_TAG('L','P','O',' ')},*/ /* Lipo */
+/*{HB_TAG('l','r','c',' '), HB_TAG('L','R','C',' ')},*/ /* Northern Luri -> Luri */
+ {HB_TAG('l','r','i',' '), HB_TAG('L','U','H',' ')}, /* Marachi -> Luyia */
+ {HB_TAG('l','r','m',' '), HB_TAG('L','U','H',' ')}, /* Marama -> Luyia */
+ {HB_TAG('l','r','t',' '), HB_TAG('C','P','P',' ')}, /* Larantuka Malay -> Creoles */
+ {HB_TAG('l','s','b',' '), HB_TAG_NONE }, /* Burundian Sign Language != Lower Sorbian */
+ {HB_TAG('l','s','m',' '), HB_TAG('L','U','H',' ')}, /* Saamia -> Luyia */
+ {HB_TAG('l','t','g',' '), HB_TAG('L','V','I',' ')}, /* Latgalian -> Latvian */
+ {HB_TAG('l','t','h',' '), HB_TAG_NONE }, /* Thur != Lithuanian */
+ {HB_TAG('l','t','o',' '), HB_TAG('L','U','H',' ')}, /* Tsotso -> Luyia */
+ {HB_TAG('l','t','s',' '), HB_TAG('L','U','H',' ')}, /* Tachoni -> Luyia */
+/*{HB_TAG('l','u','a',' '), HB_TAG('L','U','A',' ')},*/ /* Luba-Lulua */
+/*{HB_TAG('l','u','o',' '), HB_TAG('L','U','O',' ')},*/ /* Luo (Kenya and Tanzania) */
+ {HB_TAG('l','u','s',' '), HB_TAG('M','I','Z',' ')}, /* Lushai -> Mizo */
+ {HB_TAG('l','u','s',' '), HB_TAG('Q','I','N',' ')}, /* Lushai -> Chin */
+ {HB_TAG('l','u','y',' '), HB_TAG('L','U','H',' ')}, /* Luyia [macrolanguage] */
+ {HB_TAG('l','u','z',' '), HB_TAG('L','R','C',' ')}, /* Southern Luri -> Luri */
+ {HB_TAG('l','v','i',' '), HB_TAG_NONE }, /* Lavi != Latvian */
+ {HB_TAG('l','v','s',' '), HB_TAG('L','V','I',' ')}, /* Standard Latvian -> Latvian */
+ {HB_TAG('l','w','g',' '), HB_TAG('L','U','H',' ')}, /* Wanga -> Luyia */
+ {HB_TAG('l','z','h',' '), HB_TAG('Z','H','T',' ')}, /* Literary Chinese -> Chinese, Traditional */
+ {HB_TAG('l','z','z',' '), HB_TAG('L','A','Z',' ')}, /* Laz */
+/*{HB_TAG('m','a','d',' '), HB_TAG('M','A','D',' ')},*/ /* Madurese -> Madura */
+/*{HB_TAG('m','a','g',' '), HB_TAG('M','A','G',' ')},*/ /* Magahi */
+ {HB_TAG('m','a','i',' '), HB_TAG('M','T','H',' ')}, /* Maithili */
+ {HB_TAG('m','a','j',' '), HB_TAG_NONE }, /* Jalapa De Díaz Mazatec != Majang */
+ {HB_TAG('m','a','k',' '), HB_TAG('M','K','R',' ')}, /* Makasar */
+ {HB_TAG('m','a','m',' '), HB_TAG('M','A','M',' ')}, /* Mam */
+ {HB_TAG('m','a','m',' '), HB_TAG('M','Y','N',' ')}, /* Mam -> Mayan */
+ {HB_TAG('m','a','n',' '), HB_TAG('M','N','K',' ')}, /* Mandingo [macrolanguage] -> Maninka */
+ {HB_TAG('m','a','p',' '), HB_TAG_NONE }, /* Austronesian [collection] != Mapudungun */
+ {HB_TAG('m','a','w',' '), HB_TAG_NONE }, /* Mampruli != Marwari */
+ {HB_TAG('m','a','x',' '), HB_TAG('M','L','Y',' ')}, /* North Moluccan Malay -> Malay */
+ {HB_TAG('m','a','x',' '), HB_TAG('C','P','P',' ')}, /* North Moluccan Malay -> Creoles */
+ {HB_TAG('m','b','f',' '), HB_TAG('C','P','P',' ')}, /* Baba Malay -> Creoles */
+ {HB_TAG('m','b','n',' '), HB_TAG_NONE }, /* Macaguán != Mbundu */
+/*{HB_TAG('m','b','o',' '), HB_TAG('M','B','O',' ')},*/ /* Mbo (Cameroon) */
+ {HB_TAG('m','c','h',' '), HB_TAG_NONE }, /* Maquiritari != Manchu */
+ {HB_TAG('m','c','m',' '), HB_TAG('C','P','P',' ')}, /* Malaccan Creole Portuguese -> Creoles */
+ {HB_TAG('m','c','r',' '), HB_TAG_NONE }, /* Menya != Moose Cree */
+ {HB_TAG('m','c','t',' '), HB_TAG('B','T','I',' ')}, /* Mengisa -> Beti */
+ {HB_TAG('m','d','e',' '), HB_TAG_NONE }, /* Maba (Chad) != Mende */
+ {HB_TAG('m','d','f',' '), HB_TAG('M','O','K',' ')}, /* Moksha */
+/*{HB_TAG('m','d','r',' '), HB_TAG('M','D','R',' ')},*/ /* Mandar */
+ {HB_TAG('m','d','y',' '), HB_TAG('M','L','E',' ')}, /* Male (Ethiopia) */
+ {HB_TAG('m','e','n',' '), HB_TAG('M','D','E',' ')}, /* Mende (Sierra Leone) */
+ {HB_TAG('m','e','o',' '), HB_TAG('M','L','Y',' ')}, /* Kedah Malay -> Malay */
+/*{HB_TAG('m','e','r',' '), HB_TAG('M','E','R',' ')},*/ /* Meru */
+ {HB_TAG('m','f','a',' '), HB_TAG('M','F','A',' ')}, /* Pattani Malay */
+ {HB_TAG('m','f','a',' '), HB_TAG('M','L','Y',' ')}, /* Pattani Malay -> Malay */
+ {HB_TAG('m','f','b',' '), HB_TAG('M','L','Y',' ')}, /* Bangka -> Malay */
+ {HB_TAG('m','f','e',' '), HB_TAG('M','F','E',' ')}, /* Morisyen */
+ {HB_TAG('m','f','e',' '), HB_TAG('C','P','P',' ')}, /* Morisyen -> Creoles */
+ {HB_TAG('m','f','p',' '), HB_TAG('C','P','P',' ')}, /* Makassar Malay -> Creoles */
+ {HB_TAG('m','h','c',' '), HB_TAG('M','Y','N',' ')}, /* Mocho -> Mayan */
+ {HB_TAG('m','h','r',' '), HB_TAG('L','M','A',' ')}, /* Eastern Mari -> Low Mari */
+ {HB_TAG('m','h','v',' '), HB_TAG('A','R','K',' ')}, /* Arakanese (retired code) -> Rakhine */
+ {HB_TAG('m','i','n',' '), HB_TAG('M','I','N',' ')}, /* Minangkabau */
+ {HB_TAG('m','i','n',' '), HB_TAG('M','L','Y',' ')}, /* Minangkabau -> Malay */
+ {HB_TAG('m','i','z',' '), HB_TAG_NONE }, /* Coatzospan Mixtec != Mizo */
+ {HB_TAG('m','k','n',' '), HB_TAG('C','P','P',' ')}, /* Kupang Malay -> Creoles */
+ {HB_TAG('m','k','r',' '), HB_TAG_NONE }, /* Malas != Makasar */
+ {HB_TAG('m','k','u',' '), HB_TAG('M','N','K',' ')}, /* Konyanka Maninka -> Maninka */
+/*{HB_TAG('m','k','w',' '), HB_TAG('M','K','W',' ')},*/ /* Kituba (Congo) */
+ {HB_TAG('m','l','e',' '), HB_TAG_NONE }, /* Manambu != Male */
+ {HB_TAG('m','l','n',' '), HB_TAG_NONE }, /* Malango != Malinke */
+ {HB_TAG('m','l','q',' '), HB_TAG('M','L','N',' ')}, /* Western Maninkakan -> Malinke */
+ {HB_TAG('m','l','q',' '), HB_TAG('M','N','K',' ')}, /* Western Maninkakan -> Maninka */
+ {HB_TAG('m','l','r',' '), HB_TAG_NONE }, /* Vame != Malayalam Reformed */
+ {HB_TAG('m','m','r',' '), HB_TAG('H','M','N',' ')}, /* Western Xiangxi Miao -> Hmong */
+ {HB_TAG('m','n','c',' '), HB_TAG('M','C','H',' ')}, /* Manchu */
+ {HB_TAG('m','n','d',' '), HB_TAG_NONE }, /* Mondé != Mandinka */
+ {HB_TAG('m','n','g',' '), HB_TAG_NONE }, /* Eastern Mnong != Mongolian */
+ {HB_TAG('m','n','h',' '), HB_TAG('B','A','D','0')}, /* Mono (Democratic Republic of Congo) -> Banda */
+/*{HB_TAG('m','n','i',' '), HB_TAG('M','N','I',' ')},*/ /* Manipuri */
+ {HB_TAG('m','n','k',' '), HB_TAG('M','N','D',' ')}, /* Mandinka */
+ {HB_TAG('m','n','k',' '), HB_TAG('M','N','K',' ')}, /* Mandinka -> Maninka */
+ {HB_TAG('m','n','p',' '), HB_TAG('Z','H','S',' ')}, /* Min Bei Chinese -> Chinese, Simplified */
+ {HB_TAG('m','n','s',' '), HB_TAG('M','A','N',' ')}, /* Mansi */
+ {HB_TAG('m','n','w',' '), HB_TAG('M','O','N',' ')}, /* Mon */
+ {HB_TAG('m','n','w',' '), HB_TAG('M','O','N','T')}, /* Mon -> Thailand Mon */
+ {HB_TAG('m','n','x',' '), HB_TAG_NONE }, /* Manikion != Manx */
+ {HB_TAG('m','o','d',' '), HB_TAG('C','P','P',' ')}, /* Mobilian -> Creoles */
+/*{HB_TAG('m','o','h',' '), HB_TAG('M','O','H',' ')},*/ /* Mohawk */
+ {HB_TAG('m','o','k',' '), HB_TAG_NONE }, /* Morori != Moksha */
+ {HB_TAG('m','o','p',' '), HB_TAG('M','Y','N',' ')}, /* Mopán Maya -> Mayan */
+ {HB_TAG('m','o','r',' '), HB_TAG_NONE }, /* Moro != Moroccan */
+/*{HB_TAG('m','o','s',' '), HB_TAG('M','O','S',' ')},*/ /* Mossi */
+ {HB_TAG('m','p','e',' '), HB_TAG('M','A','J',' ')}, /* Majang */
+ {HB_TAG('m','q','g',' '), HB_TAG('M','L','Y',' ')}, /* Kota Bangun Kutai Malay -> Malay */
+ {HB_TAG('m','r','h',' '), HB_TAG('Q','I','N',' ')}, /* Mara Chin -> Chin */
+ {HB_TAG('m','r','j',' '), HB_TAG('H','M','A',' ')}, /* Western Mari -> High Mari */
+ {HB_TAG('m','s','c',' '), HB_TAG('M','N','K',' ')}, /* Sankaran Maninka -> Maninka */
+ {HB_TAG('m','s','h',' '), HB_TAG('M','L','G',' ')}, /* Masikoro Malagasy -> Malagasy */
+ {HB_TAG('m','s','i',' '), HB_TAG('M','L','Y',' ')}, /* Sabah Malay -> Malay */
+ {HB_TAG('m','s','i',' '), HB_TAG('C','P','P',' ')}, /* Sabah Malay -> Creoles */
+ {HB_TAG('m','t','h',' '), HB_TAG_NONE }, /* Munggui != Maithili */
+ {HB_TAG('m','t','r',' '), HB_TAG('M','A','W',' ')}, /* Mewari -> Marwari */
+ {HB_TAG('m','t','s',' '), HB_TAG_NONE }, /* Yora != Maltese */
+ {HB_TAG('m','u','d',' '), HB_TAG('C','P','P',' ')}, /* Mednyj Aleut -> Creoles */
+ {HB_TAG('m','u','i',' '), HB_TAG('M','L','Y',' ')}, /* Musi -> Malay */
+ {HB_TAG('m','u','n',' '), HB_TAG_NONE }, /* Munda [collection] != Mundari */
+ {HB_TAG('m','u','p',' '), HB_TAG('R','A','J',' ')}, /* Malvi -> Rajasthani */
+ {HB_TAG('m','u','q',' '), HB_TAG('H','M','N',' ')}, /* Eastern Xiangxi Miao -> Hmong */
+/*{HB_TAG('m','u','s',' '), HB_TAG('M','U','S',' ')},*/ /* Creek -> Muscogee */
+ {HB_TAG('m','v','b',' '), HB_TAG('A','T','H',' ')}, /* Mattole -> Athapaskan */
+ {HB_TAG('m','v','e',' '), HB_TAG('M','A','W',' ')}, /* Marwari (Pakistan) */
+ {HB_TAG('m','v','f',' '), HB_TAG('M','N','G',' ')}, /* Peripheral Mongolian -> Mongolian */
+ {HB_TAG('m','w','k',' '), HB_TAG('M','N','K',' ')}, /* Kita Maninkakan -> Maninka */
+/*{HB_TAG('m','w','l',' '), HB_TAG('M','W','L',' ')},*/ /* Mirandese */
+ {HB_TAG('m','w','q',' '), HB_TAG('Q','I','N',' ')}, /* Mün Chin -> Chin */
+ {HB_TAG('m','w','r',' '), HB_TAG('M','A','W',' ')}, /* Marwari [macrolanguage] */
+ {HB_TAG('m','w','w',' '), HB_TAG('M','W','W',' ')}, /* Hmong Daw */
+ {HB_TAG('m','w','w',' '), HB_TAG('H','M','N',' ')}, /* Hmong Daw -> Hmong */
+ {HB_TAG('m','y','m',' '), HB_TAG('M','E','N',' ')}, /* Me’en */
+/*{HB_TAG('m','y','n',' '), HB_TAG('M','Y','N',' ')},*/ /* Mayan [collection] */
+ {HB_TAG('m','y','q',' '), HB_TAG('M','N','K',' ')}, /* Forest Maninka (retired code) -> Maninka */
+ {HB_TAG('m','y','v',' '), HB_TAG('E','R','Z',' ')}, /* Erzya */
+ {HB_TAG('m','z','b',' '), HB_TAG('B','B','R',' ')}, /* Tumzabt -> Berber */
+/*{HB_TAG('m','z','n',' '), HB_TAG('M','Z','N',' ')},*/ /* Mazanderani */
+ {HB_TAG('m','z','s',' '), HB_TAG('C','P','P',' ')}, /* Macanese -> Creoles */
+ {HB_TAG('n','a','g',' '), HB_TAG('N','A','G',' ')}, /* Naga Pidgin -> Naga-Assamese */
+ {HB_TAG('n','a','g',' '), HB_TAG('C','P','P',' ')}, /* Naga Pidgin -> Creoles */
+/*{HB_TAG('n','a','h',' '), HB_TAG('N','A','H',' ')},*/ /* Nahuatl [collection] */
+ {HB_TAG('n','a','n',' '), HB_TAG('Z','H','S',' ')}, /* Min Nan Chinese -> Chinese, Simplified */
+/*{HB_TAG('n','a','p',' '), HB_TAG('N','A','P',' ')},*/ /* Neapolitan */
+ {HB_TAG('n','a','s',' '), HB_TAG_NONE }, /* Naasioi != Naskapi */
+ {HB_TAG('n','a','z',' '), HB_TAG('N','A','H',' ')}, /* Coatepec Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','h',' '), HB_TAG('N','A','H',' ')}, /* Central Huasteca Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','i',' '), HB_TAG('N','A','H',' ')}, /* Classical Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','j',' '), HB_TAG('N','A','H',' ')}, /* Northern Puebla Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','l',' '), HB_TAG('N','A','H',' ')}, /* Michoacán Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','r',' '), HB_TAG_NONE }, /* Ncane != N-Cree */
+ {HB_TAG('n','c','x',' '), HB_TAG('N','A','H',' ')}, /* Central Puebla Nahuatl -> Nahuatl */
+ {HB_TAG('n','d','b',' '), HB_TAG_NONE }, /* Kenswei Nsei != Ndebele */
+/*{HB_TAG('n','d','c',' '), HB_TAG('N','D','C',' ')},*/ /* Ndau */
+ {HB_TAG('n','d','g',' '), HB_TAG_NONE }, /* Ndengereko != Ndonga */
+/*{HB_TAG('n','d','s',' '), HB_TAG('N','D','S',' ')},*/ /* Low Saxon */
+ {HB_TAG('n','e','f',' '), HB_TAG('C','P','P',' ')}, /* Nefamese -> Creoles */
+/*{HB_TAG('n','e','w',' '), HB_TAG('N','E','W',' ')},*/ /* Newari */
+/*{HB_TAG('n','g','a',' '), HB_TAG('N','G','A',' ')},*/ /* Ngbaka */
+ {HB_TAG('n','g','l',' '), HB_TAG('L','M','W',' ')}, /* Lomwe */
+ {HB_TAG('n','g','m',' '), HB_TAG('C','P','P',' ')}, /* Ngatik Men's Creole -> Creoles */
+ {HB_TAG('n','g','o',' '), HB_TAG('S','X','T',' ')}, /* Ngoni (retired code) -> Sutu */
+ {HB_TAG('n','g','r',' '), HB_TAG_NONE }, /* Engdewu != Nagari */
+ {HB_TAG('n','g','u',' '), HB_TAG('N','A','H',' ')}, /* Guerrero Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','c',' '), HB_TAG('N','A','H',' ')}, /* Tabasco Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','d',' '), HB_TAG('G','U','A',' ')}, /* Chiripá -> Guarani */
+ {HB_TAG('n','h','e',' '), HB_TAG('N','A','H',' ')}, /* Eastern Huasteca Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','g',' '), HB_TAG('N','A','H',' ')}, /* Tetelcingo Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','i',' '), HB_TAG('N','A','H',' ')}, /* Zacatlán-Ahuacatlán-Tepetzintla Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','k',' '), HB_TAG('N','A','H',' ')}, /* Isthmus-Cosoleacaque Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','m',' '), HB_TAG('N','A','H',' ')}, /* Morelos Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','n',' '), HB_TAG('N','A','H',' ')}, /* Central Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','p',' '), HB_TAG('N','A','H',' ')}, /* Isthmus-Pajapan Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','q',' '), HB_TAG('N','A','H',' ')}, /* Huaxcaleca Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','t',' '), HB_TAG('N','A','H',' ')}, /* Ometepec Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','v',' '), HB_TAG('N','A','H',' ')}, /* Temascaltepec Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','w',' '), HB_TAG('N','A','H',' ')}, /* Western Huasteca Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','x',' '), HB_TAG('N','A','H',' ')}, /* Isthmus-Mecayapan Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','y',' '), HB_TAG('N','A','H',' ')}, /* Northern Oaxaca Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','z',' '), HB_TAG('N','A','H',' ')}, /* Santa María La Alta Nahuatl -> Nahuatl */
+ {HB_TAG('n','i','q',' '), HB_TAG('K','A','L',' ')}, /* Nandi -> Kalenjin */
+ {HB_TAG('n','i','s',' '), HB_TAG_NONE }, /* Nimi != Nisi */
+/*{HB_TAG('n','i','u',' '), HB_TAG('N','I','U',' ')},*/ /* Niuean */
+ {HB_TAG('n','i','v',' '), HB_TAG('G','I','L',' ')}, /* Gilyak */
+ {HB_TAG('n','j','t',' '), HB_TAG('C','P','P',' ')}, /* Ndyuka-Trio Pidgin -> Creoles */
+ {HB_TAG('n','j','z',' '), HB_TAG('N','I','S',' ')}, /* Nyishi -> Nisi */
+ {HB_TAG('n','k','o',' '), HB_TAG_NONE }, /* Nkonya != N’Ko */
+ {HB_TAG('n','k','x',' '), HB_TAG('I','J','O',' ')}, /* Nkoroo -> Ijo */
+ {HB_TAG('n','l','a',' '), HB_TAG('B','M','L',' ')}, /* Ngombale -> Bamileke */
+ {HB_TAG('n','l','e',' '), HB_TAG('L','U','H',' ')}, /* East Nyala -> Luyia */
+ {HB_TAG('n','l','n',' '), HB_TAG('N','A','H',' ')}, /* Durango Nahuatl (retired code) -> Nahuatl */
+ {HB_TAG('n','l','v',' '), HB_TAG('N','A','H',' ')}, /* Orizaba Nahuatl -> Nahuatl */
+ {HB_TAG('n','n','h',' '), HB_TAG('B','M','L',' ')}, /* Ngiemboon -> Bamileke */
+ {HB_TAG('n','n','z',' '), HB_TAG('B','M','L',' ')}, /* Nda'nda' -> Bamileke */
+ {HB_TAG('n','o','d',' '), HB_TAG('N','T','A',' ')}, /* Northern Thai -> Northern Tai */
+/*{HB_TAG('n','o','e',' '), HB_TAG('N','O','E',' ')},*/ /* Nimadi */
+/*{HB_TAG('n','o','g',' '), HB_TAG('N','O','G',' ')},*/ /* Nogai */
+/*{HB_TAG('n','o','v',' '), HB_TAG('N','O','V',' ')},*/ /* Novial */
+ {HB_TAG('n','p','i',' '), HB_TAG('N','E','P',' ')}, /* Nepali */
+ {HB_TAG('n','p','l',' '), HB_TAG('N','A','H',' ')}, /* Southeastern Puebla Nahuatl -> Nahuatl */
+ {HB_TAG('n','q','o',' '), HB_TAG('N','K','O',' ')}, /* N’Ko */
+ {HB_TAG('n','s','k',' '), HB_TAG('N','A','S',' ')}, /* Naskapi */
+ {HB_TAG('n','s','m',' '), HB_TAG_NONE }, /* Sumi Naga != Northern Sami */
+/*{HB_TAG('n','s','o',' '), HB_TAG('N','S','O',' ')},*/ /* Northern Sotho */
+ {HB_TAG('n','s','u',' '), HB_TAG('N','A','H',' ')}, /* Sierra Negra Nahuatl -> Nahuatl */
+ {HB_TAG('n','t','o',' '), HB_TAG_NONE }, /* Ntomba != Esperanto */
+ {HB_TAG('n','u','e',' '), HB_TAG('B','A','D','0')}, /* Ngundu -> Banda */
+ {HB_TAG('n','u','u',' '), HB_TAG('B','A','D','0')}, /* Ngbundu -> Banda */
+ {HB_TAG('n','u','z',' '), HB_TAG('N','A','H',' ')}, /* Tlamacazapa Nahuatl -> Nahuatl */
+ {HB_TAG('n','w','e',' '), HB_TAG('B','M','L',' ')}, /* Ngwe -> Bamileke */
+ {HB_TAG('n','y','d',' '), HB_TAG('L','U','H',' ')}, /* Nyore -> Luyia */
+/*{HB_TAG('n','y','m',' '), HB_TAG('N','Y','M',' ')},*/ /* Nyamwezi */
+ {HB_TAG('n','y','n',' '), HB_TAG('N','K','L',' ')}, /* Nyankole */
+/*{HB_TAG('n','z','a',' '), HB_TAG('N','Z','A',' ')},*/ /* Tigon Mbembe -> Mbembe Tigon */
+/*{HB_TAG('o','j','b',' '), HB_TAG('O','J','B',' ')},*/ /* Northwestern Ojibwa -> Ojibway */
+ {HB_TAG('o','j','c',' '), HB_TAG('O','J','B',' ')}, /* Central Ojibwa -> Ojibway */
+ {HB_TAG('o','j','g',' '), HB_TAG('O','J','B',' ')}, /* Eastern Ojibwa -> Ojibway */
+ {HB_TAG('o','j','s',' '), HB_TAG('O','C','R',' ')}, /* Severn Ojibwa -> Oji-Cree */
+ {HB_TAG('o','j','s',' '), HB_TAG('O','J','B',' ')}, /* Severn Ojibwa -> Ojibway */
+ {HB_TAG('o','j','w',' '), HB_TAG('O','J','B',' ')}, /* Western Ojibwa -> Ojibway */
+ {HB_TAG('o','k','d',' '), HB_TAG('I','J','O',' ')}, /* Okodia -> Ijo */
+ {HB_TAG('o','k','i',' '), HB_TAG('K','A','L',' ')}, /* Okiek -> Kalenjin */
+ {HB_TAG('o','k','m',' '), HB_TAG('K','O','H',' ')}, /* Middle Korean (10th-16th cent.) -> Korean Old Hangul */
+ {HB_TAG('o','k','r',' '), HB_TAG('I','J','O',' ')}, /* Kirike -> Ijo */
+ {HB_TAG('o','n','x',' '), HB_TAG('C','P','P',' ')}, /* Onin Based Pidgin -> Creoles */
+ {HB_TAG('o','o','r',' '), HB_TAG('C','P','P',' ')}, /* Oorlams -> Creoles */
+ {HB_TAG('o','r','c',' '), HB_TAG('O','R','O',' ')}, /* Orma -> Oromo */
+ {HB_TAG('o','r','n',' '), HB_TAG('M','L','Y',' ')}, /* Orang Kanaq -> Malay */
+ {HB_TAG('o','r','o',' '), HB_TAG_NONE }, /* Orokolo != Oromo */
+ {HB_TAG('o','r','r',' '), HB_TAG('I','J','O',' ')}, /* Oruma -> Ijo */
+ {HB_TAG('o','r','s',' '), HB_TAG('M','L','Y',' ')}, /* Orang Seletar -> Malay */
+ {HB_TAG('o','r','y',' '), HB_TAG('O','R','I',' ')}, /* Odia (formerly Oriya) */
+ {HB_TAG('o','t','w',' '), HB_TAG('O','J','B',' ')}, /* Ottawa -> Ojibway */
+ {HB_TAG('o','u','a',' '), HB_TAG('B','B','R',' ')}, /* Tagargrent -> Berber */
+ {HB_TAG('p','a','a',' '), HB_TAG_NONE }, /* Papuan [collection] != Palestinian Aramaic */
+/*{HB_TAG('p','a','g',' '), HB_TAG('P','A','G',' ')},*/ /* Pangasinan */
+ {HB_TAG('p','a','l',' '), HB_TAG_NONE }, /* Pahlavi != Pali */
+/*{HB_TAG('p','a','m',' '), HB_TAG('P','A','M',' ')},*/ /* Pampanga -> Pampangan */
+ {HB_TAG('p','a','p',' '), HB_TAG('P','A','P','0')}, /* Papiamento -> Papiamentu */
+ {HB_TAG('p','a','p',' '), HB_TAG('C','P','P',' ')}, /* Papiamento -> Creoles */
+ {HB_TAG('p','a','s',' '), HB_TAG_NONE }, /* Papasena != Pashto */
+/*{HB_TAG('p','a','u',' '), HB_TAG('P','A','U',' ')},*/ /* Palauan */
+ {HB_TAG('p','b','t',' '), HB_TAG('P','A','S',' ')}, /* Southern Pashto -> Pashto */
+ {HB_TAG('p','b','u',' '), HB_TAG('P','A','S',' ')}, /* Northern Pashto -> Pashto */
+/*{HB_TAG('p','c','c',' '), HB_TAG('P','C','C',' ')},*/ /* Bouyei */
+/*{HB_TAG('p','c','d',' '), HB_TAG('P','C','D',' ')},*/ /* Picard */
+ {HB_TAG('p','c','e',' '), HB_TAG('P','L','G',' ')}, /* Ruching Palaung -> Palaung */
+ {HB_TAG('p','c','k',' '), HB_TAG('Q','I','N',' ')}, /* Paite Chin -> Chin */
+ {HB_TAG('p','c','m',' '), HB_TAG('C','P','P',' ')}, /* Nigerian Pidgin -> Creoles */
+/*{HB_TAG('p','d','c',' '), HB_TAG('P','D','C',' ')},*/ /* Pennsylvania German */
+ {HB_TAG('p','d','u',' '), HB_TAG('K','R','N',' ')}, /* Kayan -> Karen */
+ {HB_TAG('p','e','a',' '), HB_TAG('C','P','P',' ')}, /* Peranakan Indonesian -> Creoles */
+ {HB_TAG('p','e','l',' '), HB_TAG('M','L','Y',' ')}, /* Pekal -> Malay */
+ {HB_TAG('p','e','s',' '), HB_TAG('F','A','R',' ')}, /* Iranian Persian -> Persian */
+ {HB_TAG('p','e','y',' '), HB_TAG('C','P','P',' ')}, /* Petjo -> Creoles */
+ {HB_TAG('p','g','a',' '), HB_TAG('A','R','A',' ')}, /* Sudanese Creole Arabic -> Arabic */
+ {HB_TAG('p','g','a',' '), HB_TAG('C','P','P',' ')}, /* Sudanese Creole Arabic -> Creoles */
+/*{HB_TAG('p','h','k',' '), HB_TAG('P','H','K',' ')},*/ /* Phake */
+ {HB_TAG('p','i','h',' '), HB_TAG('P','I','H',' ')}, /* Pitcairn-Norfolk -> Norfolk */
+ {HB_TAG('p','i','h',' '), HB_TAG('C','P','P',' ')}, /* Pitcairn-Norfolk -> Creoles */
+ {HB_TAG('p','i','l',' '), HB_TAG_NONE }, /* Yom != Filipino */
+ {HB_TAG('p','i','s',' '), HB_TAG('C','P','P',' ')}, /* Pijin -> Creoles */
+ {HB_TAG('p','k','h',' '), HB_TAG('Q','I','N',' ')}, /* Pankhu -> Chin */
+ {HB_TAG('p','k','o',' '), HB_TAG('K','A','L',' ')}, /* Pökoot -> Kalenjin */
+ {HB_TAG('p','l','g',' '), HB_TAG_NONE }, /* Pilagá != Palaung */
+ {HB_TAG('p','l','k',' '), HB_TAG_NONE }, /* Kohistani Shina != Polish */
+ {HB_TAG('p','l','l',' '), HB_TAG('P','L','G',' ')}, /* Shwe Palaung -> Palaung */
+ {HB_TAG('p','l','n',' '), HB_TAG('C','P','P',' ')}, /* Palenquero -> Creoles */
+ {HB_TAG('p','l','p',' '), HB_TAG('P','A','P',' ')}, /* Palpa (retired code) */
+ {HB_TAG('p','l','t',' '), HB_TAG('M','L','G',' ')}, /* Plateau Malagasy -> Malagasy */
+ {HB_TAG('p','m','l',' '), HB_TAG('C','P','P',' ')}, /* Lingua Franca -> Creoles */
+/*{HB_TAG('p','m','s',' '), HB_TAG('P','M','S',' ')},*/ /* Piemontese */
+ {HB_TAG('p','m','y',' '), HB_TAG('C','P','P',' ')}, /* Papuan Malay -> Creoles */
+/*{HB_TAG('p','n','b',' '), HB_TAG('P','N','B',' ')},*/ /* Western Panjabi */
+ {HB_TAG('p','o','c',' '), HB_TAG('M','Y','N',' ')}, /* Poqomam -> Mayan */
+ {HB_TAG('p','o','h',' '), HB_TAG('P','O','H',' ')}, /* Poqomchi' -> Pocomchi */
+ {HB_TAG('p','o','h',' '), HB_TAG('M','Y','N',' ')}, /* Poqomchi' -> Mayan */
+/*{HB_TAG('p','o','n',' '), HB_TAG('P','O','N',' ')},*/ /* Pohnpeian */
+ {HB_TAG('p','o','v',' '), HB_TAG('C','P','P',' ')}, /* Upper Guinea Crioulo -> Creoles */
+ {HB_TAG('p','p','a',' '), HB_TAG('B','A','G',' ')}, /* Pao (retired code) -> Baghelkhandi */
+ {HB_TAG('p','r','e',' '), HB_TAG('C','P','P',' ')}, /* Principense -> Creoles */
+/*{HB_TAG('p','r','o',' '), HB_TAG('P','R','O',' ')},*/ /* Old Provençal (to 1500) -> Provençal / Old Provençal */
+ {HB_TAG('p','r','s',' '), HB_TAG('D','R','I',' ')}, /* Dari */
+ {HB_TAG('p','r','s',' '), HB_TAG('F','A','R',' ')}, /* Dari -> Persian */
+ {HB_TAG('p','s','e',' '), HB_TAG('M','L','Y',' ')}, /* Central Malay -> Malay */
+ {HB_TAG('p','s','t',' '), HB_TAG('P','A','S',' ')}, /* Central Pashto -> Pashto */
+ {HB_TAG('p','u','b',' '), HB_TAG('Q','I','N',' ')}, /* Purum -> Chin */
+ {HB_TAG('p','u','z',' '), HB_TAG('Q','I','N',' ')}, /* Purum Naga (retired code) -> Chin */
+ {HB_TAG('p','w','o',' '), HB_TAG('P','W','O',' ')}, /* Pwo Western Karen -> Western Pwo Karen */
+ {HB_TAG('p','w','o',' '), HB_TAG('K','R','N',' ')}, /* Pwo Western Karen -> Karen */
+ {HB_TAG('p','w','w',' '), HB_TAG('K','R','N',' ')}, /* Pwo Northern Karen -> Karen */
+ {HB_TAG('q','u','b',' '), HB_TAG('Q','W','H',' ')}, /* Huallaga Huánuco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','u','b',' '), HB_TAG('Q','U','Z',' ')}, /* Huallaga Huánuco Quechua -> Quechua */
+ {HB_TAG('q','u','c',' '), HB_TAG('Q','U','C',' ')}, /* K’iche’ */
+ {HB_TAG('q','u','c',' '), HB_TAG('M','Y','N',' ')}, /* K'iche' -> Mayan */
+ {HB_TAG('q','u','d',' '), HB_TAG('Q','V','I',' ')}, /* Calderón Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','u','d',' '), HB_TAG('Q','U','Z',' ')}, /* Calderón Highland Quichua -> Quechua */
+ {HB_TAG('q','u','f',' '), HB_TAG('Q','U','Z',' ')}, /* Lambayeque Quechua -> Quechua */
+ {HB_TAG('q','u','g',' '), HB_TAG('Q','V','I',' ')}, /* Chimborazo Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','u','g',' '), HB_TAG('Q','U','Z',' ')}, /* Chimborazo Highland Quichua -> Quechua */
+ {HB_TAG('q','u','h',' '), HB_TAG('Q','U','H',' ')}, /* South Bolivian Quechua -> Quechua (Bolivia) */
+ {HB_TAG('q','u','h',' '), HB_TAG('Q','U','Z',' ')}, /* South Bolivian Quechua -> Quechua */
+ {HB_TAG('q','u','k',' '), HB_TAG('Q','U','Z',' ')}, /* Chachapoyas Quechua -> Quechua */
+ {HB_TAG('q','u','l',' '), HB_TAG('Q','U','H',' ')}, /* North Bolivian Quechua -> Quechua (Bolivia) */
+ {HB_TAG('q','u','l',' '), HB_TAG('Q','U','Z',' ')}, /* North Bolivian Quechua -> Quechua */
+ {HB_TAG('q','u','m',' '), HB_TAG('M','Y','N',' ')}, /* Sipacapense -> Mayan */
+ {HB_TAG('q','u','p',' '), HB_TAG('Q','V','I',' ')}, /* Southern Pastaza Quechua -> Quechua (Ecuador) */
+ {HB_TAG('q','u','p',' '), HB_TAG('Q','U','Z',' ')}, /* Southern Pastaza Quechua -> Quechua */
+ {HB_TAG('q','u','r',' '), HB_TAG('Q','W','H',' ')}, /* Yanahuanca Pasco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','u','r',' '), HB_TAG('Q','U','Z',' ')}, /* Yanahuanca Pasco Quechua -> Quechua */
+ {HB_TAG('q','u','s',' '), HB_TAG('Q','U','H',' ')}, /* Santiago del Estero Quichua -> Quechua (Bolivia) */
+ {HB_TAG('q','u','s',' '), HB_TAG('Q','U','Z',' ')}, /* Santiago del Estero Quichua -> Quechua */
+ {HB_TAG('q','u','v',' '), HB_TAG('M','Y','N',' ')}, /* Sacapulteco -> Mayan */
+ {HB_TAG('q','u','w',' '), HB_TAG('Q','V','I',' ')}, /* Tena Lowland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','u','w',' '), HB_TAG('Q','U','Z',' ')}, /* Tena Lowland Quichua -> Quechua */
+ {HB_TAG('q','u','x',' '), HB_TAG('Q','W','H',' ')}, /* Yauyos Quechua -> Quechua (Peru) */
+ {HB_TAG('q','u','x',' '), HB_TAG('Q','U','Z',' ')}, /* Yauyos Quechua -> Quechua */
+ {HB_TAG('q','u','y',' '), HB_TAG('Q','U','Z',' ')}, /* Ayacucho Quechua -> Quechua */
+/*{HB_TAG('q','u','z',' '), HB_TAG('Q','U','Z',' ')},*/ /* Cusco Quechua -> Quechua */
+ {HB_TAG('q','v','a',' '), HB_TAG('Q','W','H',' ')}, /* Ambo-Pasco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','a',' '), HB_TAG('Q','U','Z',' ')}, /* Ambo-Pasco Quechua -> Quechua */
+ {HB_TAG('q','v','c',' '), HB_TAG('Q','U','Z',' ')}, /* Cajamarca Quechua -> Quechua */
+ {HB_TAG('q','v','e',' '), HB_TAG('Q','U','Z',' ')}, /* Eastern Apurímac Quechua -> Quechua */
+ {HB_TAG('q','v','h',' '), HB_TAG('Q','W','H',' ')}, /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','h',' '), HB_TAG('Q','U','Z',' ')}, /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua */
+ {HB_TAG('q','v','i',' '), HB_TAG('Q','V','I',' ')}, /* Imbabura Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','v','i',' '), HB_TAG('Q','U','Z',' ')}, /* Imbabura Highland Quichua -> Quechua */
+ {HB_TAG('q','v','j',' '), HB_TAG('Q','V','I',' ')}, /* Loja Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','v','j',' '), HB_TAG('Q','U','Z',' ')}, /* Loja Highland Quichua -> Quechua */
+ {HB_TAG('q','v','l',' '), HB_TAG('Q','W','H',' ')}, /* Cajatambo North Lima Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','l',' '), HB_TAG('Q','U','Z',' ')}, /* Cajatambo North Lima Quechua -> Quechua */
+ {HB_TAG('q','v','m',' '), HB_TAG('Q','W','H',' ')}, /* Margos-Yarowilca-Lauricocha Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','m',' '), HB_TAG('Q','U','Z',' ')}, /* Margos-Yarowilca-Lauricocha Quechua -> Quechua */
+ {HB_TAG('q','v','n',' '), HB_TAG('Q','W','H',' ')}, /* North Junín Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','n',' '), HB_TAG('Q','U','Z',' ')}, /* North Junín Quechua -> Quechua */
+ {HB_TAG('q','v','o',' '), HB_TAG('Q','V','I',' ')}, /* Napo Lowland Quechua -> Quechua (Ecuador) */
+ {HB_TAG('q','v','o',' '), HB_TAG('Q','U','Z',' ')}, /* Napo Lowland Quechua -> Quechua */
+ {HB_TAG('q','v','p',' '), HB_TAG('Q','W','H',' ')}, /* Pacaraos Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','p',' '), HB_TAG('Q','U','Z',' ')}, /* Pacaraos Quechua -> Quechua */
+ {HB_TAG('q','v','s',' '), HB_TAG('Q','U','Z',' ')}, /* San Martín Quechua -> Quechua */
+ {HB_TAG('q','v','w',' '), HB_TAG('Q','W','H',' ')}, /* Huaylla Wanca Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','w',' '), HB_TAG('Q','U','Z',' ')}, /* Huaylla Wanca Quechua -> Quechua */
+ {HB_TAG('q','v','z',' '), HB_TAG('Q','V','I',' ')}, /* Northern Pastaza Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','v','z',' '), HB_TAG('Q','U','Z',' ')}, /* Northern Pastaza Quichua -> Quechua */
+ {HB_TAG('q','w','a',' '), HB_TAG('Q','W','H',' ')}, /* Corongo Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','w','a',' '), HB_TAG('Q','U','Z',' ')}, /* Corongo Ancash Quechua -> Quechua */
+ {HB_TAG('q','w','c',' '), HB_TAG('Q','U','Z',' ')}, /* Classical Quechua -> Quechua */
+ {HB_TAG('q','w','h',' '), HB_TAG('Q','W','H',' ')}, /* Huaylas Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','w','h',' '), HB_TAG('Q','U','Z',' ')}, /* Huaylas Ancash Quechua -> Quechua */
+ {HB_TAG('q','w','s',' '), HB_TAG('Q','W','H',' ')}, /* Sihuas Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','w','s',' '), HB_TAG('Q','U','Z',' ')}, /* Sihuas Ancash Quechua -> Quechua */
+ {HB_TAG('q','w','t',' '), HB_TAG('A','T','H',' ')}, /* Kwalhioqua-Tlatskanai -> Athapaskan */
+ {HB_TAG('q','x','a',' '), HB_TAG('Q','W','H',' ')}, /* Chiquián Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','a',' '), HB_TAG('Q','U','Z',' ')}, /* Chiquián Ancash Quechua -> Quechua */
+ {HB_TAG('q','x','c',' '), HB_TAG('Q','W','H',' ')}, /* Chincha Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','c',' '), HB_TAG('Q','U','Z',' ')}, /* Chincha Quechua -> Quechua */
+ {HB_TAG('q','x','h',' '), HB_TAG('Q','W','H',' ')}, /* Panao Huánuco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','h',' '), HB_TAG('Q','U','Z',' ')}, /* Panao Huánuco Quechua -> Quechua */
+ {HB_TAG('q','x','l',' '), HB_TAG('Q','V','I',' ')}, /* Salasaca Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','x','l',' '), HB_TAG('Q','U','Z',' ')}, /* Salasaca Highland Quichua -> Quechua */
+ {HB_TAG('q','x','n',' '), HB_TAG('Q','W','H',' ')}, /* Northern Conchucos Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','n',' '), HB_TAG('Q','U','Z',' ')}, /* Northern Conchucos Ancash Quechua -> Quechua */
+ {HB_TAG('q','x','o',' '), HB_TAG('Q','W','H',' ')}, /* Southern Conchucos Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','o',' '), HB_TAG('Q','U','Z',' ')}, /* Southern Conchucos Ancash Quechua -> Quechua */
+ {HB_TAG('q','x','p',' '), HB_TAG('Q','U','Z',' ')}, /* Puno Quechua -> Quechua */
+ {HB_TAG('q','x','r',' '), HB_TAG('Q','V','I',' ')}, /* Cañar Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','x','r',' '), HB_TAG('Q','U','Z',' ')}, /* Cañar Highland Quichua -> Quechua */
+ {HB_TAG('q','x','t',' '), HB_TAG('Q','W','H',' ')}, /* Santa Ana de Tusi Pasco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','t',' '), HB_TAG('Q','U','Z',' ')}, /* Santa Ana de Tusi Pasco Quechua -> Quechua */
+ {HB_TAG('q','x','u',' '), HB_TAG('Q','U','Z',' ')}, /* Arequipa-La Unión Quechua -> Quechua */
+ {HB_TAG('q','x','w',' '), HB_TAG('Q','W','H',' ')}, /* Jauja Wanca Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','w',' '), HB_TAG('Q','U','Z',' ')}, /* Jauja Wanca Quechua -> Quechua */
+ {HB_TAG('r','a','g',' '), HB_TAG('L','U','H',' ')}, /* Logooli -> Luyia */
+/*{HB_TAG('r','a','j',' '), HB_TAG('R','A','J',' ')},*/ /* Rajasthani [macrolanguage] */
+ {HB_TAG('r','a','l',' '), HB_TAG('Q','I','N',' ')}, /* Ralte -> Chin */
+/*{HB_TAG('r','a','r',' '), HB_TAG('R','A','R',' ')},*/ /* Rarotongan */
+ {HB_TAG('r','b','b',' '), HB_TAG('P','L','G',' ')}, /* Rumai Palaung -> Palaung */
+ {HB_TAG('r','b','l',' '), HB_TAG('B','I','K',' ')}, /* Miraya Bikol -> Bikol */
+ {HB_TAG('r','c','f',' '), HB_TAG('C','P','P',' ')}, /* Réunion Creole French -> Creoles */
+/*{HB_TAG('r','e','j',' '), HB_TAG('R','E','J',' ')},*/ /* Rejang */
+/*{HB_TAG('r','h','g',' '), HB_TAG('R','H','G',' ')},*/ /* Rohingya */
+/*{HB_TAG('r','i','a',' '), HB_TAG('R','I','A',' ')},*/ /* Riang (India) */
+ {HB_TAG('r','i','f',' '), HB_TAG('R','I','F',' ')}, /* Tarifit */
+ {HB_TAG('r','i','f',' '), HB_TAG('B','B','R',' ')}, /* Tarifit -> Berber */
+/*{HB_TAG('r','i','t',' '), HB_TAG('R','I','T',' ')},*/ /* Ritharrngu -> Ritarungo */
+ {HB_TAG('r','k','i',' '), HB_TAG('A','R','K',' ')}, /* Rakhine */
+/*{HB_TAG('r','k','w',' '), HB_TAG('R','K','W',' ')},*/ /* Arakwal */
+ {HB_TAG('r','m','c',' '), HB_TAG('R','O','Y',' ')}, /* Carpathian Romani -> Romany */
+ {HB_TAG('r','m','f',' '), HB_TAG('R','O','Y',' ')}, /* Kalo Finnish Romani -> Romany */
+ {HB_TAG('r','m','l',' '), HB_TAG('R','O','Y',' ')}, /* Baltic Romani -> Romany */
+ {HB_TAG('r','m','n',' '), HB_TAG('R','O','Y',' ')}, /* Balkan Romani -> Romany */
+ {HB_TAG('r','m','o',' '), HB_TAG('R','O','Y',' ')}, /* Sinte Romani -> Romany */
+ {HB_TAG('r','m','s',' '), HB_TAG_NONE }, /* Romanian Sign Language != Romansh */
+ {HB_TAG('r','m','w',' '), HB_TAG('R','O','Y',' ')}, /* Welsh Romani -> Romany */
+ {HB_TAG('r','m','y',' '), HB_TAG('R','M','Y',' ')}, /* Vlax Romani */
+ {HB_TAG('r','m','y',' '), HB_TAG('R','O','Y',' ')}, /* Vlax Romani -> Romany */
+ {HB_TAG('r','m','z',' '), HB_TAG('A','R','K',' ')}, /* Marma -> Rakhine */
+ {HB_TAG('r','o','m',' '), HB_TAG('R','O','Y',' ')}, /* Romany [macrolanguage] */
+ {HB_TAG('r','o','p',' '), HB_TAG('C','P','P',' ')}, /* Kriol -> Creoles */
+ {HB_TAG('r','t','c',' '), HB_TAG('Q','I','N',' ')}, /* Rungtu Chin -> Chin */
+/*{HB_TAG('r','t','m',' '), HB_TAG('R','T','M',' ')},*/ /* Rotuman */
+ {HB_TAG('r','u','e',' '), HB_TAG('R','S','Y',' ')}, /* Rusyn */
+/*{HB_TAG('r','u','p',' '), HB_TAG('R','U','P',' ')},*/ /* Aromanian */
+ {HB_TAG('r','w','r',' '), HB_TAG('M','A','W',' ')}, /* Marwari (India) */
+ {HB_TAG('s','a','d',' '), HB_TAG_NONE }, /* Sandawe != Sadri */
+ {HB_TAG('s','a','h',' '), HB_TAG('Y','A','K',' ')}, /* Yakut -> Sakha */
+ {HB_TAG('s','a','m',' '), HB_TAG('P','A','A',' ')}, /* Samaritan Aramaic -> Palestinian Aramaic */
+/*{HB_TAG('s','a','s',' '), HB_TAG('S','A','S',' ')},*/ /* Sasak */
+/*{HB_TAG('s','a','t',' '), HB_TAG('S','A','T',' ')},*/ /* Santali */
+ {HB_TAG('s','a','y',' '), HB_TAG_NONE }, /* Saya != Sayisi */
+ {HB_TAG('s','c','f',' '), HB_TAG('C','P','P',' ')}, /* San Miguel Creole French -> Creoles */
+ {HB_TAG('s','c','h',' '), HB_TAG('Q','I','N',' ')}, /* Sakachep -> Chin */
+ {HB_TAG('s','c','i',' '), HB_TAG('C','P','P',' ')}, /* Sri Lankan Creole Malay -> Creoles */
+ {HB_TAG('s','c','k',' '), HB_TAG('S','A','D',' ')}, /* Sadri */
+/*{HB_TAG('s','c','n',' '), HB_TAG('S','C','N',' ')},*/ /* Sicilian */
+/*{HB_TAG('s','c','o',' '), HB_TAG('S','C','O',' ')},*/ /* Scots */
+ {HB_TAG('s','c','s',' '), HB_TAG('S','C','S',' ')}, /* North Slavey */
+ {HB_TAG('s','c','s',' '), HB_TAG('S','L','A',' ')}, /* North Slavey -> Slavey */
+ {HB_TAG('s','c','s',' '), HB_TAG('A','T','H',' ')}, /* North Slavey -> Athapaskan */
+ {HB_TAG('s','d','c',' '), HB_TAG('S','R','D',' ')}, /* Sassarese Sardinian -> Sardinian */
+ {HB_TAG('s','d','h',' '), HB_TAG('K','U','R',' ')}, /* Southern Kurdish -> Kurdish */
+ {HB_TAG('s','d','n',' '), HB_TAG('S','R','D',' ')}, /* Gallurese Sardinian -> Sardinian */
+ {HB_TAG('s','d','s',' '), HB_TAG('B','B','R',' ')}, /* Sened -> Berber */
+ {HB_TAG('s','e','h',' '), HB_TAG('S','N','A',' ')}, /* Sena */
+ {HB_TAG('s','e','k',' '), HB_TAG('A','T','H',' ')}, /* Sekani -> Athapaskan */
+/*{HB_TAG('s','e','l',' '), HB_TAG('S','E','L',' ')},*/ /* Selkup */
+ {HB_TAG('s','e','z',' '), HB_TAG('Q','I','N',' ')}, /* Senthang Chin -> Chin */
+ {HB_TAG('s','f','m',' '), HB_TAG('S','F','M',' ')}, /* Small Flowery Miao */
+ {HB_TAG('s','f','m',' '), HB_TAG('H','M','N',' ')}, /* Small Flowery Miao -> Hmong */
+/*{HB_TAG('s','g','a',' '), HB_TAG('S','G','A',' ')},*/ /* Old Irish (to 900) */
+ {HB_TAG('s','g','c',' '), HB_TAG('K','A','L',' ')}, /* Kipsigis -> Kalenjin */
+ {HB_TAG('s','g','o',' '), HB_TAG_NONE }, /* Songa (retired code) != Sango */
+/*{HB_TAG('s','g','s',' '), HB_TAG('S','G','S',' ')},*/ /* Samogitian */
+ {HB_TAG('s','g','w',' '), HB_TAG('C','H','G',' ')}, /* Sebat Bet Gurage -> Chaha Gurage */
+ {HB_TAG('s','h','i',' '), HB_TAG('S','H','I',' ')}, /* Tachelhit */
+ {HB_TAG('s','h','i',' '), HB_TAG('B','B','R',' ')}, /* Tachelhit -> Berber */
+ {HB_TAG('s','h','l',' '), HB_TAG('Q','I','N',' ')}, /* Shendu -> Chin */
+/*{HB_TAG('s','h','n',' '), HB_TAG('S','H','N',' ')},*/ /* Shan */
+ {HB_TAG('s','h','u',' '), HB_TAG('A','R','A',' ')}, /* Chadian Arabic -> Arabic */
+ {HB_TAG('s','h','y',' '), HB_TAG('B','B','R',' ')}, /* Tachawit -> Berber */
+ {HB_TAG('s','i','b',' '), HB_TAG_NONE }, /* Sebop != Sibe */
+/*{HB_TAG('s','i','d',' '), HB_TAG('S','I','D',' ')},*/ /* Sidamo */
+ {HB_TAG('s','i','g',' '), HB_TAG_NONE }, /* Paasaal != Silte Gurage */
+ {HB_TAG('s','i','z',' '), HB_TAG('B','B','R',' ')}, /* Siwi -> Berber */
+ {HB_TAG('s','j','d',' '), HB_TAG('K','S','M',' ')}, /* Kildin Sami */
+ {HB_TAG('s','j','o',' '), HB_TAG('S','I','B',' ')}, /* Xibe -> Sibe */
+ {HB_TAG('s','j','s',' '), HB_TAG('B','B','R',' ')}, /* Senhaja De Srair -> Berber */
+ {HB_TAG('s','k','g',' '), HB_TAG('M','L','G',' ')}, /* Sakalava Malagasy -> Malagasy */
+ {HB_TAG('s','k','r',' '), HB_TAG('S','R','K',' ')}, /* Saraiki */
+ {HB_TAG('s','k','s',' '), HB_TAG_NONE }, /* Maia != Skolt Sami */
+ {HB_TAG('s','k','w',' '), HB_TAG('C','P','P',' ')}, /* Skepi Creole Dutch -> Creoles */
+ {HB_TAG('s','k','y',' '), HB_TAG_NONE }, /* Sikaiana != Slovak */
+ {HB_TAG('s','l','a',' '), HB_TAG_NONE }, /* Slavic [collection] != Slavey */
+ {HB_TAG('s','m','a',' '), HB_TAG('S','S','M',' ')}, /* Southern Sami */
+ {HB_TAG('s','m','d',' '), HB_TAG('M','B','N',' ')}, /* Sama (retired code) -> Mbundu */
+ {HB_TAG('s','m','j',' '), HB_TAG('L','S','M',' ')}, /* Lule Sami */
+ {HB_TAG('s','m','l',' '), HB_TAG_NONE }, /* Central Sama != Somali */
+ {HB_TAG('s','m','n',' '), HB_TAG('I','S','M',' ')}, /* Inari Sami */
+ {HB_TAG('s','m','s',' '), HB_TAG('S','K','S',' ')}, /* Skolt Sami */
+ {HB_TAG('s','m','t',' '), HB_TAG('Q','I','N',' ')}, /* Simte -> Chin */
+ {HB_TAG('s','n','b',' '), HB_TAG('I','B','A',' ')}, /* Sebuyau (retired code) -> Iban */
+ {HB_TAG('s','n','h',' '), HB_TAG_NONE }, /* Shinabo (retired code) != Sinhala (Sinhalese) */
+/*{HB_TAG('s','n','k',' '), HB_TAG('S','N','K',' ')},*/ /* Soninke */
+ {HB_TAG('s','o','g',' '), HB_TAG_NONE }, /* Sogdian != Sodo Gurage */
+/*{HB_TAG('s','o','p',' '), HB_TAG('S','O','P',' ')},*/ /* Songe */
+ {HB_TAG('s','p','v',' '), HB_TAG('O','R','I',' ')}, /* Sambalpuri -> Odia (formerly Oriya) */
+ {HB_TAG('s','p','y',' '), HB_TAG('K','A','L',' ')}, /* Sabaot -> Kalenjin */
+ {HB_TAG('s','r','b',' '), HB_TAG_NONE }, /* Sora != Serbian */
+ {HB_TAG('s','r','c',' '), HB_TAG('S','R','D',' ')}, /* Logudorese Sardinian -> Sardinian */
+ {HB_TAG('s','r','k',' '), HB_TAG_NONE }, /* Serudung Murut != Saraiki */
+ {HB_TAG('s','r','m',' '), HB_TAG('C','P','P',' ')}, /* Saramaccan -> Creoles */
+ {HB_TAG('s','r','n',' '), HB_TAG('C','P','P',' ')}, /* Sranan Tongo -> Creoles */
+ {HB_TAG('s','r','o',' '), HB_TAG('S','R','D',' ')}, /* Campidanese Sardinian -> Sardinian */
+/*{HB_TAG('s','r','r',' '), HB_TAG('S','R','R',' ')},*/ /* Serer */
+ {HB_TAG('s','r','s',' '), HB_TAG('A','T','H',' ')}, /* Sarsi -> Athapaskan */
+ {HB_TAG('s','s','h',' '), HB_TAG('A','R','A',' ')}, /* Shihhi Arabic -> Arabic */
+ {HB_TAG('s','s','l',' '), HB_TAG_NONE }, /* Western Sisaala != South Slavey */
+ {HB_TAG('s','s','m',' '), HB_TAG_NONE }, /* Semnam != Southern Sami */
+ {HB_TAG('s','t','a',' '), HB_TAG('C','P','P',' ')}, /* Settla -> Creoles */
+/*{HB_TAG('s','t','q',' '), HB_TAG('S','T','Q',' ')},*/ /* Saterfriesisch -> Saterland Frisian */
+ {HB_TAG('s','t','v',' '), HB_TAG('S','I','G',' ')}, /* Silt'e -> Silte Gurage */
+/*{HB_TAG('s','u','k',' '), HB_TAG('S','U','K',' ')},*/ /* Sukuma */
+ {HB_TAG('s','u','q',' '), HB_TAG('S','U','R',' ')}, /* Suri */
+ {HB_TAG('s','u','r',' '), HB_TAG_NONE }, /* Mwaghavul != Suri */
+/*{HB_TAG('s','v','a',' '), HB_TAG('S','V','A',' ')},*/ /* Svan */
+ {HB_TAG('s','v','c',' '), HB_TAG('C','P','P',' ')}, /* Vincentian Creole English -> Creoles */
+ {HB_TAG('s','v','e',' '), HB_TAG_NONE }, /* Serili != Swedish */
+ {HB_TAG('s','w','b',' '), HB_TAG('C','M','R',' ')}, /* Maore Comorian -> Comorian */
+ {HB_TAG('s','w','c',' '), HB_TAG('S','W','K',' ')}, /* Congo Swahili -> Swahili */
+ {HB_TAG('s','w','h',' '), HB_TAG('S','W','K',' ')}, /* Swahili */
+ {HB_TAG('s','w','k',' '), HB_TAG_NONE }, /* Malawi Sena != Swahili */
+ {HB_TAG('s','w','n',' '), HB_TAG('B','B','R',' ')}, /* Sawknah -> Berber */
+ {HB_TAG('s','w','v',' '), HB_TAG('M','A','W',' ')}, /* Shekhawati -> Marwari */
+/*{HB_TAG('s','x','u',' '), HB_TAG('S','X','U',' ')},*/ /* Upper Saxon */
+ {HB_TAG('s','y','c',' '), HB_TAG('S','Y','R',' ')}, /* Classical Syriac -> Syriac */
+/*{HB_TAG('s','y','l',' '), HB_TAG('S','Y','L',' ')},*/ /* Sylheti */
+/*{HB_TAG('s','y','r',' '), HB_TAG('S','Y','R',' ')},*/ /* Syriac [macrolanguage] */
+/*{HB_TAG('s','z','l',' '), HB_TAG('S','Z','L',' ')},*/ /* Silesian */
+ {HB_TAG('t','a','a',' '), HB_TAG('A','T','H',' ')}, /* Lower Tanana -> Athapaskan */
+/*{HB_TAG('t','a','b',' '), HB_TAG('T','A','B',' ')},*/ /* Tabassaran -> Tabasaran */
+ {HB_TAG('t','a','j',' '), HB_TAG_NONE }, /* Eastern Tamang != Tajiki */
+ {HB_TAG('t','a','q',' '), HB_TAG('T','M','H',' ')}, /* Tamasheq -> Tamashek */
+ {HB_TAG('t','a','q',' '), HB_TAG('B','B','R',' ')}, /* Tamasheq -> Berber */
+ {HB_TAG('t','a','s',' '), HB_TAG('C','P','P',' ')}, /* Tay Boi -> Creoles */
+ {HB_TAG('t','a','u',' '), HB_TAG('A','T','H',' ')}, /* Upper Tanana -> Athapaskan */
+ {HB_TAG('t','c','b',' '), HB_TAG('A','T','H',' ')}, /* Tanacross -> Athapaskan */
+ {HB_TAG('t','c','e',' '), HB_TAG('A','T','H',' ')}, /* Southern Tutchone -> Athapaskan */
+ {HB_TAG('t','c','h',' '), HB_TAG('C','P','P',' ')}, /* Turks And Caicos Creole English -> Creoles */
+ {HB_TAG('t','c','p',' '), HB_TAG('Q','I','N',' ')}, /* Tawr Chin -> Chin */
+ {HB_TAG('t','c','s',' '), HB_TAG('C','P','P',' ')}, /* Torres Strait Creole -> Creoles */
+ {HB_TAG('t','c','y',' '), HB_TAG('T','U','L',' ')}, /* Tulu -> Tumbuka */
+ {HB_TAG('t','c','z',' '), HB_TAG('Q','I','N',' ')}, /* Thado Chin -> Chin */
+/*{HB_TAG('t','d','d',' '), HB_TAG('T','D','D',' ')},*/ /* Tai Nüa -> Dehong Dai */
+ {HB_TAG('t','d','x',' '), HB_TAG('M','L','G',' ')}, /* Tandroy-Mahafaly Malagasy -> Malagasy */
+ {HB_TAG('t','e','c',' '), HB_TAG('K','A','L',' ')}, /* Terik -> Kalenjin */
+ {HB_TAG('t','e','m',' '), HB_TAG('T','M','N',' ')}, /* Timne -> Temne */
+/*{HB_TAG('t','e','t',' '), HB_TAG('T','E','T',' ')},*/ /* Tetum */
+ {HB_TAG('t','e','z',' '), HB_TAG('B','B','R',' ')}, /* Tetserret -> Berber */
+ {HB_TAG('t','f','n',' '), HB_TAG('A','T','H',' ')}, /* Tanaina -> Athapaskan */
+ {HB_TAG('t','g','h',' '), HB_TAG('C','P','P',' ')}, /* Tobagonian Creole English -> Creoles */
+ {HB_TAG('t','g','j',' '), HB_TAG('N','I','S',' ')}, /* Tagin -> Nisi */
+ {HB_TAG('t','g','n',' '), HB_TAG_NONE }, /* Tandaganon != Tongan */
+ {HB_TAG('t','g','r',' '), HB_TAG_NONE }, /* Tareng != Tigre */
+ {HB_TAG('t','g','x',' '), HB_TAG('A','T','H',' ')}, /* Tagish -> Athapaskan */
+ {HB_TAG('t','g','y',' '), HB_TAG_NONE }, /* Togoyo != Tigrinya */
+ {HB_TAG('t','h','t',' '), HB_TAG('A','T','H',' ')}, /* Tahltan -> Athapaskan */
+ {HB_TAG('t','h','v',' '), HB_TAG('T','M','H',' ')}, /* Tahaggart Tamahaq -> Tamashek */
+ {HB_TAG('t','h','v',' '), HB_TAG('B','B','R',' ')}, /* Tahaggart Tamahaq -> Berber */
+ {HB_TAG('t','h','z',' '), HB_TAG('T','M','H',' ')}, /* Tayart Tamajeq -> Tamashek */
+ {HB_TAG('t','h','z',' '), HB_TAG('B','B','R',' ')}, /* Tayart Tamajeq -> Berber */
+ {HB_TAG('t','i','a',' '), HB_TAG('B','B','R',' ')}, /* Tidikelt Tamazight -> Berber */
+ {HB_TAG('t','i','g',' '), HB_TAG('T','G','R',' ')}, /* Tigre */
+/*{HB_TAG('t','i','v',' '), HB_TAG('T','I','V',' ')},*/ /* Tiv */
+/*{HB_TAG('t','j','l',' '), HB_TAG('T','J','L',' ')},*/ /* Tai Laing */
+ {HB_TAG('t','j','o',' '), HB_TAG('B','B','R',' ')}, /* Temacine Tamazight -> Berber */
+ {HB_TAG('t','k','g',' '), HB_TAG('M','L','G',' ')}, /* Tesaka Malagasy -> Malagasy */
+ {HB_TAG('t','k','m',' '), HB_TAG_NONE }, /* Takelma != Turkmen */
+/*{HB_TAG('t','l','i',' '), HB_TAG('T','L','I',' ')},*/ /* Tlingit */
+ {HB_TAG('t','m','g',' '), HB_TAG('C','P','P',' ')}, /* Ternateño -> Creoles */
+ {HB_TAG('t','m','h',' '), HB_TAG('T','M','H',' ')}, /* Tamashek [macrolanguage] */
+ {HB_TAG('t','m','h',' '), HB_TAG('B','B','R',' ')}, /* Tamashek [macrolanguage] -> Berber */
+ {HB_TAG('t','m','n',' '), HB_TAG_NONE }, /* Taman (Indonesia) != Temne */
+ {HB_TAG('t','m','w',' '), HB_TAG('M','L','Y',' ')}, /* Temuan -> Malay */
+ {HB_TAG('t','n','a',' '), HB_TAG_NONE }, /* Tacana != Tswana */
+ {HB_TAG('t','n','e',' '), HB_TAG_NONE }, /* Tinoc Kallahan (retired code) != Tundra Enets */
+ {HB_TAG('t','n','f',' '), HB_TAG('D','R','I',' ')}, /* Tangshewi (retired code) -> Dari */
+ {HB_TAG('t','n','f',' '), HB_TAG('F','A','R',' ')}, /* Tangshewi (retired code) -> Persian */
+ {HB_TAG('t','n','g',' '), HB_TAG_NONE }, /* Tobanga != Tonga */
+ {HB_TAG('t','o','d',' '), HB_TAG('T','O','D','0')}, /* Toma */
+ {HB_TAG('t','o','i',' '), HB_TAG('T','N','G',' ')}, /* Tonga (Zambia) */
+ {HB_TAG('t','o','j',' '), HB_TAG('M','Y','N',' ')}, /* Tojolabal -> Mayan */
+ {HB_TAG('t','o','l',' '), HB_TAG('A','T','H',' ')}, /* Tolowa -> Athapaskan */
+ {HB_TAG('t','o','r',' '), HB_TAG('B','A','D','0')}, /* Togbo-Vara Banda -> Banda */
+ {HB_TAG('t','p','i',' '), HB_TAG('T','P','I',' ')}, /* Tok Pisin */
+ {HB_TAG('t','p','i',' '), HB_TAG('C','P','P',' ')}, /* Tok Pisin -> Creoles */
+ {HB_TAG('t','r','f',' '), HB_TAG('C','P','P',' ')}, /* Trinidadian Creole English -> Creoles */
+ {HB_TAG('t','r','k',' '), HB_TAG_NONE }, /* Turkic [collection] != Turkish */
+ {HB_TAG('t','r','u',' '), HB_TAG('T','U','A',' ')}, /* Turoyo -> Turoyo Aramaic */
+ {HB_TAG('t','r','u',' '), HB_TAG('S','Y','R',' ')}, /* Turoyo -> Syriac */
+ {HB_TAG('t','s','g',' '), HB_TAG_NONE }, /* Tausug != Tsonga */
+/*{HB_TAG('t','s','j',' '), HB_TAG('T','S','J',' ')},*/ /* Tshangla */
+ {HB_TAG('t','t','c',' '), HB_TAG('M','Y','N',' ')}, /* Tektiteko -> Mayan */
+ {HB_TAG('t','t','m',' '), HB_TAG('A','T','H',' ')}, /* Northern Tutchone -> Athapaskan */
+ {HB_TAG('t','t','q',' '), HB_TAG('T','M','H',' ')}, /* Tawallammat Tamajaq -> Tamashek */
+ {HB_TAG('t','t','q',' '), HB_TAG('B','B','R',' ')}, /* Tawallammat Tamajaq -> Berber */
+ {HB_TAG('t','u','a',' '), HB_TAG_NONE }, /* Wiarumus != Turoyo Aramaic */
+ {HB_TAG('t','u','l',' '), HB_TAG_NONE }, /* Tula != Tumbuka */
+/*{HB_TAG('t','u','m',' '), HB_TAG('T','U','M',' ')},*/ /* Tumbuka -> Tulu */
+ {HB_TAG('t','u','u',' '), HB_TAG('A','T','H',' ')}, /* Tututni -> Athapaskan */
+ {HB_TAG('t','u','v',' '), HB_TAG_NONE }, /* Turkana != Tuvin */
+ {HB_TAG('t','u','y',' '), HB_TAG('K','A','L',' ')}, /* Tugen -> Kalenjin */
+/*{HB_TAG('t','v','l',' '), HB_TAG('T','V','L',' ')},*/ /* Tuvalu */
+ {HB_TAG('t','v','y',' '), HB_TAG('C','P','P',' ')}, /* Timor Pidgin -> Creoles */
+ {HB_TAG('t','x','c',' '), HB_TAG('A','T','H',' ')}, /* Tsetsaut -> Athapaskan */
+ {HB_TAG('t','x','y',' '), HB_TAG('M','L','G',' ')}, /* Tanosy Malagasy -> Malagasy */
+ {HB_TAG('t','y','v',' '), HB_TAG('T','U','V',' ')}, /* Tuvinian -> Tuvin */
+/*{HB_TAG('t','y','z',' '), HB_TAG('T','Y','Z',' ')},*/ /* Tày */
+ {HB_TAG('t','z','h',' '), HB_TAG('M','Y','N',' ')}, /* Tzeltal -> Mayan */
+ {HB_TAG('t','z','j',' '), HB_TAG('M','Y','N',' ')}, /* Tz'utujil -> Mayan */
+ {HB_TAG('t','z','m',' '), HB_TAG('T','Z','M',' ')}, /* Central Atlas Tamazight -> Tamazight */
+ {HB_TAG('t','z','m',' '), HB_TAG('B','B','R',' ')}, /* Central Atlas Tamazight -> Berber */
+ {HB_TAG('t','z','o',' '), HB_TAG('T','Z','O',' ')}, /* Tzotzil */
+ {HB_TAG('t','z','o',' '), HB_TAG('M','Y','N',' ')}, /* Tzotzil -> Mayan */
+ {HB_TAG('u','b','l',' '), HB_TAG('B','I','K',' ')}, /* Buhi'non Bikol -> Bikol */
+/*{HB_TAG('u','d','m',' '), HB_TAG('U','D','M',' ')},*/ /* Udmurt */
+ {HB_TAG('u','k','i',' '), HB_TAG('K','U','I',' ')}, /* Kui (India) */
+ {HB_TAG('u','l','n',' '), HB_TAG('C','P','P',' ')}, /* Unserdeutsch -> Creoles */
+/*{HB_TAG('u','m','b',' '), HB_TAG('U','M','B',' ')},*/ /* Umbundu */
+ {HB_TAG('u','n','r',' '), HB_TAG('M','U','N',' ')}, /* Mundari */
+ {HB_TAG('u','r','k',' '), HB_TAG('M','L','Y',' ')}, /* Urak Lawoi' -> Malay */
+ {HB_TAG('u','s','p',' '), HB_TAG('M','Y','N',' ')}, /* Uspanteco -> Mayan */
+ {HB_TAG('u','z','n',' '), HB_TAG('U','Z','B',' ')}, /* Northern Uzbek -> Uzbek */
+ {HB_TAG('u','z','s',' '), HB_TAG('U','Z','B',' ')}, /* Southern Uzbek -> Uzbek */
+ {HB_TAG('v','a','p',' '), HB_TAG('Q','I','N',' ')}, /* Vaiphei -> Chin */
+/*{HB_TAG('v','e','c',' '), HB_TAG('V','E','C',' ')},*/ /* Venetian */
+ {HB_TAG('v','i','c',' '), HB_TAG('C','P','P',' ')}, /* Virgin Islands Creole English -> Creoles */
+ {HB_TAG('v','i','t',' '), HB_TAG_NONE }, /* Viti != Vietnamese */
+ {HB_TAG('v','k','k',' '), HB_TAG('M','L','Y',' ')}, /* Kaur -> Malay */
+ {HB_TAG('v','k','p',' '), HB_TAG('C','P','P',' ')}, /* Korlai Creole Portuguese -> Creoles */
+ {HB_TAG('v','k','t',' '), HB_TAG('M','L','Y',' ')}, /* Tenggarong Kutai Malay -> Malay */
+ {HB_TAG('v','l','s',' '), HB_TAG('F','L','E',' ')}, /* Vlaams -> Dutch (Flemish) */
+ {HB_TAG('v','m','w',' '), HB_TAG('M','A','K',' ')}, /* Makhuwa */
+/*{HB_TAG('v','r','o',' '), HB_TAG('V','R','O',' ')},*/ /* Võro */
+ {HB_TAG('w','a','g',' '), HB_TAG_NONE }, /* Wa'ema != Wagdi */
+/*{HB_TAG('w','a','r',' '), HB_TAG('W','A','R',' ')},*/ /* Waray (Philippines) -> Waray-Waray */
+ {HB_TAG('w','b','m',' '), HB_TAG('W','A',' ',' ')}, /* Wa */
+ {HB_TAG('w','b','r',' '), HB_TAG('W','A','G',' ')}, /* Wagdi */
+ {HB_TAG('w','b','r',' '), HB_TAG('R','A','J',' ')}, /* Wagdi -> Rajasthani */
+/*{HB_TAG('w','c','i',' '), HB_TAG('W','C','I',' ')},*/ /* Waci Gbe */
+ {HB_TAG('w','e','a',' '), HB_TAG('K','R','N',' ')}, /* Wewaw -> Karen */
+ {HB_TAG('w','e','s',' '), HB_TAG('C','P','P',' ')}, /* Cameroon Pidgin -> Creoles */
+ {HB_TAG('w','e','u',' '), HB_TAG('Q','I','N',' ')}, /* Rawngtu Chin -> Chin */
+ {HB_TAG('w','l','c',' '), HB_TAG('C','M','R',' ')}, /* Mwali Comorian -> Comorian */
+ {HB_TAG('w','l','e',' '), HB_TAG('S','I','G',' ')}, /* Wolane -> Silte Gurage */
+ {HB_TAG('w','l','k',' '), HB_TAG('A','T','H',' ')}, /* Wailaki -> Athapaskan */
+ {HB_TAG('w','n','i',' '), HB_TAG('C','M','R',' ')}, /* Ndzwani Comorian -> Comorian */
+ {HB_TAG('w','r','y',' '), HB_TAG('M','A','W',' ')}, /* Merwari -> Marwari */
+ {HB_TAG('w','s','g',' '), HB_TAG('G','O','N',' ')}, /* Adilabad Gondi -> Gondi */
+/*{HB_TAG('w','t','m',' '), HB_TAG('W','T','M',' ')},*/ /* Mewati */
+ {HB_TAG('w','u','u',' '), HB_TAG('Z','H','S',' ')}, /* Wu Chinese -> Chinese, Simplified */
+ {HB_TAG('x','a','l',' '), HB_TAG('K','L','M',' ')}, /* Kalmyk */
+ {HB_TAG('x','a','l',' '), HB_TAG('T','O','D',' ')}, /* Kalmyk -> Todo */
+ {HB_TAG('x','a','n',' '), HB_TAG('S','E','K',' ')}, /* Xamtanga -> Sekota */
+ {HB_TAG('x','b','d',' '), HB_TAG_NONE }, /* Bindal != Lü */
+/*{HB_TAG('x','j','b',' '), HB_TAG('X','J','B',' ')},*/ /* Minjungbal -> Minjangbal */
+/*{HB_TAG('x','k','f',' '), HB_TAG('X','K','F',' ')},*/ /* Khengkha */
+ {HB_TAG('x','m','g',' '), HB_TAG('B','M','L',' ')}, /* Mengaka -> Bamileke */
+ {HB_TAG('x','m','m',' '), HB_TAG('M','L','Y',' ')}, /* Manado Malay -> Malay */
+ {HB_TAG('x','m','m',' '), HB_TAG('C','P','P',' ')}, /* Manado Malay -> Creoles */
+ {HB_TAG('x','m','v',' '), HB_TAG('M','L','G',' ')}, /* Antankarana Malagasy -> Malagasy */
+ {HB_TAG('x','m','w',' '), HB_TAG('M','L','G',' ')}, /* Tsimihety Malagasy -> Malagasy */
+ {HB_TAG('x','n','j',' '), HB_TAG('S','X','T',' ')}, /* Ngoni (Tanzania) -> Sutu */
+ {HB_TAG('x','n','q',' '), HB_TAG('S','X','T',' ')}, /* Ngoni (Mozambique) -> Sutu */
+ {HB_TAG('x','n','r',' '), HB_TAG('D','G','R',' ')}, /* Kangri -> Dogri (macrolanguage) */
+/*{HB_TAG('x','o','g',' '), HB_TAG('X','O','G',' ')},*/ /* Soga */
+ {HB_TAG('x','p','e',' '), HB_TAG('X','P','E',' ')}, /* Liberia Kpelle -> Kpelle (Liberia) */
+ {HB_TAG('x','p','e',' '), HB_TAG('K','P','L',' ')}, /* Liberia Kpelle -> Kpelle */
+ {HB_TAG('x','s','l',' '), HB_TAG('S','S','L',' ')}, /* South Slavey */
+ {HB_TAG('x','s','l',' '), HB_TAG('S','L','A',' ')}, /* South Slavey -> Slavey */
+ {HB_TAG('x','s','l',' '), HB_TAG('A','T','H',' ')}, /* South Slavey -> Athapaskan */
+ {HB_TAG('x','s','t',' '), HB_TAG('S','I','G',' ')}, /* Silt'e (retired code) -> Silte Gurage */
+/*{HB_TAG('x','u','b',' '), HB_TAG('X','U','B',' ')},*/ /* Betta Kurumba -> Bette Kuruma */
+/*{HB_TAG('x','u','j',' '), HB_TAG('X','U','J',' ')},*/ /* Jennu Kurumba -> Jennu Kuruma */
+ {HB_TAG('x','u','p',' '), HB_TAG('A','T','H',' ')}, /* Upper Umpqua -> Athapaskan */
+ {HB_TAG('x','w','o',' '), HB_TAG('T','O','D',' ')}, /* Written Oirat -> Todo */
+ {HB_TAG('y','a','j',' '), HB_TAG('B','A','D','0')}, /* Banda-Yangere -> Banda */
+ {HB_TAG('y','a','k',' '), HB_TAG_NONE }, /* Yakama != Sakha */
+/*{HB_TAG('y','a','o',' '), HB_TAG('Y','A','O',' ')},*/ /* Yao */
+/*{HB_TAG('y','a','p',' '), HB_TAG('Y','A','P',' ')},*/ /* Yapese */
+ {HB_TAG('y','b','a',' '), HB_TAG_NONE }, /* Yala != Yoruba */
+ {HB_TAG('y','b','b',' '), HB_TAG('B','M','L',' ')}, /* Yemba -> Bamileke */
+ {HB_TAG('y','b','d',' '), HB_TAG('A','R','K',' ')}, /* Yangbye (retired code) -> Rakhine */
+ {HB_TAG('y','d','d',' '), HB_TAG('J','I','I',' ')}, /* Eastern Yiddish -> Yiddish */
+/*{HB_TAG('y','g','p',' '), HB_TAG('Y','G','P',' ')},*/ /* Gepo */
+ {HB_TAG('y','i','h',' '), HB_TAG('J','I','I',' ')}, /* Western Yiddish -> Yiddish */
+ {HB_TAG('y','i','m',' '), HB_TAG_NONE }, /* Yimchungru Naga != Yi Modern */
+/*{HB_TAG('y','n','a',' '), HB_TAG('Y','N','A',' ')},*/ /* Aluo */
+ {HB_TAG('y','o','s',' '), HB_TAG('Q','I','N',' ')}, /* Yos (retired code) -> Chin */
+ {HB_TAG('y','u','a',' '), HB_TAG('M','Y','N',' ')}, /* Yucateco -> Mayan */
+ {HB_TAG('y','u','e',' '), HB_TAG('Z','H','H',' ')}, /* Yue Chinese -> Chinese, Traditional, Hong Kong SAR */
+/*{HB_TAG('y','w','q',' '), HB_TAG('Y','W','Q',' ')},*/ /* Wuding-Luquan Yi */
+ {HB_TAG('z','c','h',' '), HB_TAG('Z','H','A',' ')}, /* Central Hongshuihe Zhuang -> Zhuang */
+ {HB_TAG('z','d','j',' '), HB_TAG('C','M','R',' ')}, /* Ngazidja Comorian -> Comorian */
+/*{HB_TAG('z','e','a',' '), HB_TAG('Z','E','A',' ')},*/ /* Zeeuws -> Zealandic */
+ {HB_TAG('z','e','h',' '), HB_TAG('Z','H','A',' ')}, /* Eastern Hongshuihe Zhuang -> Zhuang */
+ {HB_TAG('z','e','n',' '), HB_TAG('B','B','R',' ')}, /* Zenaga -> Berber */
+ {HB_TAG('z','g','b',' '), HB_TAG('Z','H','A',' ')}, /* Guibei Zhuang -> Zhuang */
+ {HB_TAG('z','g','h',' '), HB_TAG('Z','G','H',' ')}, /* Standard Moroccan Tamazight */
+ {HB_TAG('z','g','h',' '), HB_TAG('B','B','R',' ')}, /* Standard Moroccan Tamazight -> Berber */
+ {HB_TAG('z','g','m',' '), HB_TAG('Z','H','A',' ')}, /* Minz Zhuang -> Zhuang */
+ {HB_TAG('z','g','n',' '), HB_TAG('Z','H','A',' ')}, /* Guibian Zhuang -> Zhuang */
+ {HB_TAG('z','h','d',' '), HB_TAG('Z','H','A',' ')}, /* Dai Zhuang -> Zhuang */
+ {HB_TAG('z','h','n',' '), HB_TAG('Z','H','A',' ')}, /* Nong Zhuang -> Zhuang */
+ {HB_TAG('z','l','j',' '), HB_TAG('Z','H','A',' ')}, /* Liujiang Zhuang -> Zhuang */
+ {HB_TAG('z','l','m',' '), HB_TAG('M','L','Y',' ')}, /* Malay */
+ {HB_TAG('z','l','n',' '), HB_TAG('Z','H','A',' ')}, /* Lianshan Zhuang -> Zhuang */
+ {HB_TAG('z','l','q',' '), HB_TAG('Z','H','A',' ')}, /* Liuqian Zhuang -> Zhuang */
+ {HB_TAG('z','m','i',' '), HB_TAG('M','L','Y',' ')}, /* Negeri Sembilan Malay -> Malay */
+ {HB_TAG('z','m','z',' '), HB_TAG('B','A','D','0')}, /* Mbandja -> Banda */
+ {HB_TAG('z','n','d',' '), HB_TAG_NONE }, /* Zande [collection] != Zande */
+ {HB_TAG('z','n','e',' '), HB_TAG('Z','N','D',' ')}, /* Zande */
+ {HB_TAG('z','o','m',' '), HB_TAG('Q','I','N',' ')}, /* Zou -> Chin */
+ {HB_TAG('z','q','e',' '), HB_TAG('Z','H','A',' ')}, /* Qiubei Zhuang -> Zhuang */
+ {HB_TAG('z','s','m',' '), HB_TAG('M','L','Y',' ')}, /* Standard Malay -> Malay */
+ {HB_TAG('z','u','m',' '), HB_TAG('L','R','C',' ')}, /* Kumzari -> Luri */
+ {HB_TAG('z','y','b',' '), HB_TAG('Z','H','A',' ')}, /* Yongbei Zhuang -> Zhuang */
+ {HB_TAG('z','y','g',' '), HB_TAG('Z','H','A',' ')}, /* Yang Zhuang -> Zhuang */
+ {HB_TAG('z','y','j',' '), HB_TAG('Z','H','A',' ')}, /* Youjiang Zhuang -> Zhuang */
+ {HB_TAG('z','y','n',' '), HB_TAG('Z','H','A',' ')}, /* Yongnan Zhuang -> Zhuang */
+ {HB_TAG('z','y','p',' '), HB_TAG('Q','I','N',' ')}, /* Zyphe Chin -> Chin */
+/*{HB_TAG('z','z','a',' '), HB_TAG('Z','Z','A',' ')},*/ /* Zazaki [macrolanguage] */
+ {HB_TAG('z','z','j',' '), HB_TAG('Z','H','A',' ')}, /* Zuojiang Zhuang -> Zhuang */
};
/**
@@ -1639,69 +1642,75 @@ hb_ot_tags_from_complex_language (const char *lang_str,
unsigned int *count /* IN/OUT */,
hb_tag_t *tags /* OUT */)
{
- if (subtag_matches (lang_str, limit, "-fonnapa"))
- {
- /* Undetermined; North American Phonetic Alphabet */
- tags[0] = HB_TAG('A','P','P','H'); /* Phonetic transcription—Americanist conventions */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-polyton"))
- {
- /* Modern Greek (1453-); Polytonic Greek */
- tags[0] = HB_TAG('P','G','R',' '); /* Polytonic Greek */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-arevmda"))
- {
- /* Armenian; Western Armenian (retired code) */
- tags[0] = HB_TAG('H','Y','E',' '); /* Armenian */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-provenc"))
- {
- /* Occitan (post 1500); Provençal */
- tags[0] = HB_TAG('P','R','O',' '); /* Provençal / Old Provençal */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-fonipa"))
- {
- /* Undetermined; International Phonetic Alphabet */
- tags[0] = HB_TAG('I','P','P','H'); /* Phonetic transcription—IPA conventions */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-geok"))
- {
- /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
- tags[0] = HB_TAG('K','G','E',' '); /* Khutsuri Georgian */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-syre"))
+ if (limit - lang_str >= 7)
{
- /* Undetermined; Syriac (Estrangelo variant) */
- tags[0] = HB_TAG('S','Y','R','E'); /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-syrj"))
- {
- /* Undetermined; Syriac (Western variant) */
- tags[0] = HB_TAG('S','Y','R','J'); /* Syriac, Western script-variant (equivalent to ISO 15924 'Syrj') */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-syrn"))
- {
- /* Undetermined; Syriac (Eastern variant) */
- tags[0] = HB_TAG('S','Y','R','N'); /* Syriac, Eastern script-variant (equivalent to ISO 15924 'Syrn') */
- *count = 1;
- return true;
+ const char *p = strchr (lang_str, '-');
+ if (!p || p >= limit || limit - p < 5) goto out;
+ if (subtag_matches (p, limit, "-fonnapa", 8))
+ {
+ /* Undetermined; North American Phonetic Alphabet */
+ tags[0] = HB_TAG('A','P','P','H'); /* Phonetic transcription—Americanist conventions */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-polyton", 8))
+ {
+ /* Modern Greek (1453-); Polytonic Greek */
+ tags[0] = HB_TAG('P','G','R',' '); /* Polytonic Greek */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-arevmda", 8))
+ {
+ /* Armenian; Western Armenian (retired code) */
+ tags[0] = HB_TAG('H','Y','E',' '); /* Armenian */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-provenc", 8))
+ {
+ /* Occitan (post 1500); Provençal */
+ tags[0] = HB_TAG('P','R','O',' '); /* Provençal / Old Provençal */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-fonipa", 7))
+ {
+ /* Undetermined; International Phonetic Alphabet */
+ tags[0] = HB_TAG('I','P','P','H'); /* Phonetic transcription—IPA conventions */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-geok", 5))
+ {
+ /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
+ tags[0] = HB_TAG('K','G','E',' '); /* Khutsuri Georgian */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-syre", 5))
+ {
+ /* Undetermined; Syriac (Estrangelo variant) */
+ tags[0] = HB_TAG('S','Y','R','E'); /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-syrj", 5))
+ {
+ /* Undetermined; Syriac (Western variant) */
+ tags[0] = HB_TAG('S','Y','R','J'); /* Syriac, Western script-variant (equivalent to ISO 15924 'Syrj') */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-syrn", 5))
+ {
+ /* Undetermined; Syriac (Eastern variant) */
+ tags[0] = HB_TAG('S','Y','R','N'); /* Syriac, Eastern script-variant (equivalent to ISO 15924 'Syrn') */
+ *count = 1;
+ return true;
+ }
}
+out:
switch (lang_str[0])
{
case 'a':
@@ -1714,14 +1723,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'c':
- if (lang_matches (&lang_str[1], "do-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "do-hant-hk", 10))
{
/* Min Dong Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "do-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "do-hant-mo", 10))
{
/* Min Dong Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1734,14 +1743,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "jy-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "jy-hant-hk", 10))
{
/* Jinyu Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "jy-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "jy-hant-mo", 10))
{
/* Jinyu Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1754,14 +1763,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "mn-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "mn-hant-hk", 10))
{
/* Mandarin Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "mn-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "mn-hant-mo", 10))
{
/* Mandarin Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1774,14 +1783,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "np-hant-hk", 10))
{
/* Northern Ping Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "np-hant-mo", 10))
{
/* Northern Ping Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1794,14 +1803,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "px-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "px-hant-hk", 10))
{
/* Pu-Xian Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "px-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "px-hant-mo", 10))
{
/* Pu-Xian Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1814,14 +1823,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "sp-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "sp-hant-hk", 10))
{
/* Southern Ping Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sp-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "sp-hant-mo", 10))
{
/* Southern Ping Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1834,14 +1843,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "zh-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "zh-hant-hk", 10))
{
/* Huizhou Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zh-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "zh-hant-mo", 10))
{
/* Huizhou Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1854,14 +1863,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "zo-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "zo-hant-hk", 10))
{
/* Min Zhong Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zo-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "zo-hant-mo", 10))
{
/* Min Zhong Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1874,112 +1883,112 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "do-hans"))
+ if (lang_matches (&lang_str[1], limit, "do-hans", 7))
{
/* Min Dong Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "do-hant"))
+ if (lang_matches (&lang_str[1], limit, "do-hant", 7))
{
/* Min Dong Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "jy-hans"))
+ if (lang_matches (&lang_str[1], limit, "jy-hans", 7))
{
/* Jinyu Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "jy-hant"))
+ if (lang_matches (&lang_str[1], limit, "jy-hant", 7))
{
/* Jinyu Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "mn-hans"))
+ if (lang_matches (&lang_str[1], limit, "mn-hans", 7))
{
/* Mandarin Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "mn-hant"))
+ if (lang_matches (&lang_str[1], limit, "mn-hant", 7))
{
/* Mandarin Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hans"))
+ if (lang_matches (&lang_str[1], limit, "np-hans", 7))
{
/* Northern Ping Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant"))
+ if (lang_matches (&lang_str[1], limit, "np-hant", 7))
{
/* Northern Ping Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "px-hans"))
+ if (lang_matches (&lang_str[1], limit, "px-hans", 7))
{
/* Pu-Xian Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "px-hant"))
+ if (lang_matches (&lang_str[1], limit, "px-hant", 7))
{
/* Pu-Xian Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sp-hans"))
+ if (lang_matches (&lang_str[1], limit, "sp-hans", 7))
{
/* Southern Ping Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sp-hant"))
+ if (lang_matches (&lang_str[1], limit, "sp-hant", 7))
{
/* Southern Ping Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zh-hans"))
+ if (lang_matches (&lang_str[1], limit, "zh-hans", 7))
{
/* Huizhou Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zh-hant"))
+ if (lang_matches (&lang_str[1], limit, "zh-hant", 7))
{
/* Huizhou Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zo-hans"))
+ if (lang_matches (&lang_str[1], limit, "zo-hans", 7))
{
/* Min Zhong Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zo-hant"))
+ if (lang_matches (&lang_str[1], limit, "zo-hant", 7))
{
/* Min Zhong Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -1987,7 +1996,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "do-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Min Dong Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -1995,7 +2004,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "do-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Min Dong Chinese; Macao */
unsigned int i;
@@ -2009,7 +2018,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "do-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Min Dong Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2017,7 +2026,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "jy-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Jinyu Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2025,7 +2034,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "jy-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Jinyu Chinese; Macao */
unsigned int i;
@@ -2039,7 +2048,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "jy-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Jinyu Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2047,7 +2056,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "mn-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Mandarin Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2055,7 +2064,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "mn-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Mandarin Chinese; Macao */
unsigned int i;
@@ -2069,7 +2078,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "mn-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Mandarin Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2077,7 +2086,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Northern Ping Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2085,7 +2094,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Northern Ping Chinese; Macao */
unsigned int i;
@@ -2099,7 +2108,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Northern Ping Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2107,7 +2116,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "px-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Pu-Xian Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2115,7 +2124,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "px-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Pu-Xian Chinese; Macao */
unsigned int i;
@@ -2129,7 +2138,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "px-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Pu-Xian Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2137,7 +2146,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sp-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Southern Ping Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2145,7 +2154,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sp-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Southern Ping Chinese; Macao */
unsigned int i;
@@ -2159,7 +2168,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sp-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Southern Ping Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2167,7 +2176,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zh-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Huizhou Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2175,7 +2184,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zh-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Huizhou Chinese; Macao */
unsigned int i;
@@ -2189,7 +2198,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zh-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Huizhou Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2197,7 +2206,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zo-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Min Zhong Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2205,7 +2214,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zo-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Min Zhong Chinese; Macao */
unsigned int i;
@@ -2219,7 +2228,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zo-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Min Zhong Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2228,14 +2237,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'g':
- if (lang_matches (&lang_str[1], "an-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "an-hant-hk", 10))
{
/* Gan Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "an-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "an-hant-mo", 10))
{
/* Gan Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2248,21 +2257,21 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "an-hans"))
+ if (lang_matches (&lang_str[1], limit, "an-hans", 7))
{
/* Gan Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "an-hant"))
+ if (lang_matches (&lang_str[1], limit, "an-hant", 7))
{
/* Gan Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "a-latg"))
+ if (lang_matches (&lang_str[1], limit, "a-latg", 6))
{
/* Irish; Latin (Gaelic variant) */
tags[0] = HB_TAG('I','R','T',' '); /* Irish Traditional */
@@ -2270,7 +2279,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Gan Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2278,7 +2287,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Gan Chinese; Macao */
unsigned int i;
@@ -2292,7 +2301,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Gan Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2301,14 +2310,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'h':
- if (lang_matches (&lang_str[1], "ak-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "ak-hant-hk", 10))
{
/* Hakka Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "ak-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "ak-hant-mo", 10))
{
/* Hakka Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2321,14 +2330,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "sn-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "sn-hant-hk", 10))
{
/* Xiang Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sn-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "sn-hant-mo", 10))
{
/* Xiang Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2341,28 +2350,28 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "ak-hans"))
+ if (lang_matches (&lang_str[1], limit, "ak-hans", 7))
{
/* Hakka Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "ak-hant"))
+ if (lang_matches (&lang_str[1], limit, "ak-hant", 7))
{
/* Hakka Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sn-hans"))
+ if (lang_matches (&lang_str[1], limit, "sn-hans", 7))
{
/* Xiang Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sn-hant"))
+ if (lang_matches (&lang_str[1], limit, "sn-hant", 7))
{
/* Xiang Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2370,7 +2379,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "ak-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Hakka Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2378,7 +2387,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "ak-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Hakka Chinese; Macao */
unsigned int i;
@@ -2392,7 +2401,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "ak-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Hakka Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2400,7 +2409,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sn-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Xiang Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2408,7 +2417,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sn-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Xiang Chinese; Macao */
unsigned int i;
@@ -2422,7 +2431,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sn-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Xiang Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2460,7 +2469,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'l':
- if (lang_matches (&lang_str[1], "zh-hans"))
+ if (lang_matches (&lang_str[1], limit, "zh-hans", 7))
{
/* Literary Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
@@ -2469,14 +2478,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'm':
- if (lang_matches (&lang_str[1], "np-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "np-hant-hk", 10))
{
/* Min Bei Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "np-hant-mo", 10))
{
/* Min Bei Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2489,14 +2498,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "np-hans"))
+ if (lang_matches (&lang_str[1], limit, "np-hans", 7))
{
/* Min Bei Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant"))
+ if (lang_matches (&lang_str[1], limit, "np-hant", 7))
{
/* Min Bei Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2504,7 +2513,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Min Bei Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2512,7 +2521,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Min Bei Chinese; Macao */
unsigned int i;
@@ -2526,7 +2535,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Min Bei Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2534,7 +2543,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "nw-", 3)
- && subtag_matches (lang_str, limit, "-th"))
+ && subtag_matches (lang_str, limit, "-th", 3))
{
/* Mon; Thailand */
tags[0] = HB_TAG('M','O','N','T'); /* Thailand Mon */
@@ -2543,14 +2552,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'n':
- if (lang_matches (&lang_str[1], "an-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "an-hant-hk", 10))
{
/* Min Nan Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "an-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "an-hant-mo", 10))
{
/* Min Nan Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2563,14 +2572,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "an-hans"))
+ if (lang_matches (&lang_str[1], limit, "an-hans", 7))
{
/* Min Nan Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "an-hant"))
+ if (lang_matches (&lang_str[1], limit, "an-hant", 7))
{
/* Min Nan Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2578,7 +2587,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Min Nan Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2586,7 +2595,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Min Nan Chinese; Macao */
unsigned int i;
@@ -2600,7 +2609,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Min Nan Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2624,7 +2633,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
break;
case 'r':
if (0 == strncmp (&lang_str[1], "o-", 2)
- && subtag_matches (lang_str, limit, "-md"))
+ && subtag_matches (lang_str, limit, "-md", 3))
{
/* Romanian; Moldova */
unsigned int i;
@@ -2639,14 +2648,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'w':
- if (lang_matches (&lang_str[1], "uu-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "uu-hant-hk", 10))
{
/* Wu Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "uu-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "uu-hant-mo", 10))
{
/* Wu Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2659,14 +2668,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "uu-hans"))
+ if (lang_matches (&lang_str[1], limit, "uu-hans", 7))
{
/* Wu Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "uu-hant"))
+ if (lang_matches (&lang_str[1], limit, "uu-hant", 7))
{
/* Wu Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2674,7 +2683,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "uu-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Wu Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2682,7 +2691,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "uu-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Wu Chinese; Macao */
unsigned int i;
@@ -2696,7 +2705,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "uu-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Wu Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2705,7 +2714,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'y':
- if (lang_matches (&lang_str[1], "ue-hans"))
+ if (lang_matches (&lang_str[1], limit, "ue-hans", 7))
{
/* Yue Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
@@ -2714,14 +2723,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'z':
- if (lang_matches (&lang_str[1], "h-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "h-hant-hk", 9))
{
/* Chinese [macrolanguage]; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "h-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "h-hant-mo", 9))
{
/* Chinese [macrolanguage]; Han (Traditional variant); Macao */
unsigned int i;
@@ -2741,14 +2750,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "h-hans"))
+ if (lang_matches (&lang_str[1], limit, "h-hans", 6))
{
/* Chinese [macrolanguage]; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "h-hant"))
+ if (lang_matches (&lang_str[1], limit, "h-hant", 6))
{
/* Chinese [macrolanguage]; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2763,7 +2772,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "h-", 2)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Chinese [macrolanguage]; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2771,7 +2780,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "h-", 2)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Chinese [macrolanguage]; Macao */
unsigned int i;
@@ -2785,7 +2794,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "h-", 2)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Chinese [macrolanguage]; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc
index f50be97ad3a..a4a9515362a 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-tag.cc
@@ -189,48 +189,46 @@ hb_ot_tag_to_script (hb_tag_t tag)
/* hb_language_t */
-static bool
+static inline bool
subtag_matches (const char *lang_str,
const char *limit,
- const char *subtag)
+ const char *subtag,
+ unsigned subtag_len)
{
+ if (likely ((unsigned) (limit - lang_str) < subtag_len))
+ return false;
+
do {
const char *s = strstr (lang_str, subtag);
if (!s || s >= limit)
return false;
- if (!ISALNUM (s[strlen (subtag)]))
+ if (!ISALNUM (s[subtag_len]))
return true;
- lang_str = s + strlen (subtag);
+ lang_str = s + subtag_len;
} while (true);
}
-static hb_bool_t
-lang_matches (const char *lang_str, const char *spec)
+static bool
+lang_matches (const char *lang_str,
+ const char *limit,
+ const char *spec,
+ unsigned spec_len)
{
- unsigned int len = strlen (spec);
+ if (likely ((unsigned) (limit - lang_str) < spec_len))
+ return false;
- return strncmp (lang_str, spec, len) == 0 &&
- (lang_str[len] == '\0' || lang_str[len] == '-');
+ return strncmp (lang_str, spec, spec_len) == 0 &&
+ (lang_str[spec_len] == '\0' || lang_str[spec_len] == '-');
}
struct LangTag
{
- char language[4];
+ hb_tag_t language;
hb_tag_t tag;
- int cmp (const char *a) const
+ int cmp (hb_tag_t a) const
{
- const char *b = this->language;
- unsigned int da, db;
- const char *p;
-
- p = strchr (a, '-');
- da = p ? (unsigned int) (p - a) : strlen (a);
-
- p = strchr (b, '-');
- db = p ? (unsigned int) (p - b) : strlen (b);
-
- return strncmp (a, b, hb_max (da, db));
+ return a < this->language ? -1 : a > this->language ? +1 : 0;
}
int cmp (const LangTag *that) const
{ return cmp (that->language); }
@@ -266,7 +264,6 @@ hb_ot_tags_from_language (const char *lang_str,
hb_tag_t *tags)
{
const char *s;
- unsigned int tag_idx;
/* Check for matches of multiple subtags. */
if (hb_ot_tags_from_complex_language (lang_str, limit, count, tags))
@@ -283,17 +280,39 @@ hb_ot_tags_from_language (const char *lang_str,
ISALPHA (s[1]))
lang_str = s + 1;
}
- if (hb_sorted_array (ot_languages).bfind (lang_str, &tag_idx))
+ const LangTag *ot_languages = nullptr;
+ unsigned ot_languages_len = 0;
+ const char *dash = strchr (lang_str, '-');
+ unsigned first_len = dash ? dash - lang_str : limit - lang_str;
+ if (first_len == 2)
{
+ ot_languages = ot_languages2;
+ ot_languages_len = ARRAY_LENGTH (ot_languages2);
+ }
+ else if (first_len == 3)
+ {
+ ot_languages = ot_languages3;
+ ot_languages_len = ARRAY_LENGTH (ot_languages3);
+ }
+
+ hb_tag_t lang_tag = hb_tag_from_string (lang_str, first_len);
+
+ static unsigned last_tag_idx; /* Poor man's cache. */
+ unsigned tag_idx = last_tag_idx;
+
+ if (likely (tag_idx < ot_languages_len && ot_languages[tag_idx].language == lang_tag) ||
+ hb_sorted_array (ot_languages, ot_languages_len).bfind (lang_tag, &tag_idx))
+ {
+ last_tag_idx = tag_idx;
unsigned int i;
while (tag_idx != 0 &&
- 0 == strcmp (ot_languages[tag_idx].language, ot_languages[tag_idx - 1].language))
+ ot_languages[tag_idx].language == ot_languages[tag_idx - 1].language)
tag_idx--;
for (i = 0;
i < *count &&
- tag_idx + i < ARRAY_LENGTH (ot_languages) &&
+ tag_idx + i < ot_languages_len &&
ot_languages[tag_idx + i].tag != HB_TAG_NONE &&
- 0 == strcmp (ot_languages[tag_idx + i].language, ot_languages[tag_idx].language);
+ ot_languages[tag_idx + i].language == ot_languages[tag_idx].language;
i++)
tags[i] = ot_languages[tag_idx + i].tag;
*count = i;
@@ -459,9 +478,19 @@ hb_ot_tag_to_language (hb_tag_t tag)
return disambiguated_tag;
}
- for (i = 0; i < ARRAY_LENGTH (ot_languages); i++)
- if (ot_languages[i].tag == tag)
- return hb_language_from_string (ot_languages[i].language, -1);
+ char buf[4];
+ for (i = 0; i < ARRAY_LENGTH (ot_languages2); i++)
+ if (ot_languages2[i].tag == tag)
+ {
+ hb_tag_to_string (ot_languages2[i].language, buf);
+ return hb_language_from_string (buf, 2);
+ }
+ for (i = 0; i < ARRAY_LENGTH (ot_languages3); i++)
+ if (ot_languages3[i].tag == tag)
+ {
+ hb_tag_to_string (ot_languages3[i].language, buf);
+ return hb_language_from_string (buf, 3);
+ }
/* Return a custom language in the form of "x-hbot-AABBCCDD".
* If it's three letters long, also guess it's ISO 639-3 and lower-case and
@@ -557,13 +586,23 @@ hb_ot_tags_to_script_and_language (hb_tag_t script_tag,
static inline void
test_langs_sorted ()
{
- for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++)
+ for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages2); i++)
+ {
+ int c = ot_languages2[i].cmp (&ot_languages2[i - 1]);
+ if (c > 0)
+ {
+ fprintf (stderr, "ot_languages2 not sorted at index %d: %08x %d %08x\n",
+ i, ot_languages2[i-1].language, c, ot_languages2[i].language);
+ abort();
+ }
+ }
+ for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages3); i++)
{
- int c = ot_languages[i].cmp (&ot_languages[i - 1]);
+ int c = ot_languages3[i].cmp (&ot_languages3[i - 1]);
if (c > 0)
{
- fprintf (stderr, "ot_languages not sorted at index %d: %s %d %s\n",
- i, ot_languages[i-1].language, c, ot_languages[i].language);
+ fprintf (stderr, "ot_languages3 not sorted at index %d: %08x %d %08x\n",
+ i, ot_languages3[i-1].language, c, ot_languages3[i].language);
abort();
}
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh
index 618cec08fbf..3b2a38b9a61 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-ot-var-gvar-table.hh
@@ -390,13 +390,10 @@ struct gvar
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && (version.major == 1) &&
- (glyphCount == c->get_num_glyphs ()) &&
sharedTuples.sanitize (c, this, axisCount * sharedTupleCount) &&
(is_long_offset () ?
c->check_array (get_long_offset_array (), glyphCount+1) :
- c->check_array (get_short_offset_array (), glyphCount+1)) &&
- c->check_array (((const HBUINT8*)&(this+dataZ)) + get_offset (0),
- get_offset (glyphCount) - get_offset (0)));
+ c->check_array (get_short_offset_array (), glyphCount+1)));
}
/* GlyphVariationData not sanitized here; must be checked while accessing each glyph variation data */
@@ -482,7 +479,9 @@ struct gvar
const hb_bytes_t get_glyph_var_data_bytes (hb_blob_t *blob, hb_codepoint_t glyph) const
{
unsigned start_offset = get_offset (glyph);
- unsigned length = get_offset (glyph+1) - start_offset;
+ unsigned end_offset = get_offset (glyph+1);
+ if (unlikely (end_offset < start_offset)) return hb_bytes_t ();
+ unsigned length = end_offset - start_offset;
hb_bytes_t var_data = blob->as_bytes ().sub_array (((unsigned) dataZ) + start_offset, length);
return likely (var_data.length >= GlyphVariationData::min_size) ? var_data : hb_bytes_t ();
}
@@ -490,7 +489,10 @@ struct gvar
bool is_long_offset () const { return flags & 1; }
unsigned get_offset (unsigned i) const
- { return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2; }
+ {
+ if (unlikely (i > glyphCount)) return 0;
+ return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2;
+ }
const HBUINT32 * get_long_offset_array () const { return (const HBUINT32 *) &offsetZ; }
const HBUINT16 *get_short_offset_array () const { return (const HBUINT16 *) &offsetZ; }
@@ -696,7 +698,7 @@ no_more_gaps:
offsetZ; /* Offsets from the start of the GlyphVariationData array
* to each GlyphVariationData table. */
public:
- DEFINE_SIZE_MIN (20);
+ DEFINE_SIZE_ARRAY (20, offsetZ);
};
struct gvar_accelerator_t : gvar::accelerator_t {
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-priority-queue.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-priority-queue.hh
index 7d799ae9062..ffb86e30ae2 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-priority-queue.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-priority-queue.hh
@@ -38,18 +38,11 @@
*/
struct hb_priority_queue_t
{
- HB_DELETE_COPY_ASSIGN (hb_priority_queue_t);
- hb_priority_queue_t () { init (); }
- ~hb_priority_queue_t () { fini (); }
-
private:
typedef hb_pair_t<int64_t, unsigned> item_t;
hb_vector_t<item_t> heap;
public:
- void init () { heap.init (); }
-
- void fini () { heap.fini (); }
void reset () { heap.resize (0); }
@@ -58,14 +51,17 @@ struct hb_priority_queue_t
void insert (int64_t priority, unsigned value)
{
heap.push (item_t (priority, value));
+ if (unlikely (heap.in_error ())) return;
bubble_up (heap.length - 1);
}
item_t pop_minimum ()
{
- item_t result = heap[0];
+ assert (!is_empty ());
+
+ item_t result = heap.arrayZ[0];
- heap[0] = heap[heap.length - 1];
+ heap.arrayZ[0] = heap.arrayZ[heap.length - 1];
heap.shrink (heap.length - 1);
bubble_down (0);
@@ -104,6 +100,8 @@ struct hb_priority_queue_t
void bubble_down (unsigned index)
{
+ assert (index <= heap.length);
+
unsigned left = left_child (index);
unsigned right = right_child (index);
@@ -113,11 +111,11 @@ struct hb_priority_queue_t
return;
bool has_right = right < heap.length;
- if (heap[index].first <= heap[left].first
- && (!has_right || heap[index].first <= heap[right].first))
+ if (heap.arrayZ[index].first <= heap.arrayZ[left].first
+ && (!has_right || heap[index].first <= heap.arrayZ[right].first))
return;
- if (!has_right || heap[left].first < heap[right].first)
+ if (!has_right || heap.arrayZ[left].first < heap.arrayZ[right].first)
{
swap (index, left);
bubble_down (left);
@@ -130,10 +128,12 @@ struct hb_priority_queue_t
void bubble_up (unsigned index)
{
+ assert (index <= heap.length);
+
if (index == 0) return;
unsigned parent_index = parent (index);
- if (heap[parent_index].first <= heap[index].first)
+ if (heap.arrayZ[parent_index].first <= heap.arrayZ[index].first)
return;
swap (index, parent_index);
@@ -142,9 +142,9 @@ struct hb_priority_queue_t
void swap (unsigned a, unsigned b)
{
- item_t temp = heap[a];
- heap[a] = heap[b];
- heap[b] = temp;
+ assert (a <= heap.length);
+ assert (b <= heap.length);
+ hb_swap (heap.arrayZ[a], heap.arrayZ[b]);
}
};
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh
index 2a9e75c45b1..ce9ff90bb4f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-repacker.hh
@@ -49,6 +49,17 @@ struct graph_t
unsigned end = 0;
unsigned priority = 0;
+ friend void swap (vertex_t& a, vertex_t& b)
+ {
+ hb_swap (a.obj, b.obj);
+ hb_swap (a.distance, b.distance);
+ hb_swap (a.space, b.space);
+ hb_swap (a.parents, b.parents);
+ hb_swap (a.start, b.start);
+ hb_swap (a.end, b.end);
+ hb_swap (a.priority, b.priority);
+ }
+
bool is_shared () const
{
return parents.length > 1;
@@ -148,6 +159,8 @@ struct graph_t
{
num_roots_for_space_.push (1);
bool removed_nil = false;
+ vertices_.alloc (objects.length);
+ vertices_scratch_.alloc (objects.length);
for (unsigned i = 0; i < objects.length; i++)
{
// TODO(grieger): check all links point to valid objects.
@@ -247,59 +260,6 @@ struct graph_t
}
/*
- * Generates a new topological sorting of graph using Kahn's
- * algorithm: https://en.wikipedia.org/wiki/Topological_sorting#Algorithms
- */
- void sort_kahn ()
- {
- positions_invalid = true;
-
- if (vertices_.length <= 1) {
- // Graph of 1 or less doesn't need sorting.
- return;
- }
-
- hb_vector_t<unsigned> queue;
- hb_vector_t<vertex_t> sorted_graph;
- if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
- hb_vector_t<unsigned> id_map;
- if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
-
- hb_vector_t<unsigned> removed_edges;
- if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
- update_parents ();
-
- queue.push (root_idx ());
- int new_id = vertices_.length - 1;
-
- while (!queue.in_error () && queue.length)
- {
- unsigned next_id = queue[0];
- queue.remove (0);
-
- vertex_t& next = vertices_[next_id];
- sorted_graph[new_id] = next;
- id_map[next_id] = new_id--;
-
- for (const auto& link : next.obj.all_links ()) {
- removed_edges[link.objidx]++;
- if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx]))
- queue.push (link.objidx);
- }
- }
-
- check_success (!queue.in_error ());
- check_success (!sorted_graph.in_error ());
- if (!check_success (new_id == -1))
- print_orphaned_nodes ();
-
- remap_all_obj_indices (id_map, &sorted_graph);
-
- hb_swap (vertices_, sorted_graph);
- sorted_graph.fini ();
- }
-
- /*
* Generates a new topological sorting of graph ordered by the shortest
* distance to each node.
*/
@@ -315,7 +275,7 @@ struct graph_t
update_distances ();
hb_priority_queue_t queue;
- hb_vector_t<vertex_t> sorted_graph;
+ hb_vector_t<vertex_t> &sorted_graph = vertices_scratch_;
if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
hb_vector_t<unsigned> id_map;
if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
@@ -331,8 +291,9 @@ struct graph_t
{
unsigned next_id = queue.pop_minimum().second;
- vertex_t& next = vertices_[next_id];
- sorted_graph[new_id] = next;
+ hb_swap (sorted_graph[new_id], vertices_[next_id]);
+ const vertex_t& next = sorted_graph[new_id];
+
id_map[next_id] = new_id--;
for (const auto& link : next.obj.all_links ()) {
@@ -356,7 +317,6 @@ struct graph_t
remap_all_obj_indices (id_map, &sorted_graph);
hb_swap (vertices_, sorted_graph);
- sorted_graph.fini ();
}
/*
@@ -568,12 +528,10 @@ struct graph_t
// The last object is the root of the graph, so swap back the root to the end.
// The root's obj idx does change, however since it's root nothing else refers to it.
// all other obj idx's will be unaffected.
- vertex_t root = vertices_[vertices_.length - 2];
- vertices_[clone_idx] = *clone;
- vertices_[vertices_.length - 1] = root;
+ hb_swap (vertices_[vertices_.length - 2], *clone);
// Since the root moved, update the parents arrays of all children on the root.
- for (const auto& l : root.obj.all_links ())
+ for (const auto& l : root ().obj.all_links ())
vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ());
return clone_idx;
@@ -1090,6 +1048,7 @@ struct graph_t
public:
// TODO(garretrieger): make private, will need to move most of offset overflow code into graph.
hb_vector_t<vertex_t> vertices_;
+ hb_vector_t<vertex_t> vertices_scratch_;
private:
bool parents_invalid;
bool distance_invalid;
@@ -1217,7 +1176,6 @@ hb_resolve_overflows (const T& packed,
// Kahn sort is ~twice as fast as shortest distance sort and works for many fonts
// so try it first to save time.
graph_t sorted_graph (packed);
- sorted_graph.sort_kahn ();
if (!sorted_graph.will_overflow ())
{
return sorted_graph.serialize ();
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh
index 40895a45482..5663b290c3b 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-serialize.hh
@@ -74,7 +74,7 @@ struct hb_serialize_context_t
}
object_t () = default;
-
+
#ifdef HB_EXPERIMENTAL_API
object_t (const hb_object_t &o)
{
@@ -91,6 +91,15 @@ struct hb_serialize_context_t
}
#endif
+ friend void swap (object_t& a, object_t& b)
+ {
+ hb_swap (a.head, b.head);
+ hb_swap (a.tail, b.tail);
+ hb_swap (a.next, b.next);
+ hb_swap (a.real_links, b.real_links);
+ hb_swap (a.virtual_links, b.virtual_links);
+ }
+
bool operator == (const object_t &o) const
{
// Virtual links aren't considered for equality since they don't affect the functionality
@@ -111,10 +120,10 @@ struct hb_serialize_context_t
struct link_t
{
unsigned width: 3;
- bool is_signed: 1;
+ unsigned is_signed: 1;
unsigned whence: 2;
- unsigned position: 28;
- unsigned bias;
+ unsigned bias : 26;
+ unsigned position;
objidx_t objidx;
link_t () = default;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh
index 1f054078692..60256263637 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-set.hh
@@ -43,8 +43,8 @@ struct hb_sparseset_t
hb_sparseset_t (const hb_sparseset_t& other) : hb_sparseset_t () { set (other); }
hb_sparseset_t (hb_sparseset_t&& other) : hb_sparseset_t () { s = std::move (other.s); }
- hb_sparseset_t& operator= (const hb_sparseset_t& other) { set (other); return *this; }
- hb_sparseset_t& operator= (hb_sparseset_t&& other) { hb_swap (*this, other); return *this; }
+ hb_sparseset_t& operator = (const hb_sparseset_t& other) { set (other); return *this; }
+ hb_sparseset_t& operator = (hb_sparseset_t&& other) { s = std::move (other.s); return *this; }
friend void swap (hb_sparseset_t& a, hb_sparseset_t& b) { hb_swap (a.s, b.s); }
hb_sparseset_t (std::initializer_list<hb_codepoint_t> lst) : hb_sparseset_t ()
@@ -53,7 +53,7 @@ struct hb_sparseset_t
add (item);
}
template <typename Iterable,
- hb_requires (hb_is_iterable (Iterable))>
+ hb_requires (hb_is_iterable (Iterable))>
hb_sparseset_t (const Iterable &o) : hb_sparseset_t ()
{
hb_copy (o, *this);
@@ -77,10 +77,12 @@ struct hb_sparseset_t
void err () { s.err (); }
bool in_error () const { return s.in_error (); }
+ void alloc (unsigned sz) { s.alloc (sz); }
void reset () { s.reset (); }
void clear () { s.clear (); }
void invert () { s.invert (); }
bool is_empty () const { return s.is_empty (); }
+ uint32_t hash () const { return s.hash (); }
void add (hb_codepoint_t g) { s.add (g); }
bool add_range (hb_codepoint_t a, hb_codepoint_t b) { return s.add_range (a, b); }
@@ -125,6 +127,8 @@ struct hb_sparseset_t
void set (const hb_sparseset_t &other) { s.set (other.s); }
bool is_equal (const hb_sparseset_t &other) const { return s.is_equal (other.s); }
+ bool operator == (const hb_set_t &other) const { return is_equal (other); }
+ bool operator != (const hb_set_t &other) const { return !is_equal (other); }
bool is_subset (const hb_sparseset_t &larger_set) const { return s.is_subset (larger_set.s); }
@@ -158,15 +162,19 @@ struct hb_sparseset_t
struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t>
{
- hb_set_t () = default;
+ using sparseset = hb_sparseset_t<hb_bit_set_invertible_t>;
+
~hb_set_t () = default;
- hb_set_t (hb_set_t&) = default;
- hb_set_t& operator= (const hb_set_t&) = default;
- hb_set_t& operator= (hb_set_t&&) = default;
- hb_set_t (std::initializer_list<hb_codepoint_t> lst) : hb_sparseset_t<hb_bit_set_invertible_t> (lst) {}
+ hb_set_t () : sparseset () {};
+ hb_set_t (std::nullptr_t) : hb_set_t () {};
+ hb_set_t (const hb_set_t &o) : sparseset ((sparseset &) o) {};
+ hb_set_t (hb_set_t&& o) : sparseset (std::move ((sparseset &) o)) {}
+ hb_set_t& operator = (const hb_set_t&) = default;
+ hb_set_t& operator = (hb_set_t&&) = default;
+ hb_set_t (std::initializer_list<hb_codepoint_t> lst) : sparseset (lst) {}
template <typename Iterable,
hb_requires (hb_is_iterable (Iterable))>
- hb_set_t (const Iterable &o) : hb_sparseset_t<hb_bit_set_invertible_t> (o) {}
+ hb_set_t (const Iterable &o) : sparseset (o) {}
};
static_assert (hb_set_t::INVALID == HB_SET_VALUE_INVALID, "");
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh
index 18657705fac..ae155b4e3c8 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff-common.hh
@@ -40,7 +40,7 @@ struct str_encoder_t
str_encoder_t (str_buff_t &buff_)
: buff (buff_), error (false) {}
- void reset () { buff.resize (0); }
+ void reset () { buff.reset (); }
void encode_byte (unsigned char b)
{
@@ -107,20 +107,18 @@ struct str_encoder_t
encode_byte (op);
}
- void copy_str (const byte_str_t &str)
+ void copy_str (const hb_ubytes_t &str)
{
unsigned int offset = buff.length;
- if (unlikely (!buff.resize (offset + str.length)))
+ /* Manually resize buffer since faster. */
+ if ((signed) (buff.length + str.length) <= buff.allocated)
+ buff.length += str.length;
+ else if (unlikely (!buff.resize (offset + str.length)))
{
set_error ();
return;
}
- if (unlikely (buff.length < offset + str.length))
- {
- set_error ();
- return;
- }
- memcpy (&buff[offset], &str[0], str.length);
+ memcpy (buff.arrayZ + offset, &str[0], str.length);
}
bool is_error () const { return error; }
@@ -253,12 +251,12 @@ struct subr_flattener_t
if (endchar_op != OpCode_Invalid) flat_charstrings[i].push (endchar_op);
continue;
}
- const byte_str_t str = (*acc.charStrings)[glyph];
+ const hb_ubytes_t str = (*acc.charStrings)[glyph];
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
return false;
- cs_interpreter_t<ENV, OPSET, flatten_param_t> interp;
- interp.env.init (str, acc, fd);
+ ENV env (str, acc, fd);
+ cs_interpreter_t<ENV, OPSET, flatten_param_t> interp (env);
flatten_param_t param = {
flat_charstrings[i],
(bool) (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
@@ -317,9 +315,9 @@ struct parsed_cs_op_t : op_str_t
unsigned int subr_num;
protected:
- bool drop_flag : 1;
- bool keep_flag : 1;
- bool skip_flag : 1;
+ bool drop_flag;
+ bool keep_flag;
+ bool skip_flag;
};
struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
@@ -398,19 +396,19 @@ struct parsed_cs_str_vec_t : hb_vector_t<parsed_cs_str_t>
struct subr_subset_param_t
{
- void init (parsed_cs_str_t *parsed_charstring_,
- parsed_cs_str_vec_t *parsed_global_subrs_, parsed_cs_str_vec_t *parsed_local_subrs_,
- hb_set_t *global_closure_, hb_set_t *local_closure_,
- bool drop_hints_)
- {
- parsed_charstring = parsed_charstring_;
- current_parsed_str = parsed_charstring;
- parsed_global_subrs = parsed_global_subrs_;
- parsed_local_subrs = parsed_local_subrs_;
- global_closure = global_closure_;
- local_closure = local_closure_;
- drop_hints = drop_hints_;
- }
+ subr_subset_param_t (parsed_cs_str_t *parsed_charstring_,
+ parsed_cs_str_vec_t *parsed_global_subrs_,
+ parsed_cs_str_vec_t *parsed_local_subrs_,
+ hb_set_t *global_closure_,
+ hb_set_t *local_closure_,
+ bool drop_hints_) :
+ current_parsed_str (parsed_charstring_),
+ parsed_charstring (parsed_charstring_),
+ parsed_global_subrs (parsed_global_subrs_),
+ parsed_local_subrs (parsed_local_subrs_),
+ global_closure (global_closure_),
+ local_closure (local_closure_),
+ drop_hints (drop_hints_) {}
parsed_cs_str_t *get_parsed_str_for_context (call_context_t &context)
{
@@ -468,6 +466,7 @@ struct subr_remap_t : hb_inc_bimap_t
* no optimization based on usage counts. fonttools doesn't appear doing that either.
*/
+ resize (closure->get_population ());
hb_codepoint_t old_num = HB_SET_VALUE_INVALID;
while (hb_set_next (closure, &old_num))
add (old_num);
@@ -561,19 +560,21 @@ struct subr_subsetter_t
hb_codepoint_t glyph;
if (!plan->old_gid_for_new_gid (i, &glyph))
continue;
- const byte_str_t str = (*acc.charStrings)[glyph];
+ const hb_ubytes_t str = (*acc.charStrings)[glyph];
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
return false;
- cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp;
- interp.env.init (str, acc, fd);
+ ENV env (str, acc, fd);
+ cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp (env);
- subr_subset_param_t param;
- param.init (&parsed_charstrings[i],
- &parsed_global_subrs, &parsed_local_subrs[fd],
- &closures.global_closure, &closures.local_closures[fd],
- plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+ parsed_charstrings[i].alloc (str.length);
+ subr_subset_param_t param (&parsed_charstrings[i],
+ &parsed_global_subrs,
+ &parsed_local_subrs[fd],
+ &closures.global_closure,
+ &closures.local_closures[fd],
+ plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
if (unlikely (!interp.interpret (param)))
return false;
@@ -593,11 +594,12 @@ struct subr_subsetter_t
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
return false;
- subr_subset_param_t param;
- param.init (&parsed_charstrings[i],
- &parsed_global_subrs, &parsed_local_subrs[fd],
- &closures.global_closure, &closures.local_closures[fd],
- plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+ subr_subset_param_t param (&parsed_charstrings[i],
+ &parsed_global_subrs,
+ &parsed_local_subrs[fd],
+ &closures.global_closure,
+ &closures.local_closures[fd],
+ plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
drop_hints_param_t drop;
if (drop_hints_in_str (parsed_charstrings[i], param, drop))
@@ -618,11 +620,12 @@ struct subr_subsetter_t
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
return false;
- subr_subset_param_t param;
- param.init (&parsed_charstrings[i],
- &parsed_global_subrs, &parsed_local_subrs[fd],
- &closures.global_closure, &closures.local_closures[fd],
- plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+ subr_subset_param_t param (&parsed_charstrings[i],
+ &parsed_global_subrs,
+ &parsed_local_subrs[fd],
+ &closures.global_closure,
+ &closures.local_closures[fd],
+ plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
collect_subr_refs_in_str (parsed_charstrings[i], param);
}
}
@@ -849,9 +852,10 @@ struct subr_subsetter_t
bool encode_str (const parsed_cs_str_t &str, const unsigned int fd, str_buff_t &buff) const
{
- buff.init ();
+ unsigned count = str.get_count ();
str_encoder_t encoder (buff);
encoder.reset ();
+ buff.alloc (count * 3);
/* if a prefix (CFF1 width or CFF2 vsindex) has been removed along with hints,
* re-insert it at the beginning of charstreing */
if (str.has_prefix () && str.is_hint_dropped ())
@@ -860,7 +864,7 @@ struct subr_subsetter_t
if (str.prefix_op () != OpCode_Invalid)
encoder.encode_op (str.prefix_op ());
}
- for (unsigned int i = 0; i < str.get_count(); i++)
+ for (unsigned int i = 0; i < count; i++)
{
const parsed_cs_op_t &opstr = str.values[i];
if (!opstr.for_drop () && !opstr.for_skip ())
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc
index 35fecd67bc5..52bb13d320b 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff1.cc
@@ -169,7 +169,7 @@ struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dic
supp_op.op = op;
if ( unlikely (!(opstr.str.length >= opstr.last_arg_offset + 3)))
return_trace (false);
- supp_op.str = byte_str_t (&opstr.str + opstr.last_arg_offset, opstr.str.length - opstr.last_arg_offset);
+ supp_op.str = hb_ubytes_t (&opstr.str + opstr.last_arg_offset, opstr.str.length - opstr.last_arg_offset);
return_trace (UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::registry]) &&
UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::ordering]) &&
copy_opstr (c, supp_op));
@@ -270,13 +270,13 @@ struct range_list_t : hb_vector_t<code_pair_t>
/* replace the first glyph ID in the "glyph" field each range with a nLeft value */
bool complete (unsigned int last_glyph)
{
- bool two_byte = false;
- for (unsigned int i = (*this).length; i > 0; i--)
+ bool two_byte = false;
+ unsigned count = this->length;
+ for (unsigned int i = count; i; i--)
{
- code_pair_t &pair = (*this)[i - 1];
- unsigned int nLeft = last_glyph - pair.glyph - 1;
- if (nLeft >= 0x100)
- two_byte = true;
+ code_pair_t &pair = arrayZ[i - 1];
+ unsigned int nLeft = last_glyph - pair.glyph - 1;
+ two_byte |= nLeft >= 0x100;
last_glyph = pair.glyph;
pair.glyph = nLeft;
}
@@ -442,6 +442,9 @@ struct cff_subset_plan {
return;
}
+ bool use_glyph_to_sid_map = plan->num_output_glyphs () > plan->source->get_num_glyphs () / 8.;
+ hb_map_t *glyph_to_sid_map = use_glyph_to_sid_map ? acc.create_glyph_to_sid_map () : nullptr;
+
unsigned int glyph;
for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++)
{
@@ -451,7 +454,7 @@ struct cff_subset_plan {
/* Retain the SID for the old missing glyph ID */
old_glyph = glyph;
}
- sid = acc.glyph_to_sid (old_glyph);
+ sid = glyph_to_sid_map ? glyph_to_sid_map->get (old_glyph) : acc.glyph_to_sid (old_glyph);
if (!acc.is_CID ())
sid = sidmap.add (sid);
@@ -464,6 +467,9 @@ struct cff_subset_plan {
last_sid = sid;
}
+ if (glyph_to_sid_map)
+ hb_map_destroy (glyph_to_sid_map);
+
bool two_byte = subset_charset_ranges.complete (glyph);
size0 = Charset0::min_size + HBUINT16::static_size * (plan->num_output_glyphs () - 1);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc
index 92dd6b1d2ca..08e820efcfb 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-cff2.cc
@@ -67,9 +67,9 @@ struct cff2_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<>
}
};
-struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t>
+struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t, blend_arg_t>
{
- static void flush_args_and_op (op_code_t op, cff2_cs_interp_env_t &env, flatten_param_t& param)
+ static void flush_args_and_op (op_code_t op, cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
{
switch (op)
{
@@ -97,7 +97,7 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
}
}
- static void flush_args (cff2_cs_interp_env_t &env, flatten_param_t& param)
+ static void flush_args (cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
{
for (unsigned int i = 0; i < env.argStack.get_count ();)
{
@@ -122,7 +122,7 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
SUPER::flush_args (env, param);
}
- static void flatten_blends (const blend_arg_t &arg, unsigned int i, cff2_cs_interp_env_t &env, flatten_param_t& param)
+ static void flatten_blends (const blend_arg_t &arg, unsigned int i, cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
{
/* flatten the default values */
str_encoder_t encoder (param.flatStr);
@@ -149,7 +149,7 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
encoder.encode_op (OpCode_blendcs);
}
- static void flush_op (op_code_t op, cff2_cs_interp_env_t &env, flatten_param_t& param)
+ static void flush_op (op_code_t op, cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
{
switch (op)
{
@@ -163,13 +163,13 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
}
private:
- typedef cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t> SUPER;
- typedef cs_opset_t<blend_arg_t, cff2_cs_opset_flatten_t, cff2_cs_opset_flatten_t, cff2_cs_interp_env_t, flatten_param_t> CSOPSET;
+ typedef cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t, blend_arg_t> SUPER;
+ typedef cs_opset_t<blend_arg_t, cff2_cs_opset_flatten_t, cff2_cs_opset_flatten_t, cff2_cs_interp_env_t<blend_arg_t>, flatten_param_t> CSOPSET;
};
-struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t>
+struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t, blend_arg_t>
{
- static void process_op (op_code_t op, cff2_cs_interp_env_t &env, subr_subset_param_t& param)
+ static void process_op (op_code_t op, cff2_cs_interp_env_t<blend_arg_t> &env, subr_subset_param_t& param)
{
switch (op) {
@@ -201,7 +201,7 @@ struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t
protected:
static void process_call_subr (op_code_t op, cs_type_t type,
- cff2_cs_interp_env_t &env, subr_subset_param_t& param,
+ cff2_cs_interp_env_t<blend_arg_t> &env, subr_subset_param_t& param,
cff2_biased_subrs_t& subrs, hb_set_t *closure)
{
byte_str_ref_t str_ref = env.str_ref;
@@ -212,15 +212,15 @@ struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t
}
private:
- typedef cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t> SUPER;
+ typedef cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t, blend_arg_t> SUPER;
};
-struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs, const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_subr_subset_t>
+struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs, const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t<blend_arg_t>, cff2_cs_opset_subr_subset_t>
{
cff2_subr_subsetter_t (const OT::cff2::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_)
: subr_subsetter_t (acc_, plan_) {}
- static void complete_parsed_str (cff2_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
+ static void complete_parsed_str (cff2_cs_interp_env_t<blend_arg_t> &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
{
/* vsindex is inserted at the beginning of the charstring as necessary */
if (env.seen_vsindex ())
@@ -245,7 +245,7 @@ struct cff2_subset_plan {
if (desubroutinize)
{
/* Flatten global & local subrs */
- subr_flattener_t<const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_flatten_t>
+ subr_flattener_t<const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t<blend_arg_t>, cff2_cs_opset_flatten_t>
flattener(acc, plan);
if (!flattener.flatten (subset_charstrings))
return false;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc
index 74b7e3977c0..a62ae8e0245 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.cc
@@ -279,12 +279,7 @@ static inline void
_remove_invalid_gids (hb_set_t *glyphs,
unsigned int num_glyphs)
{
- hb_codepoint_t gid = HB_SET_VALUE_INVALID;
- while (glyphs->next (&gid))
- {
- if (gid >= num_glyphs)
- glyphs->del (gid);
- }
+ glyphs->del_range (num_glyphs, HB_SET_VALUE_INVALID);
}
static void
@@ -294,12 +289,13 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
{
OT::cmap::accelerator_t cmap (plan->source);
- constexpr static const int size_threshold = 4096;
-
+ unsigned size_threshold = plan->source->get_num_glyphs ();
if (glyphs->is_empty () && unicodes->get_population () < size_threshold)
{
- /* This is the fast path if it's anticipated that size of unicodes
- * is << than the number of codepoints in the font. */
+ // This is approach to collection is faster, but can only be used if glyphs
+ // are not being explicitly added to the subset and the input unicodes set is
+ // not excessively large (eg. an inverted set).
+ plan->unicode_to_new_gid_list.alloc (unicodes->get_population ());
for (hb_codepoint_t cp : *unicodes)
{
hb_codepoint_t gid;
@@ -310,27 +306,32 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
}
plan->codepoint_to_glyph->set (cp, gid);
+ plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
}
}
else
{
+ // This approach is slower, but can handle adding in glyphs to the subset and will match
+ // them with cmap entries.
hb_map_t unicode_glyphid_map;
- cmap.collect_mapping (hb_set_get_empty (), &unicode_glyphid_map);
+ hb_set_t cmap_unicodes;
+ cmap.collect_mapping (&cmap_unicodes, &unicode_glyphid_map);
+ plan->unicode_to_new_gid_list.alloc (hb_min(unicodes->get_population ()
+ + glyphs->get_population (),
+ cmap_unicodes.get_population ()));
- for (hb_pair_t<hb_codepoint_t, hb_codepoint_t> cp_gid :
- + unicode_glyphid_map.iter ())
+ for (hb_codepoint_t cp : cmap_unicodes)
{
- if (!unicodes->has (cp_gid.first) && !glyphs->has (cp_gid.second))
- continue;
+ hb_codepoint_t gid = unicode_glyphid_map[cp];
+ if (!unicodes->has (cp) && !glyphs->has (gid))
+ continue;
- plan->codepoint_to_glyph->set (cp_gid.first, cp_gid.second);
+ plan->codepoint_to_glyph->set (cp, gid);
+ plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
}
/* Add gids which where requested, but not mapped in cmap */
- // TODO(garretrieger):
- // Once https://github.com/harfbuzz/harfbuzz/issues/3169
- // is implemented, this can be done with union and del_range
- for (hb_codepoint_t gid : glyphs->iter ())
+ for (hb_codepoint_t gid : *glyphs)
{
if (gid >= plan->source->get_num_glyphs ())
break;
@@ -338,8 +339,12 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
}
}
- + plan->codepoint_to_glyph->keys () | hb_sink (plan->unicodes);
- + plan->codepoint_to_glyph->values () | hb_sink (plan->_glyphset_gsub);
+ auto &arr = plan->unicode_to_new_gid_list;
+ if (arr.length)
+ {
+ plan->unicodes->add_sorted_array (&arr.arrayZ->first, arr.length, sizeof (*arr.arrayZ));
+ plan->_glyphset_gsub->add_array (&arr.arrayZ->second, arr.length, sizeof (*arr.arrayZ));
+ }
}
static void
@@ -388,16 +393,19 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
_remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
hb_set_set (plan->_glyphset_colred, &cur_glyphset);
- // Populate a full set of glyphs to retain by adding all referenced
- // composite glyphs.
- for (hb_codepoint_t gid : cur_glyphset.iter ())
- {
- glyf.add_gid_and_children (gid, plan->_glyphset);
+
+ /* Populate a full set of glyphs to retain by adding all referenced
+ * composite glyphs. */
+ if (glyf.has_data ())
+ for (hb_codepoint_t gid : cur_glyphset)
+ glyf.add_gid_and_children (gid, plan->_glyphset);
+ else
+ plan->_glyphset->union_ (cur_glyphset);
#ifndef HB_NO_SUBSET_CFF
- if (cff.is_valid ())
+ if (cff.is_valid ())
+ for (hb_codepoint_t gid : cur_glyphset)
_add_cff_seac_components (cff, gid, plan->_glyphset);
#endif
- }
_remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ());
@@ -413,6 +421,20 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
}
static void
+_create_glyph_map_gsub (const hb_set_t* glyph_set_gsub,
+ const hb_map_t* glyph_map,
+ hb_map_t* out)
+{
+ + hb_iter (glyph_set_gsub)
+ | hb_map ([&] (hb_codepoint_t gid) {
+ return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid,
+ glyph_map->get (gid));
+ })
+ | hb_sink (out)
+ ;
+}
+
+static void
_create_old_gid_to_new_gid_map (const hb_face_t *face,
bool retain_gids,
const hb_set_t *all_gids_to_retain,
@@ -420,13 +442,19 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
hb_map_t *reverse_glyph_map, /* OUT */
unsigned int *num_glyphs /* OUT */)
{
+ unsigned pop = all_gids_to_retain->get_population ();
+ reverse_glyph_map->resize (pop);
+ glyph_map->resize (pop);
+
if (!retain_gids)
{
+ hb_enumerate (hb_iter (all_gids_to_retain), (hb_codepoint_t) 0)
| hb_sink (reverse_glyph_map)
;
*num_glyphs = reverse_glyph_map->get_population ();
- } else {
+ }
+ else
+ {
+ hb_iter (all_gids_to_retain)
| hb_map ([] (hb_codepoint_t _) {
return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (_, _);
@@ -434,10 +462,9 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
| hb_sink (reverse_glyph_map)
;
- unsigned max_glyph =
- + hb_iter (all_gids_to_retain)
- | hb_reduce (hb_max, 0u)
- ;
+ hb_codepoint_t max_glyph = HB_SET_VALUE_INVALID;
+ hb_set_previous (all_gids_to_retain, &max_glyph);
+
*num_glyphs = max_glyph + 1;
}
@@ -485,6 +512,9 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
plan->successful = true;
plan->flags = input->flags;
plan->unicodes = hb_set_create ();
+
+ plan->unicode_to_new_gid_list.init ();
+
plan->name_ids = hb_set_copy (input->sets.name_ids);
_nameid_closure (face, plan->name_ids);
plan->name_languages = hb_set_copy (input->sets.name_languages);
@@ -502,6 +532,7 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
plan->codepoint_to_glyph = hb_map_create ();
plan->glyph_map = hb_map_create ();
plan->reverse_glyph_map = hb_map_create ();
+ plan->glyph_map_gsub = hb_map_create ();
plan->gsub_lookups = hb_map_create ();
plan->gpos_lookups = hb_map_create ();
@@ -536,6 +567,19 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
plan->reverse_glyph_map,
&plan->_num_output_glyphs);
+ _create_glyph_map_gsub (
+ plan->_glyphset_gsub,
+ plan->glyph_map,
+ plan->glyph_map_gsub);
+
+ // Now that we have old to new gid map update the unicode to new gid list.
+ for (unsigned i = 0; i < plan->unicode_to_new_gid_list.length; i++)
+ {
+ // Use raw array access for performance.
+ plan->unicode_to_new_gid_list.arrayZ[i].second =
+ plan->glyph_map->get(plan->unicode_to_new_gid_list.arrayZ[i].second);
+ }
+
if (unlikely (plan->in_error ())) {
hb_subset_plan_destroy (plan);
return nullptr;
@@ -558,6 +602,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
if (!hb_object_destroy (plan)) return;
hb_set_destroy (plan->unicodes);
+ plan->unicode_to_new_gid_list.fini ();
hb_set_destroy (plan->name_ids);
hb_set_destroy (plan->name_languages);
hb_set_destroy (plan->layout_features);
@@ -569,6 +614,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_map_destroy (plan->codepoint_to_glyph);
hb_map_destroy (plan->glyph_map);
hb_map_destroy (plan->reverse_glyph_map);
+ hb_map_destroy (plan->glyph_map_gsub);
hb_set_destroy (plan->_glyphset);
hb_set_destroy (plan->_glyphset_gsub);
hb_set_destroy (plan->_glyphset_mathed);
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh
index ab2c4c302c5..cb567b769ea 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset-plan.hh
@@ -44,6 +44,7 @@ struct hb_subset_plan_t
// For each cp that we'd like to retain maps to the corresponding gid.
hb_set_t *unicodes;
+ hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> unicode_to_new_gid_list;
// name_ids we would like to retain
hb_set_t *name_ids;
@@ -69,6 +70,7 @@ struct hb_subset_plan_t
// Old -> New glyph id mapping
hb_map_t *glyph_map;
hb_map_t *reverse_glyph_map;
+ hb_map_t *glyph_map_gsub;
// Plan is only good for a specific source/dest so keep them with it
hb_face_t *source;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
index 4588268b762..31ddb4f8940 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-subset.cc
@@ -79,12 +79,14 @@ using OT::Layout::GSUB::GSUB;
*/
static unsigned
-_plan_estimate_subset_table_size (hb_subset_plan_t *plan, unsigned table_len)
+_plan_estimate_subset_table_size (hb_subset_plan_t *plan,
+ unsigned table_len,
+ bool same_size)
{
unsigned src_glyphs = plan->source->get_num_glyphs ();
unsigned dst_glyphs = plan->glyphset ()->get_population ();
- if (unlikely (!src_glyphs))
+ if (unlikely (!src_glyphs) || same_size)
return 512 + table_len;
return 512 + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
@@ -123,7 +125,6 @@ static
bool
_try_subset (const TableType *table,
hb_vector_t<char>* buf,
- unsigned buf_size,
hb_subset_context_t* c /* OUT */)
{
c->serializer->start_serialize<TableType> ();
@@ -136,7 +137,8 @@ _try_subset (const TableType *table,
return needed;
}
- buf_size += (buf_size >> 1) + 32;
+ unsigned buf_size = buf->allocated;
+ buf_size = buf_size * 2 + 16;
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.",
HB_UNTAG (c->table_tag), buf_size);
@@ -147,13 +149,13 @@ _try_subset (const TableType *table,
return needed;
}
- c->serializer->reset (buf->arrayZ, buf_size);
- return _try_subset (table, buf, buf_size, c);
+ c->serializer->reset (buf->arrayZ, buf->allocated);
+ return _try_subset (table, buf, c);
}
template<typename TableType>
static bool
-_subset (hb_subset_plan_t *plan)
+_subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf)
{
hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
const TableType *table = source_blob->as<TableType> ();
@@ -167,10 +169,13 @@ _subset (hb_subset_plan_t *plan)
return false;
}
- hb_vector_t<char> buf;
- /* TODO Not all tables are glyph-related. 'name' table size for example should not be
- * affected by number of glyphs. Accommodate that. */
- unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
+ /* Tables that we want to allocate same space as the source table. For GSUB/GPOS it's
+ * because those are expensive to subset, so giving them more room is fine. */
+ bool same_size_table = TableType::tableTag == HB_OT_TAG_GSUB ||
+ TableType::tableTag == HB_OT_TAG_GPOS ||
+ TableType::tableTag == HB_OT_TAG_name;
+
+ unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length, same_size_table);
DEBUG_MSG (SUBSET, nullptr,
"OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
if (unlikely (!buf.alloc (buf_size)))
@@ -181,10 +186,10 @@ _subset (hb_subset_plan_t *plan)
}
bool needed = false;
- hb_serialize_context_t serializer (buf.arrayZ, buf_size);
+ hb_serialize_context_t serializer (buf.arrayZ, buf.allocated);
{
hb_subset_context_t c (source_blob, plan, &serializer, tag);
- needed = _try_subset (table, &buf, buf_size, &c);
+ needed = _try_subset (table, &buf, &c);
}
hb_blob_destroy (source_blob);
@@ -274,7 +279,9 @@ _passthrough (hb_subset_plan_t *plan, hb_tag_t tag)
}
static bool
-_subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
+_subset_table (hb_subset_plan_t *plan,
+ hb_vector_t<char> &buf,
+ hb_tag_t tag)
{
if (plan->no_subset_tables->has (tag)) {
return _passthrough (plan, tag);
@@ -283,42 +290,42 @@ _subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
DEBUG_MSG (SUBSET, nullptr, "subset %c%c%c%c", HB_UNTAG (tag));
switch (tag)
{
- case HB_OT_TAG_glyf: return _subset<const OT::glyf> (plan);
- case HB_OT_TAG_hdmx: return _subset<const OT::hdmx> (plan);
- case HB_OT_TAG_name: return _subset<const OT::name> (plan);
+ case HB_OT_TAG_glyf: return _subset<const OT::glyf> (plan, buf);
+ case HB_OT_TAG_hdmx: return _subset<const OT::hdmx> (plan, buf);
+ case HB_OT_TAG_name: return _subset<const OT::name> (plan, buf);
case HB_OT_TAG_head:
if (_is_table_present (plan->source, HB_OT_TAG_glyf) && !_should_drop_table (plan, HB_OT_TAG_glyf))
return true; /* skip head, handled by glyf */
- return _subset<const OT::head> (plan);
+ return _subset<const OT::head> (plan, buf);
case HB_OT_TAG_hhea: return true; /* skip hhea, handled by hmtx */
- case HB_OT_TAG_hmtx: return _subset<const OT::hmtx> (plan);
+ case HB_OT_TAG_hmtx: return _subset<const OT::hmtx> (plan, buf);
case HB_OT_TAG_vhea: return true; /* skip vhea, handled by vmtx */
- case HB_OT_TAG_vmtx: return _subset<const OT::vmtx> (plan);
- case HB_OT_TAG_maxp: return _subset<const OT::maxp> (plan);
- case HB_OT_TAG_sbix: return _subset<const OT::sbix> (plan);
+ case HB_OT_TAG_vmtx: return _subset<const OT::vmtx> (plan, buf);
+ case HB_OT_TAG_maxp: return _subset<const OT::maxp> (plan, buf);
+ case HB_OT_TAG_sbix: return _subset<const OT::sbix> (plan, buf);
case HB_OT_TAG_loca: return true; /* skip loca, handled by glyf */
- case HB_OT_TAG_cmap: return _subset<const OT::cmap> (plan);
- case HB_OT_TAG_OS2 : return _subset<const OT::OS2 > (plan);
- case HB_OT_TAG_post: return _subset<const OT::post> (plan);
- case HB_OT_TAG_COLR: return _subset<const OT::COLR> (plan);
- case HB_OT_TAG_CPAL: return _subset<const OT::CPAL> (plan);
- case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan);
+ case HB_OT_TAG_cmap: return _subset<const OT::cmap> (plan, buf);
+ case HB_OT_TAG_OS2 : return _subset<const OT::OS2 > (plan, buf);
+ case HB_OT_TAG_post: return _subset<const OT::post> (plan, buf);
+ case HB_OT_TAG_COLR: return _subset<const OT::COLR> (plan, buf);
+ case HB_OT_TAG_CPAL: return _subset<const OT::CPAL> (plan, buf);
+ case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan, buf);
case HB_OT_TAG_CBDT: return true; /* skip CBDT, handled by CBLC */
- case HB_OT_TAG_MATH: return _subset<const OT::MATH> (plan);
+ case HB_OT_TAG_MATH: return _subset<const OT::MATH> (plan, buf);
#ifndef HB_NO_SUBSET_CFF
- case HB_OT_TAG_cff1: return _subset<const OT::cff1> (plan);
- case HB_OT_TAG_cff2: return _subset<const OT::cff2> (plan);
- case HB_OT_TAG_VORG: return _subset<const OT::VORG> (plan);
+ case HB_OT_TAG_cff1: return _subset<const OT::cff1> (plan, buf);
+ case HB_OT_TAG_cff2: return _subset<const OT::cff2> (plan, buf);
+ case HB_OT_TAG_VORG: return _subset<const OT::VORG> (plan, buf);
#endif
#ifndef HB_NO_SUBSET_LAYOUT
- case HB_OT_TAG_GDEF: return _subset<const OT::GDEF> (plan);
- case HB_OT_TAG_GSUB: return _subset<const GSUB> (plan);
- case HB_OT_TAG_GPOS: return _subset<const OT::GPOS> (plan);
- case HB_OT_TAG_gvar: return _subset<const OT::gvar> (plan);
- case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan);
- case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan);
+ case HB_OT_TAG_GDEF: return _subset<const OT::GDEF> (plan, buf);
+ case HB_OT_TAG_GSUB: return _subset<const GSUB> (plan, buf);
+ case HB_OT_TAG_GPOS: return _subset<const OT::GPOS> (plan, buf);
+ case HB_OT_TAG_gvar: return _subset<const OT::gvar> (plan, buf);
+ case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan, buf);
+ case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan, buf);
#endif
default:
@@ -379,6 +386,8 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
bool success = true;
hb_tag_t table_tags[32];
unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
+ hb_vector_t<char> buf;
+ buf.alloc (4096 - 16);
while ((hb_face_get_table_tags (plan->source, offset, &num_tables, table_tags), num_tables))
{
for (unsigned i = 0; i < num_tables; ++i)
@@ -386,7 +395,7 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
hb_tag_t tag = table_tags[i];
if (_should_drop_table (plan, tag) && !tags_set.has (tag)) continue;
tags_set.add (tag);
- success = _subset_table (plan, tag);
+ success = _subset_table (plan, buf, tag);
if (unlikely (!success)) goto end;
}
offset += num_tables;
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh
index 6c7d32e49d8..7b08e3b4d27 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-vector.hh
@@ -29,6 +29,7 @@
#include "hb.hh"
#include "hb-array.hh"
+#include "hb-meta.hh"
#include "hb-null.hh"
@@ -42,6 +43,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
using c_array_t = typename std::conditional<sorted, hb_sorted_array_t<const Type>, hb_array_t<const Type>>::type;
hb_vector_t () = default;
+ hb_vector_t (std::nullptr_t) : hb_vector_t () {}
hb_vector_t (std::initializer_list<Type> lst) : hb_vector_t ()
{
alloc (lst.size ());
@@ -59,7 +61,8 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
hb_vector_t (const hb_vector_t &o) : hb_vector_t ()
{
alloc (o.length);
- hb_copy (o, *this);
+ if (unlikely (in_error ())) return;
+ copy_vector (o);
}
hb_vector_t (hb_vector_t &&o)
{
@@ -70,9 +73,8 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
~hb_vector_t () { fini (); }
- private:
- int allocated = 0; /* == -1 means allocation failed. */
public:
+ int allocated = 0; /* == -1 means allocation failed. */
unsigned int length = 0;
public:
Type *arrayZ = nullptr;
@@ -108,7 +110,10 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
{
reset ();
alloc (o.length);
- hb_copy (o, *this);
+ if (unlikely (in_error ())) return *this;
+
+ copy_vector (o);
+
return *this;
}
hb_vector_t& operator = (hb_vector_t &&o)
@@ -184,12 +189,14 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
{
if (unlikely (!resize (length + 1)))
return &Crap (Type);
- return &arrayZ[length - 1];
+ return std::addressof (arrayZ[length - 1]);
}
- template <typename T>
+ template <typename T,
+ typename T2 = Type,
+ hb_enable_if (!std::is_copy_constructible<T2>::value &&
+ std::is_copy_assignable<T>::value)>
Type *push (T&& v)
{
- /* TODO Emplace? */
Type *p = push ();
if (p == &Crap (Type))
// If push failed to allocate then don't copy v, since this may cause
@@ -199,18 +206,34 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
*p = std::forward<T> (v);
return p;
}
+ template <typename T,
+ typename T2 = Type,
+ hb_enable_if (std::is_copy_constructible<T2>::value)>
+ Type *push (T&& v)
+ {
+ if (unlikely (!alloc (length + 1)))
+ // If push failed to allocate then don't copy v, since this may cause
+ // the created copy to leak memory since we won't have stored a
+ // reference to it.
+ return &Crap (Type);
+
+ /* Emplace. */
+ length++;
+ Type *p = std::addressof (arrayZ[length - 1]);
+ return new (p) Type (std::forward<T> (v));
+ }
bool in_error () const { return allocated < 0; }
template <typename T = Type,
- hb_enable_if (std::is_trivially_copy_assignable<T>::value)>
+ hb_enable_if (hb_is_trivially_copy_assignable(T))>
Type *
realloc_vector (unsigned new_allocated)
{
return (Type *) hb_realloc (arrayZ, new_allocated * sizeof (Type));
}
template <typename T = Type,
- hb_enable_if (!std::is_trivially_copy_assignable<T>::value)>
+ hb_enable_if (!hb_is_trivially_copy_assignable(T))>
Type *
realloc_vector (unsigned new_allocated)
{
@@ -230,8 +253,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
template <typename T = Type,
- hb_enable_if (std::is_trivially_constructible<T>::value ||
- !std::is_default_constructible<T>::value)>
+ hb_enable_if (hb_is_trivially_constructible(T))>
void
grow_vector (unsigned size)
{
@@ -239,8 +261,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
length = size;
}
template <typename T = Type,
- hb_enable_if (!std::is_trivially_constructible<T>::value &&
- std::is_default_constructible<T>::value)>
+ hb_enable_if (!hb_is_trivially_constructible(T))>
void
grow_vector (unsigned size)
{
@@ -252,14 +273,52 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
template <typename T = Type,
- hb_enable_if (std::is_trivially_destructible<T>::value)>
+ hb_enable_if (hb_is_trivially_copyable (T))>
+ void
+ copy_vector (const hb_vector_t &other)
+ {
+ length = other.length;
+ hb_memcpy ((void *) arrayZ, (const void *) other.arrayZ, length * item_size);
+ }
+ template <typename T = Type,
+ hb_enable_if (!hb_is_trivially_copyable (T) &&
+ std::is_copy_constructible<T>::value)>
+ void
+ copy_vector (const hb_vector_t &other)
+ {
+ length = 0;
+ while (length < other.length)
+ {
+ length++;
+ new (std::addressof (arrayZ[length - 1])) Type (other.arrayZ[length - 1]);
+ }
+ }
+ template <typename T = Type,
+ hb_enable_if (!hb_is_trivially_copyable (T) &&
+ !std::is_copy_constructible<T>::value &&
+ std::is_default_constructible<T>::value &&
+ std::is_copy_assignable<T>::value)>
+ void
+ copy_vector (const hb_vector_t &other)
+ {
+ length = 0;
+ while (length < other.length)
+ {
+ length++;
+ new (std::addressof (arrayZ[length - 1])) Type ();
+ arrayZ[length - 1] = other.arrayZ[length - 1];
+ }
+ }
+
+ template <typename T = Type,
+ hb_enable_if (hb_is_trivially_destructible(T))>
void
shrink_vector (unsigned size)
{
length = size;
}
template <typename T = Type,
- hb_enable_if (!std::is_trivially_destructible<T>::value)>
+ hb_enable_if (!hb_is_trivially_destructible(T))>
void
shrink_vector (unsigned size)
{
@@ -271,7 +330,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
template <typename T = Type,
- hb_enable_if (std::is_trivially_copy_assignable<T>::value)>
+ hb_enable_if (hb_is_trivially_copy_assignable(T))>
void
shift_down_vector (unsigned i)
{
@@ -280,7 +339,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
(length - i) * sizeof (Type));
}
template <typename T = Type,
- hb_enable_if (!std::is_trivially_copy_assignable<T>::value)>
+ hb_enable_if (!hb_is_trivially_copy_assignable(T))>
void
shift_down_vector (unsigned i)
{
@@ -341,7 +400,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
Type pop ()
{
if (!length) return Null (Type);
- Type v = std::move (arrayZ[length - 1]);
+ Type v = arrayZ[length - 1];
arrayZ[length - 1].~Type ();
length--;
return v;
@@ -351,8 +410,8 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
{
if (unlikely (i >= length))
return;
- arrayZ[i].~Type ();
shift_down_vector (i + 1);
+ arrayZ[length - 1].~Type ();
length--;
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc
index fd2b2f0e642..721edefe37b 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-map.cc
@@ -25,9 +25,13 @@
#include "hb.hh"
#include "hb-map.hh"
+#include "hb-set.hh"
#include <string>
static const std::string invalid{"invalid"};
+static const hb_map_t invalid_map{};
+static const hb_set_t invalid_set{};
+static const hb_vector_t<unsigned> invalid_vector{};
int
main (int argc, char **argv)
@@ -57,13 +61,21 @@ main (int argc, char **argv)
/* Test move constructor. */
{
- hb_map_t v {hb_map_t {}};
+ hb_map_t s {};
+ s.set (1, 2);
+ hb_map_t v (std::move (s));
+ assert (s.get_population () == 0);
+ assert (v.get_population () == 1);
}
/* Test move assignment. */
{
+ hb_map_t s {};
+ s.set (1, 2);
hb_map_t v;
- v = hb_map_t {};
+ v = std::move (s);
+ assert (s.get_population () == 0);
+ assert (v.get_population () == 1);
}
/* Test initializing from iterable. */
@@ -73,9 +85,15 @@ main (int argc, char **argv)
s.set (1, 2);
s.set (3, 4);
- hb_map_t v (s);
+ hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> v (s);
+ hb_map_t v0 (v);
+ hb_map_t v1 (s);
+ hb_map_t v2 (std::move (s));
- assert (v.get_population () == 2);
+ assert (s.get_population () == 0);
+ assert (v0.get_population () == 2);
+ assert (v1.get_population () == 2);
+ assert (v2.get_population () == 2);
}
/* Test call fini() twice. */
@@ -135,5 +153,75 @@ main (int argc, char **argv)
}
}
+ /* Test hashing maps. */
+ {
+ using pair = hb_pair_t<hb_codepoint_t, hb_codepoint_t>;
+
+ hb_hashmap_t<hb_map_t, hb_map_t, const hb_map_t *, const hb_map_t *, &invalid_map, &invalid_map> m1;
+ hb_hashmap_t<hb_map_t, hb_map_t, std::nullptr_t, std::nullptr_t, nullptr, nullptr> m2;
+
+ m1.set (hb_map_t (), hb_map_t {});
+ m2.set (hb_map_t (), hb_map_t {});
+
+ m1.set (hb_map_t (), hb_map_t {pair (1u, 2u)});
+ m2.set (hb_map_t (), hb_map_t {pair (1u, 2u)});
+
+ m1.set (hb_map_t {pair (1u, 2u)}, hb_map_t {pair (2u, 3u)});
+ m2.set (hb_map_t {pair (1u, 2u)}, hb_map_t {pair (2u, 3u)});
+
+ /* Cannot override empty map. */
+ assert (m1.get (hb_map_t ()) == hb_map_t ());
+ assert (m2.get (hb_map_t ()) == hb_map_t ());
+
+ assert (m1.get (hb_map_t {pair (1u, 2u)}) == hb_map_t {pair (2u, 3u)});
+ assert (m2.get (hb_map_t {pair (1u, 2u)}) == hb_map_t {pair (2u, 3u)});
+ }
+
+ /* Test hashing sets. */
+ {
+ hb_hashmap_t<hb_set_t, hb_set_t, const hb_set_t *, const hb_set_t *, &invalid_set, &invalid_set> m1;
+ hb_hashmap_t<hb_set_t, hb_set_t, std::nullptr_t, std::nullptr_t, nullptr, nullptr> m2;
+
+ m1.set (hb_set_t (), hb_set_t ());
+ m2.set (hb_set_t (), hb_set_t ());
+
+ m1.set (hb_set_t (), hb_set_t {1});
+ m2.set (hb_set_t (), hb_set_t {1});
+
+ m1.set (hb_set_t {1, 1000}, hb_set_t {2});
+ m2.set (hb_set_t {1, 1000}, hb_set_t {2});
+
+ /* Cannot override empty set. */
+ assert (m1.get (hb_set_t ()) == hb_set_t ());
+ assert (m2.get (hb_set_t ()) == hb_set_t ());
+
+ assert (m1.get (hb_set_t {1000, 1}) == hb_set_t {2});
+ assert (m2.get (hb_set_t {1000, 1}) == hb_set_t {2});
+ }
+
+ /* Test hashing vectors. */
+ {
+ using vector_t = hb_vector_t<unsigned>;
+
+ hb_hashmap_t<vector_t, vector_t, const vector_t *, const vector_t *, &invalid_vector, &invalid_vector> m1;
+ hb_hashmap_t<vector_t, vector_t, std::nullptr_t, std::nullptr_t, nullptr, nullptr> m2;
+
+ m1.set (vector_t (), vector_t ());
+ m2.set (vector_t (), vector_t ());
+
+ m1.set (vector_t (), vector_t {1});
+ m2.set (vector_t (), vector_t {1});
+
+ m1.set (vector_t {1}, vector_t {2});
+ m2.set (vector_t {1}, vector_t {2});
+
+ /* Cannot override empty vector. */
+ assert (m1.get (vector_t ()) == vector_t ());
+ assert (m2.get (vector_t ()) == vector_t ());
+
+ assert (m1.get (vector_t {1}) == vector_t {2});
+ assert (m2.get (vector_t {1}) == vector_t {2});
+ }
+
return 0;
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc
index fab63acb63b..e83d72c7ea1 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-priority-queue.cc
@@ -73,17 +73,9 @@ test_extract ()
assert (queue.is_empty ());
}
-static void
-test_extract_empty ()
-{
- hb_priority_queue_t queue;
- assert (queue.pop_minimum () == hb_pair (0, 0));
-}
-
int
main (int argc, char **argv)
{
test_insert ();
test_extract ();
- test_extract_empty ();
}
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc
index 3a2536a29a4..17e0d267ac2 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-repacker.cc
@@ -729,26 +729,6 @@ populate_serializer_with_split_spaces_expected_2 (hb_serialize_context_t* c)
}
static void
-populate_serializer_complex_1 (hb_serialize_context_t* c)
-{
- c->start_serialize<char> ();
-
- unsigned obj_4 = add_object ("jkl", 3, c);
- unsigned obj_3 = add_object ("ghi", 3, c);
-
- start_object ("def", 3, c);
- add_offset (obj_3, c);
- unsigned obj_2 = c->pop_pack (false);
-
- start_object ("abc", 3, c);
- add_offset (obj_2, c);
- add_offset (obj_4, c);
- c->pop_pack (false);
-
- c->end_serialize();
-}
-
-static void
populate_serializer_complex_2 (hb_serialize_context_t* c)
{
c->start_serialize<char> ();
@@ -831,68 +811,6 @@ populate_serializer_virtual_link (hb_serialize_context_t* c)
c->end_serialize();
}
-static void test_sort_kahn_1 ()
-{
- size_t buffer_size = 100;
- void* buffer = malloc (buffer_size);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_complex_1 (&c);
-
- graph_t graph (c.object_graph ());
- graph.sort_kahn ();
-
- assert(strncmp (graph.object (3).head, "abc", 3) == 0);
- assert(graph.object (3).real_links.length == 2);
- assert(graph.object (3).real_links[0].objidx == 2);
- assert(graph.object (3).real_links[1].objidx == 1);
-
- assert(strncmp (graph.object (2).head, "def", 3) == 0);
- assert(graph.object (2).real_links.length == 1);
- assert(graph.object (2).real_links[0].objidx == 0);
-
- assert(strncmp (graph.object (1).head, "jkl", 3) == 0);
- assert(graph.object (1).real_links.length == 0);
-
- assert(strncmp (graph.object (0).head, "ghi", 3) == 0);
- assert(graph.object (0).real_links.length == 0);
-
- free (buffer);
-}
-
-static void test_sort_kahn_2 ()
-{
- size_t buffer_size = 100;
- void* buffer = malloc (buffer_size);
- hb_serialize_context_t c (buffer, buffer_size);
- populate_serializer_complex_2 (&c);
-
- graph_t graph (c.object_graph ());
- graph.sort_kahn ();
-
-
- assert(strncmp (graph.object (4).head, "abc", 3) == 0);
- assert(graph.object (4).real_links.length == 3);
- assert(graph.object (4).real_links[0].objidx == 3);
- assert(graph.object (4).real_links[1].objidx == 0);
- assert(graph.object (4).real_links[2].objidx == 2);
-
- assert(strncmp (graph.object (3).head, "def", 3) == 0);
- assert(graph.object (3).real_links.length == 1);
- assert(graph.object (3).real_links[0].objidx == 1);
-
- assert(strncmp (graph.object (2).head, "mn", 2) == 0);
- assert(graph.object (2).real_links.length == 0);
-
- assert(strncmp (graph.object (1).head, "ghi", 3) == 0);
- assert(graph.object (1).real_links.length == 1);
- assert(graph.object (1).real_links[0].objidx == 0);
-
- assert(strncmp (graph.object (0).head, "jkl", 3) == 0);
- assert(graph.object (0).real_links.length == 0);
-
- free (buffer);
-}
-
static void test_sort_shortest ()
{
size_t buffer_size = 100;
@@ -1336,8 +1254,6 @@ int
main (int argc, char **argv)
{
test_serialize ();
- test_sort_kahn_1 ();
- test_sort_kahn_2 ();
test_sort_shortest ();
test_will_overflow_1 ();
test_will_overflow_2 ();
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc
index 286f1a9976c..bcff0560437 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-set.cc
@@ -42,21 +42,26 @@ main (int argc, char **argv)
/* Test copy assignment. */
{
hb_set_t v1 {1, 2};
- hb_set_t v2 = v1;
+ hb_set_t v2;
+ v2 = v1;
assert (v1.get_population () == 2);
assert (v2.get_population () == 2);
}
/* Test move constructor. */
{
- hb_set_t v {hb_set_t {1, 2}};
+ hb_set_t s {1, 2};
+ hb_set_t v (std::move (s));
+ assert (s.get_population () == 0);
assert (v.get_population () == 2);
}
/* Test move assignment. */
{
+ hb_set_t s = hb_set_t {1, 2};
hb_set_t v;
- v = hb_set_t {1, 2};
+ v = std::move (s);
+ assert (s.get_population () == 0);
assert (v.get_population () == 2);
}
@@ -67,9 +72,15 @@ main (int argc, char **argv)
s.add (18);
s.add (12);
- hb_set_t v (s);
+ hb_vector_t<hb_codepoint_t> v (s);
+ hb_set_t v0 (v);
+ hb_set_t v1 (s);
+ hb_set_t v2 (std::move (s));
- assert (v.get_population () == 2);
+ assert (s.get_population () == 0);
+ assert (v0.get_population () == 2);
+ assert (v1.get_population () == 2);
+ assert (v2.get_population () == 2);
}
/* Test initializing from iterator. */
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc
index 521f2a171d3..37bec309d0f 100644
--- a/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc
+++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/test-vector.cc
@@ -61,8 +61,12 @@ main (int argc, char **argv)
/* Test move constructor. */
{
- hb_vector_t<int> v {hb_vector_t<int> {1, 2}};
- hb_vector_t<int> V {hb_vector_t<int> {1, 2}};
+ hb_vector_t<int> s {1, 2};
+ hb_sorted_vector_t<int> S {1, 2};
+ hb_vector_t<int> v (std::move (s));
+ hb_sorted_vector_t<int> V (std::move (S));
+ assert (s.length == 0);
+ assert (S.length == 0);
assert (v.length == 2);
assert (v[0] == 1);
assert (v[1] == 2);
@@ -70,11 +74,16 @@ main (int argc, char **argv)
/* Test move assignment. */
{
+ hb_vector_t<int> s {1, 2};
+ hb_sorted_vector_t<int> S {1, 2};
hb_vector_t<int> v;
hb_sorted_vector_t<int> V;
- v = hb_vector_t<int> {1, 2};
- V = hb_sorted_vector_t<int> {1, 2};
+ v = std::move (s);
+ V = std::move (S);
+ assert (s.length == 0);
+ assert (S.length == 0);
assert (v.length == 2);
+ assert (V.length == 2);
assert (v[0] == 1);
assert (v[1] == 2);
}
@@ -137,7 +146,6 @@ main (int argc, char **argv)
assert (v2[2] == 3);
}
-#if 0
{
hb_vector_t<std::string> v;
@@ -147,8 +155,13 @@ main (int argc, char **argv)
s += "x";
v.push (s);
}
+
+ hb_vector_t<std::string> v2;
+
+ v2 = v;
+
+ v2.remove (50);
}
-#endif
return 0;
}
diff --git a/Build/source/libs/harfbuzz/version.ac b/Build/source/libs/harfbuzz/version.ac
index ef40866be78..152c15c1abe 100644
--- a/Build/source/libs/harfbuzz/version.ac
+++ b/Build/source/libs/harfbuzz/version.ac
@@ -8,4 +8,4 @@ dnl
dnl --------------------------------------------------------
dnl
dnl m4-include this file to define the current harfbuzz version
-m4_define([harfbuzz_version], [4.2.1])
+m4_define([harfbuzz_version], [4.3.0])